Skip to content

Commit

Permalink
Add test for feeProxy with evm call using pallet (#636)
Browse files Browse the repository at this point in the history
* Add test for feeProxy with evm call using pallet
  • Loading branch information
KarishmaBothara authored Jul 4, 2023
1 parent d40cc05 commit f991c52
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 2 deletions.
1 change: 1 addition & 0 deletions .github/workflows/image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ on:
- "**.lock"
- "genesis/**"
- "Dockerfile"
- "**.ts"

env:
REGISTRY: "ghcr.io"
Expand Down
143 changes: 142 additions & 1 deletion e2e/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,148 @@ import web3 from "web3";
export * from "./node";

/** TYPEDEFS */

export const rpcs = {
dex: {
quote: {
description: "Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset",
params: [
{
name: "amountA",
type: "u128",
},
{
name: "reserveA",
type: "u128",
},
{
name: "reserveB",
type: "u128",
},
],
type: "Json",
},
getAmountsOut: {
description: "Given an array of AssetIds, return amounts out for an amount in",
params: [
{
name: "amountIn",
type: "Balance",
},
{
name: "path",
type: "Vec<AssetId>",
},
],
type: "Json",
},
getAmountsIn: {
description: "Given an array of AssetIds, return amounts in for an amount out",
params: [
{
name: "amountOut",
type: "Balance",
},
{
name: "path",
type: "Vec<AssetId>",
},
],
type: "Json",
},
getLPTokenID: {
description: "Given two AssetIds, return liquidity token created for the pair",
params: [
{
name: "assetA",
type: "AssetId",
},
{
name: "assetB",
type: "AssetId",
},
],
type: "Json",
},
getLiquidity: {
description: "Given two AssetIds, return liquidity",
params: [
{
name: "assetA",
type: "AssetId",
},
{
name: "assetB",
type: "AssetId",
},
],
type: "Json",
},
getTradingPairStatus: {
description: "Given two AssetIds, return whether trading pair is enabled or disabled",
params: [
{
name: "assetA",
type: "AssetId",
},
{
name: "assetB",
type: "AssetId",
},
],
type: "Text",
},
},
ethy: {
getEventProof: {
description: "Get ETH event proof for event Id",
params: [
{
name: "eventId",
type: "EventProofId",
},
],
type: "Option<EthEventProofResponse>",
},
getXrplTxProof: {
description: "Get XRPL event proof for event Id",
params: [
{
name: "eventId",
type: "EventProofId",
},
],
type: "Option<XrplEventProofResponse>",
},
},
nft: {
ownedTokens: {
description: "Get all NFTs owned by an account",
params: [
{
name: "collectionId",
type: "CollectionUuid",
},
{
name: "who",
type: "AccountId",
},
{ name: "cursor", type: "SerialNumber" },
{ name: "limit", type: "u16" },
],
type: "Json",
},
tokenUri: {
description: "Get the URI of a token",
params: [
{
name: "tokenId",
type: "TokenId",
},
],
type: "Json",
},
},
};
export const typedefs = {
AccountId: "EthereumAccountId",
AccountId20: "EthereumAccountId",
Expand Down
75 changes: 74 additions & 1 deletion e2e/test/FeePreferences/FeePreferences.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { JsonRpcProvider } from "@ethersproject/providers";
import { ApiPromise, Keyring, WsProvider } from "@polkadot/api";
import { KeyringPair } from "@polkadot/keyring/types";
import { Codec, IEventData } from "@polkadot/types/types";
import { hexToU8a } from "@polkadot/util";
import { expect } from "chai";
import { BigNumber, Contract, Wallet, utils } from "ethers";
Expand All @@ -19,6 +20,7 @@ import {
NATIVE_TOKEN_ID,
NodeProcess,
assetIdToERC20ContractAddress,
rpcs,
startNode,
typedefs,
} from "../../common";
Expand Down Expand Up @@ -46,7 +48,7 @@ describe("Fee Preferences", function () {

// Setup PolkadotJS rpc provider
const wsProvider = new WsProvider(`ws://localhost:${node.wsPort}`);
api = await ApiPromise.create({ provider: wsProvider, types: typedefs });
api = await ApiPromise.create({ provider: wsProvider, types: typedefs, rpc: rpcs });
const keyring = new Keyring({ type: "ethereum" });
alith = keyring.addFromSeed(hexToU8a(ALITH_PRIVATE_KEY));
bob = keyring.addFromSeed(hexToU8a(BOB_PRIVATE_KEY));
Expand Down Expand Up @@ -558,6 +560,77 @@ describe("Fee Preferences", function () {
expect(error.code).to.be.eq("INSUFFICIENT_FUNDS");
expect(error.reason).to.be.eq("insufficient funds for intrinsic transaction cost");
});

it("Pays fees in non-native token with extrinsic - check maxPayment works fine", async () => {
const erc20PrecompileAddress = assetIdToERC20ContractAddress(FEE_TOKEN_ASSET_ID);
const sender = alith.address;
const value = 0; //eth
const gasLimit = 22953;
const maxFeePerGas = "15000000000000";
const maxPriorityFeePerGas = null;
const nonce = null;
const accessList = null;
const transferAmount = 1;
const iface = new utils.Interface(ERC20_ABI);
const encodedInput = iface.encodeFunctionData("transfer", [bob.address, transferAmount]);

const evmCall = api.tx.evm.call(
sender,
erc20PrecompileAddress,
encodedInput,
value,
gasLimit,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
accessList,
);

// Find estimate cost for evm call
const evmCallGasEstimate = await evmCall.paymentInfo(sender);
const evmCallGasEstimateinXRP = evmCallGasEstimate.partialFee;

// Find estimate cost for feeProxy call
const extrinsicInfo = await api.tx.feeProxy
.callWithFeePreferences(
FEE_TOKEN_ASSET_ID,
utils.parseEther("1").toString(), // 10e18
api.createType("Call", evmCall).toHex(),
)
.paymentInfo(sender);
const feeProxyGasEstimateinXRP = extrinsicInfo.partialFee;

// cost for evm call + cost for fee proxy
const estimatedTotalGasCost = evmCallGasEstimateinXRP.toNumber() + feeProxyGasEstimateinXRP.toNumber();

const {
Ok: [estimatedTokenTxCost],
} = await (api.rpc as any).dex.getAmountsIn(estimatedTotalGasCost, [FEE_TOKEN_ASSET_ID, GAS_TOKEN_ID]);

const eventData = await new Promise<Codec[] & IEventData>((resolve, reject) => {
return api.tx.feeProxy
.callWithFeePreferences(
FEE_TOKEN_ASSET_ID,
estimatedTokenTxCost.toString(),
api.createType("Call", evmCall).toHex(),
)
.signAndSend(alith, ({ events, status }) => {
if (status.isInBlock) {
for (const { event } of events) {
if (event.section === "feeProxy" && event.method === "CallWithFeePreferences") {
resolve(event.data);
}
}
reject(null);
}
});
expect(eventData).to.exist;
const [from, paymentAsset, maxPayment] = eventData;
expect(paymentAsset.toString()).to.equal(FEE_TOKEN_ASSET_ID.toString());
expect(from.toString()).to.equal(alith.address.toString());
expect(maxPayment.toString()).to.equal(estimatedTokenTxCost.toString());
});
});
});

async function getAmountIn(provider: JsonRpcProvider, estimate: BigNumber, feeTokenAssetId: number): Promise<number> {
Expand Down

0 comments on commit f991c52

Please sign in to comment.