From 6db7458cf0a09e8e8a2abb712239972ab81dc9df Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Mon, 15 May 2023 16:49:02 -0400 Subject: [PATCH] Fixed error handling for contracts with receive and non-payable fallback. --- src.ts/_tests/test-contract.ts | 6 +++--- src.ts/contract/contract.ts | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src.ts/_tests/test-contract.ts b/src.ts/_tests/test-contract.ts index 517118b027..0e039b47f5 100644 --- a/src.ts/_tests/test-contract.ts +++ b/src.ts/_tests/test-contract.ts @@ -436,13 +436,13 @@ describe("Test Contract Fallback", function() { name: "receive and non-payable fallback", address: "0x5b59d934f0d22b15e73b5d6b9ae83486b70df67e", abi: [ - "fallback() payable", + "fallback()", "receive()" ], sendNone: { data: "0x" }, sendData: { data: "0x" }, sendValue: { data: "0x" }, - sendDataAndValue: { error: "overrides.value" }, + sendDataAndValue: { error: "overrides" }, }, ]; @@ -489,7 +489,7 @@ describe("Test Contract Fallback", function() { //console.log(result); assert.ok(true); } else { - assert.rejects(func, function(error: any) { + await assert.rejects(func, function(error: any) { if (error.message === send.error) { return true; } if (isError(error, "INVALID_ARGUMENT")) { return error.argument === send.error; diff --git a/src.ts/contract/contract.ts b/src.ts/contract/contract.ts index 9d8adaf1f1..8bbbb11b9e 100644 --- a/src.ts/contract/contract.ts +++ b/src.ts/contract/contract.ts @@ -172,13 +172,23 @@ function buildWrappedFallback(contract: BaseContract): WrappedFallback { const iface = contract.interface; + const noValue = ((tx.value || BN_0) === BN_0); + const noData = ((tx.data || "0x") === "0x"); + + if (iface.fallback && !iface.fallback.payable && iface.receive && !noData && !noValue) { + assertArgument(false, "cannot send data to receive or send value to non-payable fallback", "overrides", overrides); + } + + assertArgument(iface.fallback || noData, + "cannot send data to receive-only contract", "overrides.data", tx.data); + // Only allow payable contracts to set non-zero value const payable = iface.receive || (iface.fallback && iface.fallback.payable); - assertArgument(payable || (tx.value || BN_0) === BN_0, - "cannot send value to non-payable contract", "overrides.value", tx.value); + assertArgument(payable || noValue, + "cannot send value to non-payable fallback", "overrides.value", tx.value); // Only allow fallback contracts to set non-empty data - assertArgument(iface.fallback || (tx.data || "0x") === "0x", + assertArgument(iface.fallback || noData, "cannot send data to receive-only contract", "overrides.data", tx.data); return tx;