Skip to content

Commit

Permalink
fix: Use separate shouldRun fn signatures for fallback tests
Browse files Browse the repository at this point in the history
Fallback tests are not run on each function but rather only for the specific fallback.
This means whether or not to run the test is determined by only the receive and fallback
functions, without any other ABI function.
  • Loading branch information
drklee3 committed Oct 8, 2024
1 parent 5737b3b commit b184907
Showing 1 changed file with 50 additions and 45 deletions.
95 changes: 50 additions & 45 deletions tests/e2e-evm/test/abi_basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,22 +134,11 @@ describe("ABI_BasicTests", function () {
caller: Address;
}

// ShouldRunFn is a function that determines if a test case should be run on a
// specific function. This is useful if you only want to run a test case on
// specific functions.
type ShouldRunFn = (
fn: AbiFunction,
receiveFunction: AbiReceive | undefined,
fallbackFunction: AbiFallback | undefined,
) => boolean;

// AbiFunctionTestCaseBase defines a test case for an ABI function, this is run
// on EVERY function defined in an expected ABI. Use shouldRun to only run the
// test case on matching functions.
// AbiFunctionTestCaseBase defines a test case for an ABI function, this is
// run on every function defined in an expected ABI. Use shouldRun to only run
// the test case on matching functions.
interface AbiFunctionTestCaseBase {
name: string;
// If defined, only run this test case on functions that return true
shouldRun?: ShouldRunFn;
expectedStatus: "success" | "reverted";
// If defined, check the balance of the contract after the transaction
expectedBalance?: (startingBalance: bigint) => bigint;
Expand All @@ -158,16 +147,27 @@ describe("ABI_BasicTests", function () {
// AbiFunctionTestCase is a test case for a specific function in an ABI that
// includes the function selector.
type AbiFunctionTestCase = AbiFunctionTestCaseBase & {
// If defined, only run this test case on functions that return true. This
// is useful for testing specific function types.
shouldRun?: (
fn: AbiFunction,
receiveFunction: AbiReceive | undefined,
fallbackFunction: AbiFallback | undefined,
) => boolean;
txParams: (ctx: AbiContext, funcSelector: `0x${string}`) => CallParameters<Chain>;
};

// AbiFallbackTestCase is a test case for the fallback function, which does
// not use a function selector.
type AbiFallbackTestCase = AbiFunctionTestCaseBase & {
// Same as the shouldRun function for AbiFunctionTestCase, but without a
// specific ABIFunction.
shouldRun?: (receiveFunction: AbiReceive | undefined, fallbackFunction: AbiFallback | undefined) => boolean;
// No function selector for fallback
txParams: (ctx: AbiContext) => CallParameters<Chain>;
};

// Define test cases for ABI function compliance
const abiFunctionTestCases: AbiFunctionTestCase[] = [
{
name: "can be called",
Expand Down Expand Up @@ -361,20 +361,20 @@ describe("ABI_BasicTests", function () {
},
];

// Test cases for special functions, receive and fallback
// Define test cases for special functions, receive and fallback
const specialFunctionTests: AbiFallbackTestCase[] = [
// Has receive function OR payable fallback
{
name: "can receive zero value transfers with no data",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!receiveFunction || !!fallbackFunction;
},
txParams: (ctx) => ({ to: ctx.address, gas: defaultGas }),
expectedStatus: "success",
},
{
name: "can be called by another contract with no data",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!receiveFunction || !!fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -390,7 +390,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can be called by static call with no data",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!receiveFunction || !!fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -408,15 +408,15 @@ describe("ABI_BasicTests", function () {
// No receive function AND no payable fallback
{
name: "can not receive zero value transfers with no data",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !receiveFunction && !fallbackFunction;
},
txParams: (ctx) => ({ to: ctx.address, gas: defaultGas }),
expectedStatus: "reverted",
},
{
name: "can not receive zero value transfers by high level contract call with no data",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !receiveFunction && !fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -432,7 +432,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not receive zero value transfers by static call with no data",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !receiveFunction && !fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -450,7 +450,7 @@ describe("ABI_BasicTests", function () {
// No receive function AND no payable fallback
{
name: "can not receive plain transfers",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
// No receive function and no payable fallback
return !receiveFunction && (!fallbackFunction || fallbackFunction.stateMutability !== "payable");
},
Expand All @@ -459,7 +459,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not receive plain transfers via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
// No receive function and no payable fallback
return !receiveFunction && (!fallbackFunction || fallbackFunction.stateMutability !== "payable");
},
Expand All @@ -478,7 +478,7 @@ describe("ABI_BasicTests", function () {
// Has receive function OR payable fallback
{
name: "can receive plain transfers",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
// Has receive function OR payable fallback
return !!receiveFunction || (!!fallbackFunction && fallbackFunction.stateMutability === "payable");
},
Expand All @@ -487,7 +487,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can receive plain transfers via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
// Has receive function OR payable fallback
return !!receiveFunction || (!!fallbackFunction && fallbackFunction.stateMutability === "payable");
},
Expand All @@ -506,7 +506,7 @@ describe("ABI_BasicTests", function () {

{
name: "can be called with a non-matching function selector",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -518,7 +518,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not be called with a non-matching function selector",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -531,7 +531,7 @@ describe("ABI_BasicTests", function () {

{
name: "can be called with a non-matching function selector via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -547,7 +547,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not be called with a non-matching function selector via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -564,7 +564,7 @@ describe("ABI_BasicTests", function () {

{
name: "can be called with a non-matching function selector via static call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -580,7 +580,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not be called with a non-matching function selector via static call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -597,7 +597,7 @@ describe("ABI_BasicTests", function () {

{
name: "can be called with an invalid (short) function selector",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -609,7 +609,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not be called with an invalid (short) function selector",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -622,7 +622,7 @@ describe("ABI_BasicTests", function () {

{
name: "can be called with an invalid (short) function selector via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -638,7 +638,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not be called with an invalid (short) function selector via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -655,7 +655,7 @@ describe("ABI_BasicTests", function () {

{
name: "can be called with an invalid (short) function selector via static call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -671,7 +671,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not be called with an invalid (short) function selector via static call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !fallbackFunction;
},
txParams: (ctx) => ({
Expand All @@ -689,7 +689,7 @@ describe("ABI_BasicTests", function () {
// Fallback payable tests
{
name: "can receive value with a non-matching function selector",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction && fallbackFunction.stateMutability === "payable";
},
txParams: (ctx) => ({
Expand All @@ -703,7 +703,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not receive value with a non-matching function selector",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction && fallbackFunction.stateMutability !== "payable";
},
txParams: (ctx) => ({
Expand All @@ -718,7 +718,7 @@ describe("ABI_BasicTests", function () {

{
name: "can receive value with a non-matching function selector via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction && fallbackFunction.stateMutability === "payable";
},
txParams: (ctx) => ({
Expand All @@ -736,7 +736,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not receive value with a non-matching function selector via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction && fallbackFunction.stateMutability !== "payable";
},
txParams: (ctx) => ({
Expand All @@ -755,7 +755,7 @@ describe("ABI_BasicTests", function () {

{
name: "can receive value with an invalid (short) function selector",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction && fallbackFunction.stateMutability === "payable";
},
txParams: (ctx) => ({
Expand All @@ -769,7 +769,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not receive value with an invalid (short) function selector",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction && fallbackFunction.stateMutability !== "payable";
},
txParams: (ctx) => ({
Expand All @@ -784,7 +784,7 @@ describe("ABI_BasicTests", function () {

{
name: "can receive value with an invalid (short) function selector via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction && fallbackFunction.stateMutability === "payable";
},
txParams: (ctx) => ({
Expand All @@ -802,7 +802,7 @@ describe("ABI_BasicTests", function () {
},
{
name: "can not receive value with an invalid (short) function selector via message call",
shouldRun(_, receiveFunction, fallbackFunction) {
shouldRun(receiveFunction, fallbackFunction) {
return !!fallbackFunction && fallbackFunction.stateMutability !== "payable";
},
txParams: (ctx) => ({
Expand Down Expand Up @@ -887,6 +887,11 @@ describe("ABI_BasicTests", function () {
const testName = `ABI special functions: ${receiveFunction ? "" : "no "}receive and ${fallbackFunction ? fallbackFunction.stateMutability : "no"} fallback`;
describe(testName, function () {
for (const testCase of specialFunctionTests) {
// Check if we should run this test case
if (testCase.shouldRun && !testCase.shouldRun(receiveFunction, fallbackFunction)) {
continue;
}

it(testCase.name, async function () {
const startingBalance = await publicClient.getBalance({ address: ctx.address });

Expand Down

0 comments on commit b184907

Please sign in to comment.