Skip to content

Commit

Permalink
test(transfer): adds new and re-organises existing tests
Browse files Browse the repository at this point in the history
Current 2 tests are failing for reasons that are acceptable (type is `0` and not `2`), but Ethereum-compatible. So making sure the transactions are type `2` instead of `0` is a "nice to have".

There is a nonce related bug that only occurs when I run the entire test suite. Otherwise, the test doesn't fail. It's a flakey test.
  • Loading branch information
arthurgousset committed Apr 22, 2024
1 parent fd0c0d0 commit 80568be
Showing 1 changed file with 79 additions and 85 deletions.
164 changes: 79 additions & 85 deletions tests/transfers.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import { test, expect, describe } from "@jest/globals";
import { getSigner, getTransactionByHash, MINIMAL_USDC_ABI } from "./common";
import {
BLOCK_TIME,
TxTypeNumber,
USDC_ADAPTER_ALFAJORES_ADDRESS,
USDC_ALFAJORES_ADDRESS,
} from "./consts";
import { BLOCK_TIME, USDC_ADAPTER_ALFAJORES_ADDRESS, USDC_ALFAJORES_ADDRESS } from "./consts";
import { Contract } from "ethers";
import { TxTypeToPrefix } from "../src/lib/transactions";

const signer = getSigner();
const usdc = new Contract(USDC_ALFAJORES_ADDRESS, MINIMAL_USDC_ABI, signer);

describe("[setup] supplied wallet has sufficient tokens to run tests", () => {
test(
"more than 1 CELO",
"has more than 1 CELO",
async () => {
const balanceInWei = await signer.provider?.getBalance(signer.address);
expect(balanceInWei).not.toBeUndefined();
Expand All @@ -24,7 +20,7 @@ describe("[setup] supplied wallet has sufficient tokens to run tests", () => {
);

test(
"more than 1 USDC",
"has more than 1 USDC",
async () => {
const balanceInWei = await usdc.balanceOf(signer.address);
expect(balanceInWei).not.toBeUndefined();
Expand All @@ -35,23 +31,28 @@ describe("[setup] supplied wallet has sufficient tokens to run tests", () => {
);
});

/**
* Tests that ensure Celo Legacy transactions and CIP42 transactions are
* fully deprecated.
*
* TODO(Arthur): clean up this message before merging.
*
* Default logic:
*
* 1. When sending transaction with gas in CELO then ethCompatible is true
* 2. When sending transaction with fee currency not CELO then type is 123 (CIP64)
*
* Should TS complain that maxFeePerGas etc is not defined, or that feeCurrency is not
* permitted without it?
*/
describe("[ETH compatible] when sending transactions with gas in CELO, then the transaction is an Ethereum-compatible type (ethCompatible = true)", () => {
describe("[ethereum-compatibility] when sending a transaction with gas in CELO, then the transaction is always Ethereum-compatible", () => {
test(
"normal transfer",
"can transfer CELO with CELO as gas",
async () => {
const txResponse = await signer.sendTransaction({
to: signer.address,
value: BigInt(1),
maxFeePerGas: BigInt(10e9) * BigInt(2) + BigInt(10e9), // ( base fee * 2 ) + tip
maxPriorityFeePerGas: BigInt(10e9),
});
const txReceipt = await txResponse.wait();
expect(txReceipt).not.toBeNull();
const jsonRpcResponse = await getTransactionByHash(txReceipt!.hash);

expect(jsonRpcResponse?.result.ethCompatible).toBe(true); // transaction is ethereum-compatible
expect(txReceipt?.type).toEqual(TxTypeToPrefix.eip1559); // transaction is EIP1559
expect(txReceipt?.hash).toMatch(/0x.{40}/); // transaction is successful
},
BLOCK_TIME * 3
);
test(
"can transfer CELO with CELO as gas, and estimate gas parameters",
async () => {
const txResponse = await signer.sendTransaction({
to: signer.address,
Expand All @@ -60,90 +61,83 @@ describe("[ETH compatible] when sending transactions with gas in CELO, then the
const txReceipt = await txResponse.wait();
expect(txReceipt).not.toBeNull();
const jsonRpcResponse = await getTransactionByHash(txReceipt!.hash);
expect(jsonRpcResponse?.result.ethCompatible).toBe(true);

expect(jsonRpcResponse?.result.ethCompatible).toBe(true); // transaction is ethereum-compatible
expect(txReceipt?.type).toEqual(TxTypeToPrefix.eip1559); // transaction is EIP-1559
expect(txReceipt?.hash).toMatch(/0x.{40}/); // transaction is successful
},
BLOCK_TIME * 3
);

test("ERC20 transfer", async () => {
const txResponse = await usdc.transfer(signer.address, 1n);
const txReceipt = await txResponse.wait();
expect(txReceipt).not.toBeNull();
const jsonRpcResponse = await getTransactionByHash(txReceipt!.hash);
expect(jsonRpcResponse?.result.ethCompatible).toBe(true);
});
});

describe("when sending transactions with gas in fee currency, then the transaction is always CIP-64", () => {
test("normal transfer with USDC as gas", async () => {
const txResponse = await signer.sendTransaction({
to: signer.address,
value: 1n,
feeCurrency: USDC_ADAPTER_ALFAJORES_ADDRESS,
});
const txReceipt = await txResponse.wait();
/**
* At the moment,
*/
// When feeCurrency is specified, but `gasLimit`, `maxFeePerGas`, and `maxPriorityFeePerGas`
// are not specified, then the fee currency field is dropped and a normal Ethereum type 0
// transaction is built.
// Should TypeScript complain here? That might make it easier for devs to avoid
// making type 0 transactions by mistake.
expect(txReceipt?.type).toEqual(TxTypeNumber.ETHEREUM_LEGACY);
});
test(
"can transfer USDC with CELO as gas",
async () => {
const txResponse = await usdc.transfer(signer.address, 1n);
const txReceipt = await txResponse.wait();
expect(txReceipt).not.toBeNull();
const jsonRpcResponse = await getTransactionByHash(txReceipt!.hash);

test("normal transfer with USDC as gas, and gasLimit, maxFeePerGas, and maxPriorityFeePerGas", async () => {
const txResponse = await signer.sendTransaction({
to: signer.address,
value: 1n,
gasLimit: 100_000n,
maxFeePerGas: BigInt(10e9), // gwei
maxPriorityFeePerGas: BigInt(10e9), // gwei
feeCurrency: USDC_ADAPTER_ALFAJORES_ADDRESS,
});
const txReceipt = await txResponse.wait();
expect(txReceipt?.type).toEqual(TxTypeNumber.CIP64);
});
expect(jsonRpcResponse?.result.ethCompatible).toBe(true); // transaction is ethereum-compatible
expect(txReceipt?.type).toEqual(TxTypeToPrefix.eip1559); // transaction is EIP-1559
expect(txReceipt?.hash).toMatch(/0x.{40}/); // transaction is successful
},
BLOCK_TIME * 3
);
});

describe("[cip-64]", () => {
describe("[fee currency support] when sending transactions with gas in fee currency, then the transaction is always CIP-64", () => {
test(
"can transfer CELO with USDC as feeCurrency",
"can transfer CELO with USDC as gas",
async () => {
const txResponse = await signer.sendTransaction({
to: signer.address,
value: 1n,
feeCurrency: USDC_ADAPTER_ALFAJORES_ADDRESS, // TODO(Arthur): Replace with USDC
maxFeePerGas: 5000000000n,
maxPriorityFeePerGas: 5000000000n,
value: BigInt(1),
gasLimit: BigInt(1e5),
maxFeePerGas: BigInt(5e9) * BigInt(2) + BigInt(1e9), // ( base fee * 2 ) + tip
maxPriorityFeePerGas: BigInt(1e9),
feeCurrency: USDC_ADAPTER_ALFAJORES_ADDRESS,
});
const txReceipt = await txResponse.wait();
expect(txReceipt?.hash).toMatch(/0x.{40}/);

expect(txReceipt?.type).toEqual(TxTypeToPrefix.cip64); // transaction is CIP64
expect(txReceipt?.hash).toMatch(/0x.{40}/); // transaction is successful
},
BLOCK_TIME * 3
);
test("can transfer USDC with USDC as feeCurrency", async () => {
/**
* TODO(Arthur): This test is incomplete. At the moment, it doesn't
* make the ERC-20 transfer with USDC as a fee currency.
*/
const txResponse = await usdc.transfer(signer.address, 1n);
const txReceipt = await txResponse.wait();
expect(txReceipt?.hash).toMatch(/0x.{40}/);
});
});
describe("[eip-1559]", () => {
test(
"can transfer CELO with CELO as gas",
"can transfer CELO with USDC as gas, and estimate gas parameters",
async () => {
const txResponse = await signer.sendTransaction({
to: signer.address,
value: 1n,
maxFeePerGas: 5000000000n,
maxPriorityFeePerGas: 5000000000n,
feeCurrency: USDC_ADAPTER_ALFAJORES_ADDRESS,
});
const txReceipt = await txResponse.wait();

expect(txReceipt?.type).toEqual(TxTypeToPrefix.cip64); // transaction is CIP64
expect(txReceipt?.hash).toMatch(/0x.{40}/); // transaction is successful
},
BLOCK_TIME * 3
);
test(
"can transfer USDC with USDC as gas, and estimate gas parameters",
async () => {
const transferBaseTx = await usdc.transfer.populateTransaction(signer.address, 1n);
const txReceipt = await signer.sendTransaction({
...transferBaseTx,
feeCurrency: USDC_ADAPTER_ALFAJORES_ADDRESS,
});
/**
* For future reference: Unfortunately, it's acknowledged that this
* short-hand form is not currently supported in the celo-ethers-wrapper:
*
* ```ts
* usdc.transfer(signer.address, 1n, {
* feeCurrency: USDC_ADAPTER_ALFAJORES_ADDRESS
* });
* ```
*/
expect(txReceipt?.type).toEqual(TxTypeToPrefix.cip64);
expect(txReceipt?.hash).toMatch(/0x.{40}/);
},
BLOCK_TIME * 3
Expand Down

0 comments on commit 80568be

Please sign in to comment.