Skip to content

FeeProxy (EVM example) ​

Pay the gas for an ERC-20 transfer in a token other than XRP. Reference: FeeProxy precompile.

Copied from Futureverse’s futureversecom/trn-examples, deleted with its GitHub organisation, at commit 44c9e16 of 2024-10-31. Apache-2.0: license. Before you run it, read Running the examples.

Offline destinations

Some places this page points to did not answer when last checked:

  • docs-beta.therootnetwork.com — does not resolve (checked 2026-10-18)
  • stackblitz.com/github/futureversecom — StackBlitz loads these projects from the deleted futureversecom organisation on GitHub (checked 2026-10-18)

Run in StackBlitz (repository deleted, checked 2026-10-18) · Precompile Documentation (offline, checked 2026-10-18)

IMPORTANT

Ensure the following ENV vars are available before running the examples

Examples ​

bash
# change your working directory to this example first
cd examples/evm/use-feeProxy

# export all required environments
export CALLER_PRIVATE_KEY=

# `feeProxy.callWithFeePreferences` that wraps around `ERC20.transfer`
pnpm call:callERC20Transfer

Source files ​

src/callERC20Transfer.ts ​

ts
import { ERC20_ABI } from "@therootnetwork/evm";
import { ALICE } from "@trne/utils/accounts";
import { filterTransactionEvents } from "@trne/utils/filterTransactionEvents";
import { getERC20Contract } from "@trne/utils/getERC20Contract";
import { getFeeProxyContract } from "@trne/utils/getFeeProxyContract";
import { getFeeProxyPricePair } from "@trne/utils/getFeeProxyPricePair";
import { ASTO_ASSET_ID, SYLO_ASSET_ID } from "@trne/utils/porcini-assets";
import { withEthersProvider } from "@trne/utils/withEthersProvider";
import { ContractReceipt, utils } from "ethers";

/**
 * Use `feeProxy.callWithFeePreferences` to trigger a `transfer` call of SYLO token, and pay gas
 * in ASTO token.
 *
 * Assumes the caller has ASTO balance to pay for gas and SYLO balance to demonstrate
 * the transfer
 */
withEthersProvider("porcini", async (provider, wallet, logger) => {
	// contracts creation
	const feeProxy = getFeeProxyContract().connect(wallet);
	const sylo = getERC20Contract(SYLO_ASSET_ID).connect(wallet);
	const asto = getERC20Contract(ASTO_ASSET_ID).connect(wallet);

	// transfer call
	const transferAmount = utils.parseUnits("0.1", 18); // 1 SYLO
	const transferInput = new utils.Interface(ERC20_ABI).encodeFunctionData("transfer", [
		ALICE,
		transferAmount,
	]);
	const transferEstimate = await sylo.estimateGas.transfer(ALICE, transferAmount);

	logger.info(
		{
			parameters: {
				destination: ALICE,
				amount: transferAmount,
			},
		},
		`create a transfer call`
	);

	// retrieve the maxPayment and maxFeePerGas parameters with slippage to be 0.05 (5%)
	const { maxPayment, maxFeePerGas } = await getFeeProxyPricePair(
		provider,
		transferEstimate,
		ASTO_ASSET_ID,
		0.05
	);

	logger.info(`dispatch transaction from wallet=${wallet.address}`);
	const tx = await feeProxy.callWithFeePreferences(
		asto.address,
		maxPayment,
		sylo.address,
		transferInput,
		{
			gasLimit: transferEstimate,
			maxFeePerGas: maxFeePerGas,
			maxPriorityFeePerGas: 0,
		}
	);

	const receipt = (await tx.wait()) as unknown as ContractReceipt;

	const [transferEvent] = filterTransactionEvents(ERC20_ABI, receipt.logs, ["Transfer"]);

	logger.info(
		{
			result: {
				transactionHash: receipt.transactionHash,
				blockNumber: receipt.blockNumber,
				transferEvent: {
					name: transferEvent.name,
					args: transferEvent.args,
				},
			},
		},
		"receive result"
	);
});

package.json ​

json
{
  "scripts": {
    "call": "tsx --tsconfig ../../../tsconfig.json",
    "call:callERC20Transfer": "pnpm call src/callERC20Transfer.ts"
  }
}
Source: futureversecom/trn-examples, examples/evm/use-feeProxy (deleted) · commit 44c9e16, 2024-10-31 · Apache-2.0, license · part of Code examples

Curated independently. Source-attributed reference for The Root Network. Not affiliated with Futureverse / TRN Labs.