From 3121bf46950b38f6ab822add8fce719160cbb080 Mon Sep 17 00:00:00 2001 From: Arran Schlosberg <519948+ARR4N@users.noreply.github.com> Date: Sun, 11 Aug 2024 16:37:58 +0100 Subject: [PATCH] fix: stop buyer from griefing cancellation by reflecting reimbursement (Finding 12) (#41) * test: demonstrate griefing if buyer reflects reimbursement * fix: always escrow native-token reimbursement * perf: use variable instead of repeated `address(this).balance` --- cache/fuzz/failures | 1 + src/ConsiderationLib.sol | 12 +++--------- test/ERC721ForXTest.t.sol | 26 +++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/cache/fuzz/failures b/cache/fuzz/failures index 7176c8f..065bf05 100644 --- a/cache/fuzz/failures +++ b/cache/fuzz/failures @@ -39,3 +39,4 @@ cc 62cb2547a6172f5d0617d65ba83b530caa08f54d480f5133be3ed8b00e5fe294 # shrinks to cc 9fbb337e2328ae5b966a1318433dae1046ac9b4c62058b7ea0534eeef325f555 # shrinks to 0xc7827d300000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000003190000000000000000000000000000000000000000000000000000000000001e7d00000000000000000000000000000000000000000000000000000000000020ba000000000000000000000000000000000000000000000000000000000000226b0000000000000000000000001f95d37f27ea0dea9c252fc09d5a6eaa97647353000000000000000000000000000000000000000000000000000000000000177e0000000000000000000000000000000000000000000000000000000000000c1b00000000000000000000000000000000000000000000000000000000000002bf0000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000017e00000000000000000000000000000000000000000000000000000000000021f9000000000000000000000000000000000000000000000000000000000000002500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000100c000000000000000000000000000000000000000000000000000000000000226b00000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000002119000000000000000000000000000000000000000000000000000000000000010100000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000bf500000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000001473000000000000000000000000000000000000000000000000000000000000208b000000000000000000000000000000000000000000000000000000000000151900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000137a0000000000000000000000000000000000000000000000000000000000000214000000000000000000000000000000000000000000000000000000000000157f00000000000000000000000000000000000000000000000000000000000022bb00000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002630000000000000000000000000000000000000000000000000000000000000b230000000000000000000000000000000000000000000000000000000000000ddf0000000000000000000000000000000000000000000000000000000000001616000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c70000000000000000000000000000000000000000000000000000000000001411000000000000000000000000000000000000000000000000000000000000120d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014730000000000000000000000000000000000000000000000000000000000000fb700000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000001b2b0000000000000000000000000000000000000000000000000000000000000741000000000000000000000000000000000000000000000000000000000000057400000000000000000000006572696e67a164736f6c6343000819000a0000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000c9400000000000000000000000000000000000000000000000000000000000004ef000000000000000000000000000000000000000000000000000000000000218700000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000001665000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000137b000000000000000000000000000000000000000000000000000000000000078600000000000000000000000000000000000000000000000000000000fffffffe000000000000000000000000000000000000000000000000000000000000034900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020500000000000000000000000000000000000000000000000000000000000001ba0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000074d000000000000000000000000000000000000000000000000000000000000195300000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000a5b0000000000000000000000000000000000000000000000000000000000001f8f00000000000000000000000000000000000000000000000000000000000010e700000000000000000000000000000000000000000000000000000000000007de0000000000000000000000000000000000000000000000000000000000000c920000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000075636365656473207768656e206e6f206c6f6e68000000000000000000000000000000000000000000000000000000000000feff0000000000000000000000000000000000000000000000000000000000000b25000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000ba20000000000000000000000000000000000000000000000000000000000000e8400000000000000000000000000000000000000000000000000000000000011c00000000000000000000000000000000000000000000000000000000000000fbd00000000000000000000000000000000000000000000000000000000000011260000000000000000000000000000000000000000000000000000000000002372000000000000000000000000000000000000000000000000000000000000142500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000185900000000000000000000000000000000000000000000000000000000000016d30000000000000000000000000000000000000000000000000000000000001e5300616c616e63652061667465722073696e676c65206465706f7369740000000100304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50000000000000000000000000000000000000000000000000000000000618f5880000000000000000000000000000000000000000000000000000000000001bea0000000000000000000000000000000000000000000000000000000000000158000000000000000000000000000000000000000000000000000000000000128300000000000000000000000000000000000000000000000000000000000015300000000000000000000000000000000000000000000000000000000000001202000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c160000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000019985a5b195800000000000000000000000000000000000000000000000000000000000021e80000000000000000000000000000000000000000000000000000000000001f1b0000000000000000000000000000000000000000000000000000000000001e5400000000000000000000000000000000000000000000000000000000000007880072726f723a2061203d3d2062206e6f7420736174697366696564205b75696f000000000000000000000000000000000000000000000000000000003ccfd60a000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000012bd0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000012bc0000000000000000000000000000000000000000000000000000000000000f860000000000000000000000000000000000000000000000000000000000000c1700304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f5000000000000000000000000000000000000000000000000000000000000019360000000000000000000000000000000000000000000000000000000000000d82000000000000000000000000000000000000000000000000000000000000212f0000000000000000000000000000000000000000000000000000000000001f8e00000000000000000000000000000000000000000000000000000000000005720000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000158100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001 cc eba7b1846d961e53cbfdc530b6ab276e16f2e2387ae18928c7803be23d09e595 # shrinks to 0xc6bda13300000000000000000000000055b48610427159610b017e6da32aad3e8ff3d9e500000000000000000000000000000000000000000000000000000000000008ca0000000000000000000000000000000000000000000000000000000000003bf9000000000000000000000000000000000000000000000000000000000000038b0000000000000000000000000000000000000000000000000000000000005cef00000000000000000000000000000000000000000000000000000000000005ac0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000003a2f000000000000000000000000000000000000000000000000000000000000094f00000000000000000000000000000000000000000000000000000000000001ab0000000000000000000000000000000000000000000000000000000000004f5d000000000000000000000000000000000000000000000000000000000000779f0000000000000000000000000000000000000000000000000000000000000be800000000000000000000000000000000000000000000000000000000000011c2000000000000000000000000000000000000000000000000000000000000540300000000000000000000000000000000000000000000000000000000000028bc000000000000000000000000000000000000000000000000000000000000003100000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000005270000000000000000000000000000000000000000000000000000000000002d33000000000000000000000000000000000000000000000000000000000000532b00000000000000000000000000000000000000000000000000000000000033c70000000000000000000000000000000000000000000000000000000000000b8b0000000000000000000000000000000000000000000000000000000000000fd700000000000000000000000000000000000000000000000000000000000000b3 cc 2d8d503a4c6a845b2da1d9a716d23aa581fa1db68e8e9bc87a5eed8dc0591f2d # shrinks to 0xc6bda1330000000000000000000000004342f35a708465557852b4e6094b8755eed5cb0f0000000000000000000000000b3916c65a02e0dd862268e094955e35e8a009d000000000000000000000000034bdc0692b937f7196854c997a5e46cefa7f0136000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001768b9cb337e3f520e77b8160650d100000000000000000000000074d3a17d89e233cceda8c7f00aaf47717b363512000000000000000000000000000000000000000000000000007aa59387f6bc9b0000000000000000000000009193c2261ef4826549e39e20f5bad0d22d99110a00014c402636fd861c8750828eabee0874da64ce5cb73456dc71afd8419ce636000000000000000000000000b00980db33e480d7758fa43f599fc21ec8937c4e00000000000000000000000000000000002235c3e8c9f93a4798848e504559d00000000000000000000000008acaa514e8e7e8a87e666e8b889327099fb83514000000000000000000000000000000001fff6defaf837ed75540121dc284394600000000000000000000000024eefe4dff0b6b95cd5f39dc97bb683151785df4000000000000000001c63a3c4a5e02e872b83cd3de8a2228dff9e7a1022ff8a30000000000000000000000000000000000dccbc59f5389ad1b931be7c493be69000000000000000000000000000000000000000000000000191fcfcd50099fbc0000000000000000000000000000000000000000000000000000000000000005000000000000000000000000eeb23b665d595bbfdebf9a946bf24c84ac1521a9d5b082201998f2d340b0e153040411785def31143190a6a4baea151b70ba045900000000000000000000000000000000000000000000000000000b2eb792712f0000000000000000000000000000000016d89e07054450c152a47e5e17250462000000000000000000000000000000000000000000000000000000000032ad5f0000000000000fad752dbae94f752720a8384dc6c4f526e11a64d0c41ab932ec000000000000000000000000000000000000000000000000000000000000003200000000000000000000000094dfc714f544acb8c7c58b591bc56d5dbfaf54cc +cc eb43b982e663eb1fa05b2c876facadc58cf2e6217aa72d46ab9abe3f682c37fa # shrinks to 0xef7b7b9c0000000000000000000000007bf881c2cdde0140505ebe78ca1153e6457977ed0000000000000000000000001575f21ee7eca3018c90d8938ddf1f4cb1256dce000000000000000000000000ee22a7749ac0d670fc531b444def7371c49f3163000000000000000000000000000000000000000000000000000000000000000e0000000000000008e2a998e993ed40b343954f3af9f8a6d0d4da9df0929f05b600000000000000000000000079c15a682600c0325163926fae9d787cf9bc7c4b00000000000000000000000000000be18219cb3614f66a7965ca1c96fed4e923000000000000000000000000cfb8d69f87cad32987e13a4bc1e6098d8ff0dffe3e8f10c0df6f0441023a585a783118ce5c59556083d446b0b832fcc4e803fe110000000000000000000000003b41009990dc966ddf1d3badc30dd1151d6523fb00000000000000000000000000000000000269515deb6005ac821c1c0ffb1eae000000000000000000000000188f0be7110242f7725ede0e3d63553bc52bbba400000000000000000000000000000000000000000000000000000000005f13710000000000000000000000007c6e3303497d8931e4f7ce7e509286636308daee00000000000000000000000000000000000000000000000000065d8bee5b95fa0000000000000000000000000000000000000000000000000000000000000d4f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000031c44567ba45b008173ab74c855472cfcee2e768fb890c705dd2e1fc2fd3ba34f48f0abd7d16b2e9c8723827e7456a0ad01199d800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001fec00000000000000000000000000000000000037b59a924edc548044a1329c43a900000000000000000000000000000000000000000035aa0d3aea8fb12e13cf0a00000000000000000000000000001776f623f70b209db0a66cbe6272833ee1a20000000000000000000000000000000000000000000000026bef7177341a76a400000000000000000000000030ec50a235b3e12d069be6914048dfbbc0367c740000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 diff --git a/src/ConsiderationLib.sol b/src/ConsiderationLib.sol index a8bb375..368cf38 100644 --- a/src/ConsiderationLib.sol +++ b/src/ConsiderationLib.sol @@ -93,16 +93,10 @@ library ConsiderationLib { */ function _cancel(Consideration memory, PayableParties memory parties, IEscrow escrow) internal { // MUST remain as the last step for the same reason as _disburseFunds(). - _sendOrEscrow(parties.buyer, address(this).balance, escrow); - } - - function _sendOrEscrow(address payable to, uint256 amount, IEscrow escrow) internal { - // 20k for a fresh SSTORE and an arbitrary 10k overhead - (bool success,) = to.call{value: amount, gas: 30_000}(""); - if (success) { - return; + uint256 bal = address(this).balance; + if (bal > 0) { + escrow.deposit{value: bal}(parties.buyer); } - escrow.deposit{value: amount}(to); } /// @dev Returns whether the contract's remaining balance is zero. diff --git a/test/ERC721ForXTest.t.sol b/test/ERC721ForXTest.t.sol index 2092d36..dbc6bd6 100644 --- a/test/ERC721ForXTest.t.sol +++ b/test/ERC721ForXTest.t.sol @@ -293,10 +293,18 @@ abstract contract ERC721ForXTest is SwapperTestBase { { uint256 expectedBuyerBalance = _balance(test.buyer()) + _balance(swapper); + if (!_isERC20Test() && _balance(swapper) > 0) { + vm.expectEmit(true, true, true, true, address(factory.escrow())); + emit Deposit(test.buyer(), _balance(swapper)); + } vm.expectEmit(true, true, true, true, address(factory)); emit Cancelled(_swapper(t)); _cancelAs(t, asSeller ? test.seller() : test.buyer()); + if (factory.escrow().balance(test.buyer()) > 0) { + factory.escrow().withdraw(test.buyer()); + } + assertEq(_balance(swapper), 0, "swapper balance zero after cancel"); assertEq(_balance(test.buyer()), expectedBuyerBalance, "buyer balance after cancel"); @@ -368,7 +376,7 @@ abstract contract ERC721ForXTest is SwapperTestBase { ); } - function testGriefNativeTokenInvariant(ERC721TestCase memory t, uint8 vandalIndex) + function testGriefNativeTokenInvariantOnFill(ERC721TestCase memory t, uint8 vandalIndex) external assumeValidTest(t.base, Assumptions({sufficientPayment: true, validPlatformFee: true, approving: true})) { @@ -397,6 +405,22 @@ abstract contract ERC721ForXTest is SwapperTestBase { ); } + function testGriefNativeTokenInvariantOnCancel(ERC721TestCase memory t) + external + assumeValidTest(t.base, Assumptions({sufficientPayment: true, validPlatformFee: true, approving: true})) + { + vm.skip(_isERC20Test()); + + // If the buyer sends any funds back during cancellation, the post-execution invariant of zero balance will be + // broken. + t.base.parties.buyer = address(new FundsReflector()); + address swapper = _beforeExecute(t); + + vm.expectEmit(true, true, true, true, address(factory)); + emit Cancelled(swapper); + _cancelAs(t, t.base.seller()); + } + /** * @dev The generated `ForERC20Deployer` contracts have payable `fill()` functions because of simple identifier * replacement. Being payable is unnecessary and could (but doesn't) risk accidental locking of funds. There are two