Skip to content

Commit

Permalink
Fixed error handling for contracts with receive and non-payable fallb…
Browse files Browse the repository at this point in the history
…ack.
  • Loading branch information
ricmoo committed May 15, 2023
1 parent f87f6ef commit 6db7458
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 6 deletions.
6 changes: 3 additions & 3 deletions src.ts/_tests/test-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
},
];

Expand Down Expand Up @@ -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;
Expand Down
16 changes: 13 additions & 3 deletions src.ts/contract/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 6db7458

Please sign in to comment.