From 72bd242ccb5cb6048dbc0cf8200d1648e13c7c20 Mon Sep 17 00:00:00 2001 From: Nick DeLuca Date: Wed, 25 Sep 2024 13:34:22 +0000 Subject: [PATCH] test: Fill message call and static call examples This increases coverage of calling by contract through call and static call --- tests/e2e-evm/test/abi_basic.test.ts | 141 ++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 3 deletions(-) diff --git a/tests/e2e-evm/test/abi_basic.test.ts b/tests/e2e-evm/test/abi_basic.test.ts index 38efb461a..02094fc06 100644 --- a/tests/e2e-evm/test/abi_basic.test.ts +++ b/tests/e2e-evm/test/abi_basic.test.ts @@ -403,9 +403,25 @@ describe("ABI_BasicTests", function () { expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; let expectedBalance = startingBalance; - if (fallbackFunction && fallbackFunction.stateMutability === "payable") { - expectedBalance = startingBalance + txData.value; - } + const balance = await publicClient.getBalance({ address: ctx.address }); + expect(balance).to.equal(expectedBalance); + }); + + it("can not receive plain transfers via message call", async function () { + const data = encodeFunctionData({ + abi: caller.abi, + functionName: "functionCall", + args: [ctx.address, "0x"], + }); + const txData = { to: caller.address, data: data, gas: contractCallerGas, value: 1n}; + const startingBalance = await publicClient.getBalance({ address: ctx.address }); + + const txHash = await walletClient.sendTransaction(txData); + const txReceipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + expect(txReceipt.status).to.equal("reverted"); + expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; + + let expectedBalance = startingBalance; const balance = await publicClient.getBalance({ address: ctx.address }); expect(balance).to.equal(expectedBalance); }); @@ -425,6 +441,25 @@ describe("ABI_BasicTests", function () { const balance = await publicClient.getBalance({ address: ctx.address }); expect(balance).to.equal(expectedBalance); }); + + it("can plain transfers via message call", async function () { + const data = encodeFunctionData({ + abi: caller.abi, + functionName: "functionCall", + args: [ctx.address, "0x"], + }); + const txData = { to: caller.address, data: data, gas: contractCallerGas, value: 1n}; + const startingBalance = await publicClient.getBalance({ address: ctx.address }); + + const txHash = await walletClient.sendTransaction(txData); + const txReceipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + expect(txReceipt.status).to.equal("success"); + expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; + + const expectedBalance = startingBalance + txData.value; + const balance = await publicClient.getBalance({ address: ctx.address }); + expect(balance).to.equal(expectedBalance); + }); } it(`can ${fallbackFunction ? "" : "not "}be called with a non-matching function selector`, async function () { @@ -437,6 +472,34 @@ describe("ABI_BasicTests", function () { expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; }); + it(`can ${fallbackFunction ? "" : "not "}be called with a non-matching function selector via message call`, async function () { + const data = encodeFunctionData({ + abi: caller.abi, + functionName: "functionCall", + args: [ctx.address, toFunctionSelector("does_not_exist()")], + }); + const txData = { to: caller.address, data: data, gas: contractCallerGas}; + + const txHash = await walletClient.sendTransaction(txData); + const txReceipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + expect(txReceipt.status).to.equal(fallbackFunction ? "success" : "reverted"); + expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; + }); + + it(`can ${fallbackFunction ? "" : "not "}be called with a non-matching function selector via static call`, async function () { + const data = encodeFunctionData({ + abi: caller.abi, + functionName: "functionStaticCall", + args: [ctx.address, toFunctionSelector("does_not_exist()")], + }); + const txData = { to: caller.address, data: data, gas: contractCallerGas}; + + const txHash = await walletClient.sendTransaction(txData); + const txReceipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + expect(txReceipt.status).to.equal(fallbackFunction ? "success" : "reverted"); + expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; + }); + it(`can ${fallbackFunction ? "" : "not "}be called with an invalid (short) function selector`, async function () { const data: Hex = "0x010203"; const txData = { to: ctx.address, data: data, gas: defaultGas }; @@ -447,6 +510,34 @@ describe("ABI_BasicTests", function () { expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; }); + it(`can ${fallbackFunction ? "" : "not "}be called with an invalid (short) via message call`, async function () { + const data = encodeFunctionData({ + abi: caller.abi, + functionName: "functionCall", + args: [ctx.address, "0x010203"], + }); + const txData = { to: caller.address, data: data, gas: contractCallerGas}; + + const txHash = await walletClient.sendTransaction(txData); + const txReceipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + expect(txReceipt.status).to.equal(fallbackFunction ? "success" : "reverted"); + expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; + }); + + it(`can ${fallbackFunction ? "" : "not "}be called with an invalid (short) via static call`, async function () { + const data = encodeFunctionData({ + abi: caller.abi, + functionName: "functionStaticCall", + args: [ctx.address, "0x010203"], + }); + const txData = { to: caller.address, data: data, gas: contractCallerGas}; + + const txHash = await walletClient.sendTransaction(txData); + const txReceipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + expect(txReceipt.status).to.equal(fallbackFunction ? "success" : "reverted"); + expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; + }); + if (fallbackFunction) { it(`can ${fallbackFunction.stateMutability === "payable" ? "" : "not "}receive value with a non-matching function selector`, async function () { const data = toFunctionSelector("does_not_exist()"); @@ -466,6 +557,28 @@ describe("ABI_BasicTests", function () { expect(balance).to.equal(expectedBalance); }); + it(`can ${fallbackFunction.stateMutability === "payable" ? "" : "not "}receive value with a non-matching function selector via message call`, async function () { + const data = encodeFunctionData({ + abi: caller.abi, + functionName: "functionCall", + args: [ctx.address, toFunctionSelector("does_not_exist()")], + }); + const txData = { to: caller.address, data: data, gas: contractCallerGas, value: 1n}; + const startingBalance = await publicClient.getBalance({ address: ctx.address }); + + const txHash = await walletClient.sendTransaction(txData); + const txReceipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + expect(txReceipt.status).to.equal(fallbackFunction.stateMutability === "payable" ? "success" : "reverted"); + expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; + + let expectedBalance = startingBalance; + if (fallbackFunction.stateMutability === "payable") { + expectedBalance = startingBalance + txData.value; + } + const balance = await publicClient.getBalance({ address: ctx.address }); + expect(balance).to.equal(expectedBalance); + }); + it(`can ${fallbackFunction.stateMutability === "payable" ? "" : "not "}recieve value with an invalid function selector`, async function () { const data: Hex = "0x010203"; const txData = { to: ctx.address, data: data, gas: defaultGas, value: 1n }; @@ -483,6 +596,28 @@ describe("ABI_BasicTests", function () { const balance = await publicClient.getBalance({ address: ctx.address }); expect(balance).to.equal(expectedBalance); }); + + it(`can ${fallbackFunction.stateMutability === "payable" ? "" : "not "}recieve value with an invalid function selector via message call`, async function () { + const data = encodeFunctionData({ + abi: caller.abi, + functionName: "functionCall", + args: [ctx.address, "0x010203"], + }); + const txData = { to: caller.address, data: data, gas: contractCallerGas, value: 1n}; + const startingBalance = await publicClient.getBalance({ address: ctx.address }); + + const txHash = await walletClient.sendTransaction(txData); + const txReceipt = await publicClient.waitForTransactionReceipt({ hash: txHash }); + expect(txReceipt.status).to.equal(fallbackFunction.stateMutability === "payable" ? "success" : "reverted"); + expect(txReceipt.gasUsed < txData.gas, "gas to not be exhausted").to.be.true; + + let expectedBalance = startingBalance; + if (fallbackFunction.stateMutability === "payable") { + expectedBalance = startingBalance + txData.value; + } + const balance = await publicClient.getBalance({ address: ctx.address }); + expect(balance).to.equal(expectedBalance); + }); } }); }