# EVM call (ROOTnetwork) In this document, we will talk about the parameters required to execute evm.call extrinsic ![](https://i.imgur.com/cioLQCN.png) This examples demonstrates execution of any extrinsic with fee preference i.e user wants to pay in a different asset (over XRP). As long as there is a liquidity in liquidity pool for the asset user desires to pay fees in, it will be successful. Lets consider simple extrinsic to transfer 1 ROOT token from Bob -> Alice Assets in ROOTnetwork are same as ERC20 tokens on Ethereum so ``` const ERC20_ABI = [ 'event Transfer(address indexed from, address indexed to, uint256 value)', 'event Approval(address indexed owner, address indexed spender, uint256 value)', 'function approve(address spender, uint256 amount) public returns (bool)', 'function allowance(address owner, address spender) public view returns (uint256)', 'function balanceOf(address who) public view returns (uint256)', 'function name() public view returns (string memory)', 'function symbol() public view returns (string memory)', 'function decimals() public view returns (uint8)', 'function transfer(address who, uint256 amount)', ]; ``` Encode input or calldata for transfer would be ``` let iface = new utils.Interface(ERC20_ABI); const contractAddress = feeToken.address; const transferInput = iface.encodeFunctionData("transfer", [bob.address, 1 ]); ``` >>> [transferInput]() = "0xa9059cbb000000000000000000000000e04cc55ebee1cbce552f250e85c57b70b2e2625b0000000000000000000000000000000000000000000000000000000000000001" EVM call we are intereset in executing is available at address '0x00000000000000000000000000000000000004bb'( FEE_PROXY_ADDRESS ) on ROOT network and ABI looks like ``` const FEE_PROXY_ABI = [ 'function callWithFeePreferences(address asset, uint128 maxPayment, address target, bytes input)', ]; ``` So to get encoded input or calldata for callWithFeePreferences ``` let iface1 = new utils.Interface(FEE_PROXY_ABI); const encodedInput1 = iface1.encodeFunctionData("callWithFeePreferences", ["0xccCcCccC00000464000000000000000000000000", "2000000000000000000", "0xccCcCccC00000464000000000000000000000000", "0xa9059cbb000000000000000000000000e04cc55ebee1cbce552f250e85c57b70b2e2625b0000000000000000000000000000000000000000000000000000000000000001" ]); console.log('encodedInput1:::::',encodedInput1); ``` >> encodedInput1 - 0x255a3432000000000000000000000000cccccccc000004640000000000000000000000000000000000000000000000000000000000000000000000001bc16d674ec80000000000000000000000000000cccccccc0000046400000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000044a9059cbb000000000000000000000000e04cc55ebee1cbce552f250e85c57b70b2e2625b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000 Here asset - "0xccCcCccC00000464000000000000000000000000" is the root asset id(1124) converted to ERC20ContractAddress ``` const assetIdToERC20ContractAddress = (assetId) => { const asset_id_hex = (+assetId).toString(16).padStart(8, '0'); return web3.utils.toChecksumAddress(`0xCCCCCCCC${asset_id_hex}000000000000000000000000`); } ``` This is the asset id we are willing to pay fees in. and input bytes is from [transferInput]() Now back to evm.call ![](https://i.imgur.com/cioLQCN.png) Source - Sender executing the extrinsic Target - Contract on EVM (in our case FEE_PROXY_ADDRESS - "0x00000000000000000000000000000000000004bb" ) Input - [encodedInput1]() gasLimit - estimated gas required ``` const gas = await feeProxy.connect(aliceSigner).estimateGas .callWithFeePreferences(feeToken.address, maxFeePaymentInToken, contractAddress, transferInput); console.log('estimated gas used by tx:', gas.toNumber()); ``` maxFeePerGas - estimated gas price