From 53a38ebd1a4271f263b56f20b18f56806d0ae4f3 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 31 Jul 2023 12:59:30 +0000 Subject: [PATCH 1/3] Add ERC1271 support --- src/MulticallerWithSigner.sol | 184 ++++++++++++++-------- test/Multicaller.t.sol | 89 +++++++++++ test/utils/mocks/MockERC1271Malicious.sol | 14 ++ test/utils/mocks/MockERC1271Wallet.sol | 93 +++++++++++ 4 files changed, 311 insertions(+), 69 deletions(-) create mode 100644 test/utils/mocks/MockERC1271Malicious.sol create mode 100644 test/utils/mocks/MockERC1271Wallet.sol diff --git a/src/MulticallerWithSigner.sol b/src/MulticallerWithSigner.sol index 626bb76..e097bb3 100644 --- a/src/MulticallerWithSigner.sol +++ b/src/MulticallerWithSigner.sol @@ -121,7 +121,6 @@ contract MulticallerWithSigner { assembly { // Throughout this code, we will abuse returndatasize // in place of zero anywhere before a call to save a bit of gas. - // For non-payable functions, callvalue may also be used in place of zero. // We will use storage slot zero to store the signer at // bits [0..159] and reentrancy guard at bits [160..255]. sstore(returndatasize(), shl(160, address())) @@ -215,21 +214,36 @@ contract MulticallerWithSigner { mstore(0x20, keccak256(0x60, 0xa0)) // Compute and store the domain separator. // Layout the fields of `ecrecover`. mstore(returndatasize(), 0x1901) // Store "\x19\x01". - mstore(returndatasize(), keccak256(0x1e, 0x42)) // Compute and store the digest. - calldatacopy(0x40, signature.offset, 0x41) // Copy `r`, `s`, `v`. - mstore(0x20, byte(returndatasize(), mload(0x80))) // `v`. - pop( - staticcall( - gas(), // Remaining gas. - and(eq(signature.length, 65), lt(mload(0x60), _S_THRES)), // `ecrecover`. - returndatasize(), // Start of input calldata in memory. - 0x80, // Size of input calldata. - returndatasize(), // Start of output returndata in memory. - 0x20 // Size of output returndata. + let digest := keccak256(0x1e, 0x42) // Compute the digest. + let signatureIsValid := 0 + if eq(signature.length, 65) { + mstore(returndatasize(), digest) // Store the digest. + calldatacopy(0x40, signature.offset, signature.length) // Copy `r`, `s`, `v`. + mstore(0x20, byte(returndatasize(), mload(0x80))) // `v`. + pop( + staticcall( + gas(), // Remaining gas. + lt(mload(0x60), _S_THRES), // `ecrecover`. + returndatasize(), // Start of input calldata in memory. + 0x80, // Size of input calldata. + returndatasize(), // Start of output returndata in memory. + 0x20 // Size of output returndata. + ) ) - ) - // `returndatasize()` will be 0x20 upon success and 0x00 otherwise. - let recoverySuccess := mul(returndatasize(), eq(mload(0x00), signer)) + // `returndatasize()` will be 0x20 upon success and 0x00 otherwise. + signatureIsValid := mul(returndatasize(), eq(mload(0x00), signer)) + } + // ERC1271 fallback. + if iszero(signatureIsValid) { + let f := shl(224, 0x1626ba7e) // `isValidSignature(bytes32,bytes)`. + mstore(0x00, f) + mstore(0x04, digest) + mstore(0x24, 0x40) + mstore(0x44, signature.length) + calldatacopy(0x64, signature.offset, signature.length) + let t := staticcall(gas(), signer, 0x00, add(signature.length, 0x64), 0x00, 0x20) + signatureIsValid := and(and(eq(mload(0x00), f), eq(returndatasize(), 0x20)), t) + } // Check the nonce. mstore(0x00, signer) @@ -237,7 +251,7 @@ contract MulticallerWithSigner { let bucketSlot := keccak256(0x00, 0x3f) let bucketValue := sload(bucketSlot) let bit := shl(and(0xff, nonce), 1) - if or(iszero(recoverySuccess), and(bit, bucketValue)) { + if or(iszero(signatureIsValid), and(bit, bucketValue)) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } @@ -330,20 +344,20 @@ contract MulticallerWithSigner { */ function invalidateNonces(uint256[] calldata nonces) external { assembly { - mstore(returndatasize(), caller()) + mstore(0x00, caller()) // Iterate through all the nonces and set their boolean values in the storage. let end := shl(5, nonces.length) - for { let i := returndatasize() } iszero(eq(i, end)) { i := add(i, 0x20) } { + for { let i := 0 } iszero(eq(i, end)) { i := add(i, 0x20) } { let nonce := calldataload(add(nonces.offset, i)) mstore(0x20, nonce) - let bucketSlot := keccak256(returndatasize(), 0x3f) + let bucketSlot := keccak256(0x00, 0x3f) sstore(bucketSlot, or(sload(bucketSlot), shl(and(0xff, nonce), 1))) } // Emit `NoncesInvalidated(msg.sender, nonces)`. - mstore(returndatasize(), 0x20) + mstore(0x00, 0x20) mstore(0x20, nonces.length) calldatacopy(0x40, nonces.offset, end) - log2(returndatasize(), add(0x40, end), _NONCES_INVALIDATED_EVENT_SIGNATURE, caller()) + log2(0x00, add(0x40, end), _NONCES_INVALIDATED_EVENT_SIGNATURE, caller()) } } @@ -377,38 +391,54 @@ contract MulticallerWithSigner { mstore(0x20, keccak256(0x60, 0xa0)) // Compute and store the domain separator. // Layout the fields of `ecrecover`. mstore(returndatasize(), 0x1901) // Store "\x19\x01". - mstore(returndatasize(), keccak256(0x1e, 0x42)) // Compute and store the digest. - calldatacopy(0x40, signature.offset, 0x41) // Copy `r`, `s`, `v`. - mstore(0x20, byte(returndatasize(), mload(0x80))) // `v`. - pop( - staticcall( - gas(), // Remaining gas. - and(eq(signature.length, 65), lt(mload(0x60), _S_THRES)), // `ecrecover`. - returndatasize(), // Start of input calldata in memory. - 0x80, // Size of input calldata. - returndatasize(), // Start of output returndata in memory. - 0x20 // Size of output returndata. + let digest := keccak256(0x1e, 0x42) // Compute the digest. + let signatureIsValid := 0 + if eq(signature.length, 65) { + mstore(returndatasize(), digest) // Store the digest. + calldatacopy(0x40, signature.offset, signature.length) // Copy `r`, `s`, `v`. + mstore(0x20, byte(returndatasize(), mload(0x80))) // `v`. + pop( + staticcall( + gas(), // Remaining gas. + lt(mload(0x60), _S_THRES), // `ecrecover`. + returndatasize(), // Start of input calldata in memory. + 0x80, // Size of input calldata. + returndatasize(), // Start of output returndata in memory. + 0x20 // Size of output returndata. + ) ) - ) - // `returndatasize()` will be 0x20 upon success and 0x00 otherwise. - if iszero(mul(returndatasize(), eq(mload(callvalue()), signer))) { - mstore(callvalue(), 0x8baa579f) // `InvalidSignature()`. + // `returndatasize()` will be 0x20 upon success and 0x00 otherwise. + signatureIsValid := mul(returndatasize(), eq(mload(0x00), signer)) + } + // ERC1271 fallback. + if iszero(signatureIsValid) { + let f := shl(224, 0x1626ba7e) // `isValidSignature(bytes32,bytes)`. + mstore(0x00, f) + mstore(0x04, digest) + mstore(0x24, 0x40) + mstore(0x44, signature.length) + calldatacopy(0x64, signature.offset, signature.length) + let t := staticcall(gas(), signer, 0x00, add(signature.length, 0x64), 0x00, 0x20) + signatureIsValid := and(and(eq(mload(0x00), f), eq(returndatasize(), 0x20)), t) + } + if iszero(signatureIsValid) { + mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } - mstore(callvalue(), signer) + mstore(0x00, signer) // Iterate through all the nonces and set their boolean values in the storage. - for { let i := callvalue() } iszero(eq(i, end)) { i := add(i, 0x20) } { + for { let i := 0 } iszero(eq(i, end)) { i := add(i, 0x20) } { let nonce := calldataload(add(nonces.offset, i)) mstore(0x20, nonce) - let bucketSlot := keccak256(callvalue(), 0x3f) + let bucketSlot := keccak256(0x00, 0x3f) sstore(bucketSlot, or(sload(bucketSlot), shl(and(0xff, nonce), 1))) } - // Emit `NoncesInvalidated(msg.sender, nonces)`. - mstore(callvalue(), 0x20) + // Emit `NoncesInvalidated(signer, nonces)`. + mstore(0x00, 0x20) mstore(0x20, nonces.length) calldatacopy(0x40, nonces.offset, end) - log2(callvalue(), add(0x40, end), _NONCES_INVALIDATED_EVENT_SIGNATURE, signer) + log2(0x00, add(0x40, end), _NONCES_INVALIDATED_EVENT_SIGNATURE, signer) } } @@ -424,18 +454,18 @@ contract MulticallerWithSigner { returns (bool[] memory) { assembly { - mstore(returndatasize(), signer) + mstore(0x00, signer) // Iterate through all the nonces and append their boolean values. let end := shl(5, nonces.length) - for { let i := returndatasize() } iszero(eq(i, end)) { i := add(i, 0x20) } { + for { let i := 0 } iszero(eq(i, end)) { i := add(i, 0x20) } { let nonce := calldataload(add(nonces.offset, i)) mstore(0x20, nonce) - let bit := and(1, shr(and(0xff, nonce), sload(keccak256(returndatasize(), 0x3f)))) + let bit := and(1, shr(and(0xff, nonce), sload(keccak256(0x00, 0x3f)))) mstore(add(0x40, i), bit) } - mstore(returndatasize(), 0x20) // Store the memory offset of the `results`. + mstore(0x00, 0x20) // Store the memory offset of the `results`. mstore(0x20, nonces.length) // Store `data.length` into `results`. - return(returndatasize(), add(0x40, end)) + return(0x00, add(0x40, end)) } } @@ -454,9 +484,9 @@ contract MulticallerWithSigner { let newNonceSalt := add(add(1, shr(224, blockhash(sub(number(), 1)))), nonceSalt) sstore(nonceSaltSlot, newNonceSalt) // Emit `NonceSaltIncremented(msg.sender, newNonceSalt)`. - mstore(returndatasize(), newNonceSalt) - log2(returndatasize(), 0x20, _NONCE_SALT_INCREMENTED_EVENT_SIGNATURE, caller()) - return(returndatasize(), 0x20) + mstore(0x00, newNonceSalt) + log2(0x00, 0x20, _NONCE_SALT_INCREMENTED_EVENT_SIGNATURE, caller()) + return(0x00, 0x20) } } @@ -489,32 +519,48 @@ contract MulticallerWithSigner { mstore(0x20, keccak256(0x60, 0xa0)) // Compute and store the domain separator. // Layout the fields of `ecrecover`. mstore(returndatasize(), 0x1901) // Store "\x19\x01". - mstore(returndatasize(), keccak256(0x1e, 0x42)) // Compute and store the digest. - calldatacopy(0x40, signature.offset, 0x41) // Copy `r`, `s`, `v`. - mstore(0x20, byte(returndatasize(), mload(0x80))) // `v`. - pop( - staticcall( - gas(), // Remaining gas. - and(eq(signature.length, 65), lt(mload(0x60), _S_THRES)), // `ecrecover`. - returndatasize(), // Start of input calldata in memory. - 0x80, // Size of input calldata. - returndatasize(), // Start of output returndata in memory. - 0x20 // Size of output returndata. + let digest := keccak256(0x1e, 0x42) // Compute the digest. + let signatureIsValid := 0 + if eq(signature.length, 65) { + mstore(returndatasize(), digest) // Store the digest. + calldatacopy(0x40, signature.offset, signature.length) // Copy `r`, `s`, `v`. + mstore(0x20, byte(returndatasize(), mload(0x80))) // `v`. + pop( + staticcall( + gas(), // Remaining gas. + lt(mload(0x60), _S_THRES), // `ecrecover`. + returndatasize(), // Start of input calldata in memory. + 0x80, // Size of input calldata. + returndatasize(), // Start of output returndata in memory. + 0x20 // Size of output returndata. + ) ) - ) - // `returndatasize()` will be 0x20 upon success and 0x00 otherwise. - if iszero(mul(returndatasize(), eq(mload(callvalue()), signer))) { - mstore(callvalue(), 0x8baa579f) // `InvalidSignature()`. + // `returndatasize()` will be 0x20 upon success and 0x00 otherwise. + signatureIsValid := mul(returndatasize(), eq(mload(0x00), signer)) + } + // ERC1271 fallback. + if iszero(signatureIsValid) { + let f := shl(224, 0x1626ba7e) // `isValidSignature(bytes32,bytes)`. + mstore(0x00, f) + mstore(0x04, digest) + mstore(0x24, 0x40) + mstore(0x44, signature.length) + calldatacopy(0x64, signature.offset, signature.length) + let t := staticcall(gas(), signer, 0x00, add(signature.length, 0x64), 0x00, 0x20) + signatureIsValid := and(and(eq(mload(0x00), f), eq(returndatasize(), 0x20)), t) + } + if iszero(signatureIsValid) { + mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } // Increment by some pseudorandom amount from [1..4294967296]. let newNonceSalt := add(add(1, shr(224, blockhash(sub(number(), 1)))), nonceSalt) sstore(nonceSaltSlot, newNonceSalt) - // Emit `NonceSaltIncremented(msg.sender, newNonceSalt)`. - mstore(callvalue(), newNonceSalt) - log2(callvalue(), 0x20, _NONCE_SALT_INCREMENTED_EVENT_SIGNATURE, signer) - return(callvalue(), 0x20) + // Emit `NonceSaltIncremented(signer, newNonceSalt)`. + mstore(0x00, newNonceSalt) + log2(0x00, 0x20, _NONCE_SALT_INCREMENTED_EVENT_SIGNATURE, signer) + return(0x00, 0x20) } } diff --git a/test/Multicaller.t.sol b/test/Multicaller.t.sol index 7754685..2a7436e 100644 --- a/test/Multicaller.t.sol +++ b/test/Multicaller.t.sol @@ -6,6 +6,8 @@ import {Multicaller} from "../src/Multicaller.sol"; import {MulticallerWithSender} from "../src/MulticallerWithSender.sol"; import {MulticallerWithSigner} from "../src/MulticallerWithSigner.sol"; import {LibMulticaller} from "../src/LibMulticaller.sol"; +import {MockERC1271Wallet} from "./utils/mocks/MockERC1271Wallet.sol"; +import {MockERC1271Malicious} from "./utils/mocks/MockERC1271Malicious.sol"; /** * @dev Target contract for the multicaller for testing purposes. @@ -139,6 +141,11 @@ contract MulticallerTest is TestPlus { FallbackTarget fallbackTargetA; FallbackTarget fallbackTargetB; + address erc721Signer; + uint256 erc721SignerPrivateKey; + address erc1271Wallet; + address erc1271Malicious; + event NoncesInvalidated(address indexed signer, uint256[] nonces); event NonceSaltIncremented(address indexed signer, uint256 newNonceSalt); @@ -194,6 +201,12 @@ contract MulticallerTest is TestPlus { fallbackTargetB = new FallbackTarget(); } + function _deployERC1271Contracts() internal virtual { + (erc721Signer, erc721SignerPrivateKey) = _randomSigner(); + erc1271Wallet = address(new MockERC1271Wallet(erc721Signer)); + erc1271Malicious = address(new MockERC1271Malicious()); + } + function testMulticallerRefund(uint256) public { uint256 payment = _bound(_random(), 0, type(uint128).max); @@ -602,6 +615,36 @@ contract MulticallerTest is TestPlus { } } + function testMulticallerWithSignerWithERC1271(uint256) public { + _deployERC1271Contracts(); + _TestTemps memory t = _testTemps(); + t.signer = erc1271Wallet; + t.privateKey = erc721SignerPrivateKey; + t.nonceSalt = multicallerWithSigner.nonceSaltOf(t.signer); + _generateSignature(t); + + vm.deal(address(this), type(uint160).max); + + if (_random() % 2 == 0) { + t.signer = erc1271Malicious; + _callAndCheckMulticallerWithSigner(t, MulticallerWithSigner.InvalidSignature.selector); + } else { + bytes[] memory results = _callAndCheckMulticallerWithSigner(t, bytes4(0)); + + unchecked { + uint256 expectedHashSum; + for (uint256 i; i < t.data.length; ++i) { + expectedHashSum += uint256(keccak256(t.data[i])); + } + uint256 actualHashSum = fallbackTargetA.hashSum() + fallbackTargetB.hashSum(); + assertEq(actualHashSum, expectedHashSum); + for (uint256 i; i < results.length; ++i) { + assertEq(keccak256(results[i]), keccak256(t.data[i])); + } + } + } + } + function _checkBalance(_TestTemps memory t, address target) internal { unchecked { uint256 expected; @@ -869,6 +912,35 @@ contract MulticallerTest is TestPlus { } } + function testMulticallerWithSignerInvalidateNoncesWithERC1271(uint256) public { + _deployERC1271Contracts(); + unchecked { + uint256[] memory nonces = new uint256[](_random() % 4); + if (_random() % 2 == 0) { + for (uint256 i; i < nonces.length; ++i) { + nonces[i] = _random(); + } + } else { + for (uint256 i; i < nonces.length; ++i) { + nonces[i] = _random() % 8; + } + } + + bytes memory signature = + _generateInvalidateNoncesSignature(nonces, erc1271Wallet, erc721SignerPrivateKey); + + vm.expectRevert(MulticallerWithSigner.InvalidSignature.selector); + multicallerWithSigner.invalidateNoncesForSigner(nonces, erc1271Malicious, signature); + + vm.expectEmit(true, true, true, true); + emit NoncesInvalidated(erc1271Wallet, nonces); + multicallerWithSigner.invalidateNoncesForSigner(nonces, erc1271Wallet, signature); + + vm.expectRevert(MulticallerWithSigner.InvalidSignature.selector); + multicallerWithSigner.invalidateNoncesForSigner(nonces, erc1271Malicious, signature); + } + } + function testMultiCallerWithSignerIncrementNonceSalt(uint256) public { (address signer, uint256 privateKey) = _randomSigner(); @@ -894,6 +966,23 @@ contract MulticallerTest is TestPlus { } } + function testMultiCallerWithSignerIncrementNonceSaltWithERC1271(uint256) public { + _deployERC1271Contracts(); + uint256 nonceSaltBefore = multicallerWithSigner.nonceSaltOf(erc1271Wallet); + uint256 nextNonceSalt = _nextNonceSalt(nonceSaltBefore); + bytes memory signature = + _generateIncrementNonceSaltSignature(erc1271Wallet, erc721SignerPrivateKey); + + vm.expectRevert(MulticallerWithSigner.InvalidSignature.selector); + multicallerWithSigner.incrementNonceSaltForSigner(erc1271Malicious, signature); + + emit NonceSaltIncremented(erc1271Wallet, nextNonceSalt); + multicallerWithSigner.incrementNonceSaltForSigner(erc1271Wallet, signature); + + vm.expectRevert(MulticallerWithSigner.InvalidSignature.selector); + multicallerWithSigner.incrementNonceSaltForSigner(erc1271Wallet, signature); + } + function _generateInvalidateNoncesSignature( uint256[] memory nonces, address signer, diff --git a/test/utils/mocks/MockERC1271Malicious.sol b/test/utils/mocks/MockERC1271Malicious.sol new file mode 100644 index 0000000..3428d1a --- /dev/null +++ b/test/utils/mocks/MockERC1271Malicious.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/// @dev WARNING! This mock is strictly intended for testing purposes only. +/// Do NOT copy anything here into production code unless you really know what you are doing. +contract MockERC1271Malicious { + function isValidSignature(bytes32, bytes calldata) external pure returns (bytes4) { + /// @solidity memory-safe-assembly + assembly { + mstore(0, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) + return(0, 32) + } + } +} diff --git a/test/utils/mocks/MockERC1271Wallet.sol b/test/utils/mocks/MockERC1271Wallet.sol new file mode 100644 index 0000000..17b0f7e --- /dev/null +++ b/test/utils/mocks/MockERC1271Wallet.sol @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +/// @notice A generic interface for a contract which properly accepts ERC721 tokens. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) +abstract contract ERC721TokenReceiver { + function onERC721Received(address, address, uint256, bytes calldata) + external + virtual + returns (bytes4) + { + return ERC721TokenReceiver.onERC721Received.selector; + } +} + +/// @notice A generic interface for a contract which properly accepts ERC1155 tokens. +/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) +abstract contract ERC1155TokenReceiver { + function onERC1155Received(address, address, uint256, uint256, bytes calldata) + external + virtual + returns (bytes4) + { + return ERC1155TokenReceiver.onERC1155Received.selector; + } + + function onERC1155BatchReceived( + address, + address, + uint256[] calldata, + uint256[] calldata, + bytes calldata + ) external virtual returns (bytes4) { + return ERC1155TokenReceiver.onERC1155BatchReceived.selector; + } +} + +/// @dev WARNING! This mock is strictly intended for testing purposes only. +/// Do NOT copy anything here into production code unless you really know what you are doing. +contract MockERC1271Wallet is ERC721TokenReceiver, ERC1155TokenReceiver { + address signer; + + bytes32 private constant _MALLEABILITY_THRESHOLD_PLUS_ONE = + 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1; + + constructor(address signer_) { + signer = signer_; + } + + function isValidSignature(bytes32 hash, bytes calldata signature) + external + view + returns (bytes4) + { + return _recoverCalldata(hash, signature) == signer ? bytes4(0x1626ba7e) : bytes4(0); + } + + function _recoverCalldata(bytes32 hash, bytes calldata signature) + internal + view + returns (address result) + { + assembly { + let m := mload(0x40) // Cache the free memory pointer. + mstore(0x00, hash) + mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. + calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. + pop( + staticcall( + gas(), // Amount of gas left for the transaction. + and( + // If the signature is exactly 65 bytes in length. + eq(signature.length, 65), + // If `s` in lower half order, such that the signature is not malleable. + lt(mload(0x60), _MALLEABILITY_THRESHOLD_PLUS_ONE) + ), // Address of `ecrecover`. + 0x00, // Start of input. + 0x80, // Size of input. + 0x00, // Start of output. + 0x20 // Size of output. + ) + ) + result := mload(0x00) + // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. + if iszero(returndatasize()) { + mstore(0x00, 0x8baa579f) // `InvalidSignature()`. + revert(0x1c, 0x04) + } + mstore(0x60, 0) // Restore the zero slot. + mstore(0x40, m) // Restore the free memory pointer. + } + } +} From e79a5b0f0738cbf5550a5df2d865b40f90942e07 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Mon, 31 Jul 2023 19:40:37 +0000 Subject: [PATCH 2/3] Optimize --- src/MulticallerWithSigner.sol | 42 +++++------------------------------ 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/src/MulticallerWithSigner.sol b/src/MulticallerWithSigner.sol index e097bb3..ba16713 100644 --- a/src/MulticallerWithSigner.sol +++ b/src/MulticallerWithSigner.sol @@ -220,18 +220,8 @@ contract MulticallerWithSigner { mstore(returndatasize(), digest) // Store the digest. calldatacopy(0x40, signature.offset, signature.length) // Copy `r`, `s`, `v`. mstore(0x20, byte(returndatasize(), mload(0x80))) // `v`. - pop( - staticcall( - gas(), // Remaining gas. - lt(mload(0x60), _S_THRES), // `ecrecover`. - returndatasize(), // Start of input calldata in memory. - 0x80, // Size of input calldata. - returndatasize(), // Start of output returndata in memory. - 0x20 // Size of output returndata. - ) - ) - // `returndatasize()` will be 0x20 upon success and 0x00 otherwise. - signatureIsValid := mul(returndatasize(), eq(mload(0x00), signer)) + let t := staticcall(gas(), lt(mload(0x60), _S_THRES), 0x00, 0x80, 0x01, 0x20) + signatureIsValid := mul(returndatasize(), eq(signer, mload(t))) } // ERC1271 fallback. if iszero(signatureIsValid) { @@ -397,18 +387,8 @@ contract MulticallerWithSigner { mstore(returndatasize(), digest) // Store the digest. calldatacopy(0x40, signature.offset, signature.length) // Copy `r`, `s`, `v`. mstore(0x20, byte(returndatasize(), mload(0x80))) // `v`. - pop( - staticcall( - gas(), // Remaining gas. - lt(mload(0x60), _S_THRES), // `ecrecover`. - returndatasize(), // Start of input calldata in memory. - 0x80, // Size of input calldata. - returndatasize(), // Start of output returndata in memory. - 0x20 // Size of output returndata. - ) - ) - // `returndatasize()` will be 0x20 upon success and 0x00 otherwise. - signatureIsValid := mul(returndatasize(), eq(mload(0x00), signer)) + let t := staticcall(gas(), lt(mload(0x60), _S_THRES), 0x00, 0x80, 0x01, 0x20) + signatureIsValid := mul(returndatasize(), eq(signer, mload(t))) } // ERC1271 fallback. if iszero(signatureIsValid) { @@ -525,18 +505,8 @@ contract MulticallerWithSigner { mstore(returndatasize(), digest) // Store the digest. calldatacopy(0x40, signature.offset, signature.length) // Copy `r`, `s`, `v`. mstore(0x20, byte(returndatasize(), mload(0x80))) // `v`. - pop( - staticcall( - gas(), // Remaining gas. - lt(mload(0x60), _S_THRES), // `ecrecover`. - returndatasize(), // Start of input calldata in memory. - 0x80, // Size of input calldata. - returndatasize(), // Start of output returndata in memory. - 0x20 // Size of output returndata. - ) - ) - // `returndatasize()` will be 0x20 upon success and 0x00 otherwise. - signatureIsValid := mul(returndatasize(), eq(mload(0x00), signer)) + let t := staticcall(gas(), lt(mload(0x60), _S_THRES), 0x00, 0x80, 0x01, 0x20) + signatureIsValid := mul(returndatasize(), eq(signer, mload(t))) } // ERC1271 fallback. if iszero(signatureIsValid) { From 850048ec073b61eb3c269a2e5691a830ef73e68c Mon Sep 17 00:00:00 2001 From: Vectorized Date: Tue, 1 Aug 2023 02:02:29 +0000 Subject: [PATCH 3/3] Add ERC1271 support --- .gas-snapshot | 59 ++++++++++++++++++++++-------------------- API.md | 2 +- README.md | 14 +++++----- src/LibMulticaller.sol | 2 +- test/Multicaller.t.sol | 16 ++++++------ 5 files changed, 48 insertions(+), 45 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 6f130cd..a2baf97 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,29 +1,32 @@ -MulticallerTest:testMultiCallerWithSignerIncrementNonceSalt(uint256) (runs: 256, μ: 76649, ~: 78646) -MulticallerTest:testMulticallerCdFallback(string) (runs: 256, μ: 306344, ~: 301385) -MulticallerTest:testMulticallerForwardsMessageValue() (gas: 213765) -MulticallerTest:testMulticallerGetNames() (gas: 147559) -MulticallerTest:testMulticallerReentrancyGuard() (gas: 18376) -MulticallerTest:testMulticallerRefund(uint256) (runs: 256, μ: 169784, ~: 171897) -MulticallerTest:testMulticallerReturnDataIsProperlyEncoded() (gas: 122094) -MulticallerTest:testMulticallerReturnDataIsProperlyEncoded(string,string,uint256) (runs: 256, μ: 526229, ~: 529983) -MulticallerTest:testMulticallerReturnDataIsProperlyEncoded(uint256,uint256,uint256,uint256) (runs: 256, μ: 122151, ~: 122151) -MulticallerTest:testMulticallerRevertWithCustomError() (gas: 31988) -MulticallerTest:testMulticallerRevertWithMessage() (gas: 34780) -MulticallerTest:testMulticallerRevertWithMessage(string) (runs: 256, μ: 35673, ~: 35735) -MulticallerTest:testMulticallerRevertWithNothing() (gas: 31828) -MulticallerTest:testMulticallerSenderDoesNotRevertWithoutMulticallerDeployed() (gas: 3452) -MulticallerTest:testMulticallerTargetGetMulticallerSender() (gas: 27471) -MulticallerTest:testMulticallerWithNoData() (gas: 16144) -MulticallerTest:testMulticallerWithSigner(uint256) (runs: 256, μ: 129357, ~: 122472) -MulticallerTest:testMulticallerWithSignerEIP712Domain() (gas: 12317) -MulticallerTest:testMulticallerWithSignerGetMulticallerSigner() (gas: 142638) -MulticallerTest:testMulticallerWithSignerInvalidateNonces(uint256) (runs: 256, μ: 81048, ~: 80575) -MulticallerTest:testMulticallerWithSignerNonPayableFunctions() (gas: 48770) -MulticallerTest:testMulticallerWithSignerReentrancyGuard() (gas: 127793) -MulticallerTest:testMulticallerWithSignerRevert() (gas: 211886) -MulticallerTest:testMulticallerWithSignerRevertsWithNastyArrayLength() (gas: 9663) -MulticallerTest:testMulticallerWithSignerWithNoData() (gas: 132142) -MulticallerTest:testNastyCalldataRevert() (gas: 30988) -MulticallerTest:testOffsetTrick(uint256,uint256,uint256) (runs: 256, μ: 549, ~: 549) -MulticallerTest:test__codesize() (gas: 49507) +MulticallerTest:testMultiCallerWithSignerIncrementNonceSalt(uint256) (runs: 256, μ: 79117, ~: 81170) +MulticallerTest:testMultiCallerWithSignerIncrementNonceSaltWithERC1271(uint256) (runs: 256, μ: 579599, ~: 579578) +MulticallerTest:testMulticallerCdFallback(string) (runs: 256, μ: 307142, ~: 301941) +MulticallerTest:testMulticallerForwardsMessageValue() (gas: 213836) +MulticallerTest:testMulticallerGetNames() (gas: 147569) +MulticallerTest:testMulticallerReentrancyGuard() (gas: 18370) +MulticallerTest:testMulticallerRefund(uint256) (runs: 256, μ: 169958, ~: 171973) +MulticallerTest:testMulticallerReturnDataIsProperlyEncoded() (gas: 122104) +MulticallerTest:testMulticallerReturnDataIsProperlyEncoded(string,string,uint256) (runs: 256, μ: 523865, ~: 513971) +MulticallerTest:testMulticallerReturnDataIsProperlyEncoded(uint256,uint256,uint256,uint256) (runs: 256, μ: 122228, ~: 122228) +MulticallerTest:testMulticallerRevertWithCustomError() (gas: 32024) +MulticallerTest:testMulticallerRevertWithMessage() (gas: 34819) +MulticallerTest:testMulticallerRevertWithMessage(string) (runs: 256, μ: 35689, ~: 35751) +MulticallerTest:testMulticallerRevertWithNothing() (gas: 31867) +MulticallerTest:testMulticallerSenderDoesNotRevertWithoutMulticallerDeployed() (gas: 3408) +MulticallerTest:testMulticallerTargetGetMulticallerSender() (gas: 27451) +MulticallerTest:testMulticallerWithNoData() (gas: 16181) +MulticallerTest:testMulticallerWithSigner(uint256) (runs: 256, μ: 129847, ~: 122128) +MulticallerTest:testMulticallerWithSignerEIP712Domain() (gas: 12442) +MulticallerTest:testMulticallerWithSignerGetMulticallerSigner() (gas: 139939) +MulticallerTest:testMulticallerWithSignerInvalidateNonces(uint256) (runs: 256, μ: 82230, ~: 80039) +MulticallerTest:testMulticallerWithSignerInvalidateNoncesWithERC1271(uint256) (runs: 256, μ: 585512, ~: 584949) +MulticallerTest:testMulticallerWithSignerNonPayableFunctions() (gas: 48928) +MulticallerTest:testMulticallerWithSignerReentrancyGuard() (gas: 127316) +MulticallerTest:testMulticallerWithSignerRevert() (gas: 211551) +MulticallerTest:testMulticallerWithSignerRevertsWithNastyArrayLength() (gas: 9297) +MulticallerTest:testMulticallerWithSignerWithERC1271(uint256) (runs: 256, μ: 630394, ~: 606221) +MulticallerTest:testMulticallerWithSignerWithNoData() (gas: 131563) +MulticallerTest:testNastyCalldataRevert() (gas: 30788) +MulticallerTest:testOffsetTrick(uint256,uint256,uint256) (runs: 256, μ: 571, ~: 571) +MulticallerTest:test__codesize() (gas: 50447) TestPlus:test__codesize() (gas: 1102) \ No newline at end of file diff --git a/API.md b/API.md index 677d817..feb69fa 100644 --- a/API.md +++ b/API.md @@ -329,7 +329,7 @@ The address of the multicaller with sender contract. #### `MULTICALLER_WITH_SIGNER` ```solidity address internal constant MULTICALLER_WITH_SIGNER = - 0x0000000000007e02fB2d04caa1C19Ac15d8E77A3; + 0x0000000000007DeD88fff5c18A2Bb6254ECd4130; ``` The address of the multicaller with signer contract. diff --git a/README.md b/README.md index 0e1766e..67e5731 100644 --- a/README.md +++ b/README.md @@ -13,31 +13,31 @@ Enables "forwarding" of `msg.sender` to the contracts called. - Ethereum - Multicaller: [`0x0000000000009C27972b97d86134DFcffACAbE15`](https://etherscan.io/address/0x0000000000009C27972b97d86134DFcffACAbE15) - MulticallerWithSender: [`0x00000000002Fd5Aeb385D324B580FCa7c83823A0`](https://etherscan.io/address/0x00000000002Fd5Aeb385D324B580FCa7c83823A0) - - MulticallerWithSigner: [`0x0000000000007e02fB2d04caa1C19Ac15d8E77A3`](https://etherscan.io/address/0x0000000000007e02fB2d04caa1C19Ac15d8E77A3) + - MulticallerWithSigner: [`0x0000000000007DeD88fff5c18A2Bb6254ECd4130`](https://etherscan.io/address/0x0000000000007DeD88fff5c18A2Bb6254ECd4130) - Goerli - Multicaller: [`0x0000000000009C27972b97d86134DFcffACAbE15`](https://goerli.etherscan.io/address/0x0000000000009C27972b97d86134DFcffACAbE15) - MulticallerWithSender: [`0x00000000002Fd5Aeb385D324B580FCa7c83823A0`](https://goerli.etherscan.io/address/0x00000000002Fd5Aeb385D324B580FCa7c83823A0) - - MulticallerWithSigner: [`0x0000000000007e02fB2d04caa1C19Ac15d8E77A3`](https://goerli.etherscan.io/address/0x0000000000007e02fB2d04caa1C19Ac15d8E77A3) + - MulticallerWithSigner: [`0x0000000000007DeD88fff5c18A2Bb6254ECd4130`](https://goerli.etherscan.io/address/0x0000000000007DeD88fff5c18A2Bb6254ECd4130) - Sepolia - Multicaller: [`0x0000000000009C27972b97d86134DFcffACAbE15`](https://sepolia.etherscan.io/address/0x0000000000009C27972b97d86134DFcffACAbE15) - MulticallerWithSender: [`0x00000000002Fd5Aeb385D324B580FCa7c83823A0`](https://sepolia.etherscan.io/address/0x00000000002Fd5Aeb385D324B580FCa7c83823A0) - - MulticallerWithSigner: [`0x0000000000007e02fB2d04caa1C19Ac15d8E77A3`](https://sepolia.etherscan.io/address/0x0000000000007e02fB2d04caa1C19Ac15d8E77A3) + - MulticallerWithSigner: [`0x0000000000007DeD88fff5c18A2Bb6254ECd4130`](https://sepolia.etherscan.io/address/0x0000000000007DeD88fff5c18A2Bb6254ECd4130) - Polygon - Multicaller: [`0x0000000000009C27972b97d86134DFcffACAbE15`](https://polygonscan.com/address/0x0000000000009C27972b97d86134DFcffACAbE15) - MulticallerWithSender: [`0x00000000002Fd5Aeb385D324B580FCa7c83823A0`](https://polygonscan.com/address/0x00000000002Fd5Aeb385D324B580FCa7c83823A0) - - MulticallerWithSigner: [`0x0000000000007e02fB2d04caa1C19Ac15d8E77A3`](https://polygonscan.com/address/0x0000000000007e02fB2d04caa1C19Ac15d8E77A3) + - MulticallerWithSigner: [`0x0000000000007DeD88fff5c18A2Bb6254ECd4130`](https://polygonscan.com/address/0x0000000000007DeD88fff5c18A2Bb6254ECd4130) - Mumbai - Multicaller: [`0x0000000000009C27972b97d86134DFcffACAbE15`](https://mumbai.polygonscan.com/address/0x0000000000009C27972b97d86134DFcffACAbE15) - MulticallerWithSender: [`0x00000000002Fd5Aeb385D324B580FCa7c83823A0`](https://mumbai.polygonscan.com/address/0x00000000002Fd5Aeb385D324B580FCa7c83823A0) - - MulticallerWithSigner: [`0x0000000000007e02fB2d04caa1C19Ac15d8E77A3`](https://mumbai.polygonscan.com/address/0x0000000000007e02fB2d04caa1C19Ac15d8E77A3) + - MulticallerWithSigner: [`0x0000000000007DeD88fff5c18A2Bb6254ECd4130`](https://mumbai.polygonscan.com/address/0x0000000000007DeD88fff5c18A2Bb6254ECd4130) - Optimism - Multicaller: [`0x0000000000009C27972b97d86134DFcffACAbE15`](https://optimistic.etherscan.io/address/0x0000000000009C27972b97d86134DFcffACAbE15) - MulticallerWithSender: [`0x00000000002Fd5Aeb385D324B580FCa7c83823A0`](https://optimistic.etherscan.io/address/0x00000000002Fd5Aeb385D324B580FCa7c83823A0) - - MulticallerWithSigner: [`0x0000000000007e02fB2d04caa1C19Ac15d8E77A3`](https://optimistic.etherscan.io/address/0x0000000000007e02fB2d04caa1C19Ac15d8E77A3) + - MulticallerWithSigner: [`0x0000000000007DeD88fff5c18A2Bb6254ECd4130`](https://optimistic.etherscan.io/address/0x0000000000007DeD88fff5c18A2Bb6254ECd4130) - Arbitrum - Multicaller: [`0x0000000000009C27972b97d86134DFcffACAbE15`](https://arbiscan.io/address/0x0000000000009C27972b97d86134DFcffACAbE15) - MulticallerWithSender: [`0x00000000002Fd5Aeb385D324B580FCa7c83823A0`](https://arbiscan.io/address/0x00000000002Fd5Aeb385D324B580FCa7c83823A0) - - MulticallerWithSigner: [`0x0000000000007e02fB2d04caa1C19Ac15d8E77A3`](https://arbiscan.io/address/0x0000000000007e02fB2d04caa1C19Ac15d8E77A3) + - MulticallerWithSigner: [`0x0000000000007DeD88fff5c18A2Bb6254ECd4130`](https://arbiscan.io/address/0x0000000000007DeD88fff5c18A2Bb6254ECd4130) Please open an issue if you need help to deploy to an EVM chain of your choice. diff --git a/src/LibMulticaller.sol b/src/LibMulticaller.sol index fedb7f6..4ebdd8b 100644 --- a/src/LibMulticaller.sol +++ b/src/LibMulticaller.sol @@ -20,7 +20,7 @@ library LibMulticaller { /** * @dev The address of the multicaller with signer contract. */ - address internal constant MULTICALLER_WITH_SIGNER = 0x0000000000007e02fB2d04caa1C19Ac15d8E77A3; + address internal constant MULTICALLER_WITH_SIGNER = 0x0000000000007DeD88fff5c18A2Bb6254ECd4130; /** * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`. diff --git a/test/Multicaller.t.sol b/test/Multicaller.t.sol index 2a7436e..004002b 100644 --- a/test/Multicaller.t.sol +++ b/test/Multicaller.t.sol @@ -120,16 +120,16 @@ contract MulticallerTest is TestPlus { 0x00000000002Fd5Aeb385D324B580FCa7c83823A0; bytes public constant MULTICALLER_WITH_SIGNER_INITCODE = - hex"6080806040523060a01b3d55610a1590816100188239f3fe6040608081526004361015610020575b50361561001b57600080fd5b610735565b6000803560e01c91826317447cf1146100aa57505080632eb48a80146100a55780633aeb2206146100a05780634eb311501461009b57806356b1a87f1461009657806384b0196e1461009157806387ec11ca1461008c5763f0c60f1a14610087573861000f565b6106e2565b610512565b6104bd565b610337565b610292565b610241565b6101a7565b3461012b578060031936011261012b576100c261012f565b916024359067ffffffffffffffff821161012857506100e5903690600401610176565b90923d528060051b923d3d905b8581036101075750505060203d52602052013df35b80602091840135808352603f8420549060ff161c60011681870152016100f2565b80fd5b5080fd5b600435906001600160a01b038216820361014557565b600080fd5b60a435906001600160a01b038216820361014557565b602435906001600160a01b038216820361014557565b9181601f840112156101455782359167ffffffffffffffff8311610145576020808501948460051b01011161014557565b34610145576020806003193601126101455760043567ffffffffffffffff8111610145576101d9903690600401610176565b90333d528160051b913d3d905b8481036102225750508383943d52526040377fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a433916040013da2005b8086918501358083526001603f85209160ff161b8154179055016101e6565b346101455760203660031901126101455761025a61012f565b3001543d5260203df35b9181601f840112156101455782359167ffffffffffffffff8311610145576020838186019501011161014557565b60e03660031901126101455767ffffffffffffffff60048035828111610145576102bf9036908301610264565b9190602435848111610145576102d89036908401610176565b9094604435818111610145576102f19036908601610176565b90606435838111610145576103099036908801610176565b94909361031461014a565b9760c4359182116101455761032b91369101610264565b99909860843597610747565b346101455760403660031901126101455761035061012f565b6024359067ffffffffffffffff8211610145576103736041923690600401610264565b308301918254917f898da98c106c91ce6f05405740b0ed23b5c4dc847a0dd1996fb93189d8310bef3d52602095869284845260403d206040527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6060527f301013e8a31863902646dc218ecd889c37491c2967a8104d5ff1cf42af0f9ea46080527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660a0524660c0523060e05260a060602084526119013d526042601e203d526040376080513d1a825260803d913d9060416fa2a8918ca85bafe22016d0b997e4df5f600160ff1b03606051109114165afa5082600051143d02156104af5760019060001943014060e01c01018091556000527f997a42216df16c8b9e7caf2fc71c59dba956f1f2b12320f87a80a5879464217d826000a26000f35b638baa579f6000526004601cfd5b3461014557600036600319011261014557600f3d5360e060205275154d756c746963616c6c6572576974685369676e657260f55261012060405261013161012152466060523060805261016060c0526101803df35b346101455760603660031901126101455767ffffffffffffffff60043581811161014557610544903690600401610176565b61054c610160565b91604435938411610145576105676041943690600401610264565b92908160051b937fe75b4aefef1358e66ac7ed2f180022e0a7f661dcd2781630ce58e05bb8bdb1c13d5260209687928686853786842084523088015460405260603d206040527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6060527f301013e8a31863902646dc218ecd889c37491c2967a8104d5ff1cf42af0f9ea46080527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660a0524660c0523060e05260a060602084526119013d526042601e203d526040376080513d1a825260803d913d9060416fa2a8918ca85bafe22016d0b997e4df5f600160ff1b03606051109114165afa50600094848651143d02156106d557848652855b8481036106b65750808652527fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a49190819060403760400183a280f35b8082918501358083526001603f8a209160ff161b81541790550161067a565b638baa579f86526004601cfd5b34610145576000366003190112610145573033016001815460001943014060e01c01018091553d52337f997a42216df16c8b9e7caf2fc71c59dba956f1f2b12320f87a80a5879464217d60203da260203df35b3d546001600160a01b03163d5260203df35b96919a9098949792979593956060928114818a1416156109d2573d5460a01c156109c5577fc4d2f044d99707794280032fc14879a220a3f7dc766d75100809624f91d69e973d5260051b9860209788929190819084378220825260409a8a8d8d378a8c208c523d5b8b81036109a157508a8420845260416080918c8884378c832083528660a0523089015460c0528d60e03d2090527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f86527f301013e8a31863902646dc218ecd889c37491c2967a8104d5ff1cf42af0f9ea483527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660a0524660c0523060e05260a0862085526119013d526042601e203d528d3780513d1a83523d913d9060416fa2a8918ca85bafe22016d0b997e4df5f600160ff1b038751109114165afa50600099848b51143d0294808c52838852603f93848d20805497600198898460ff161b9181831690151761099357179055888d528689528b52807fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a4848ea2891561098c5785949392918b978d9283558b818a378c8c8101975b610919575b8b8b523060a01b84558c0183f35b9883808c839f969798999a9b9c845186019088019481869235938491018337603f19818e0181013591890101355af11561098357838b918f958f523d90523d868883013e3d018701601f19169c0198888a1461097b5797969594939288610906565b50839261090b565b843d81803e3d90fd5b8a8c8b8a52f35b50638baa579f8f526004601cfd5b91929091848101898201358a018035908190850183378120905201908892916107af565b63ab143c063d526004601cfd5b633b800a463d526004601cfdfea2646970667358221220ce833c059ba8793f41734fd367450eb73d017797c50fe9f80ca2956db217ef8164736f6c63430008120033"; + hex"6080806040523060a01b3d55610b0890816100188239f3fe6040608081526004361015610020575b50361561001b57600080fd5b6107d4565b6000803560e01c91826317447cf1146100aa57505080632eb48a80146100a55780633aeb2206146100a05780634eb311501461009b57806356b1a87f1461009657806384b0196e1461009157806387ec11ca1461008c5763f0c60f1a14610087573861000f565b61077e565b610564565b61050f565b610334565b61028f565b61023e565b6101a3565b346101275780600319360112610127576100c261012b565b9060243567ffffffffffffffff8111610123576100e3903690600401610172565b909284528060051b92845b848103610102575050602084526020520190f35b80602091830135808352603f8820549060ff161c60011681860152016100ee565b8380fd5b5080fd5b600435906001600160a01b038216820361014157565b600080fd5b60a435906001600160a01b038216820361014157565b602435906001600160a01b038216820361014157565b9181601f840112156101415782359167ffffffffffffffff8311610141576020808501948460051b01011161014157565b34610141576020806003193601126101415760043567ffffffffffffffff8111610141576101d5903690600401610172565b6000913383528160051b91835b83810361021f5750848495849552526040377fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a4339160400183a280f35b8086918401358083526001603f88209160ff161b8154179055016101e2565b346101415760203660031901126101415761025761012b565b3001543d5260203df35b9181601f840112156101415782359167ffffffffffffffff8311610141576020838186019501011161014157565b60e03660031901126101415767ffffffffffffffff60048035828111610141576102bc9036908301610261565b9190602435848111610141576102d59036908401610172565b9094604435818111610141576102ee9036908601610172565b90606435838111610141576103069036908801610172565b949093610311610146565b9760c4359182116101415761032891369101610261565b999098608435976107e6565b346101415760403660031901126101415761034d61012b565b60243567ffffffffffffffff81116101415761036d903690600401610261565b9190308201908154907f898da98c106c91ce6f05405740b0ed23b5c4dc847a0dd1996fb93189d8310bef3d5260209482865260403d206040527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6060527f301013e8a31863902646dc218ecd889c37491c2967a8104d5ff1cf42af0f9ea46080527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660a0524660c0523060e05260a060602086526119013d52856042601e2091600093604182146104d2575b8415610494575b50505050156104865760019060001943014060e01c01018091556000527f997a42216df16c8b9e7caf2fc71c59dba956f1f2b12320f87a80a5879464217d826000a26000f35b638baa579f6000526004601cfd5b6000929394509080606492630b135d3f60e11b9687865260045260406024528160445283370181875afa90853d149060005114161638858180610440565b93600160808492863d52848860403781513d1a84526fa2a8918ca85bafe22016d0b997e4df5f600160ff1b03606051105afa5187143d0293610439565b3461014157600036600319011261014157600f3d5360e060205275154d756c746963616c6c6572576974685369676e657260f55261012060405261013161012152466060523060805261016060c0526101803df35b346101415760603660031901126101415767ffffffffffffffff60043581811161014157610596903690600401610172565b6105a192919261015c565b91604435908111610141576105ba903690600401610261565b90938260051b927fe75b4aefef1358e66ac7ed2f180022e0a7f661dcd2781630ce58e05bb8bdb1c13d526020958483883784872087523086015493604094855260603d2085527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6060527f301013e8a31863902646dc218ecd889c37491c2967a8104d5ff1cf42af0f9ea46080527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660a0524660c0523060e05260a060602088526119013d52876042601e209160009360418214610742575b8415610705575b5050505015610486578460005260005b8481036106e55750908391867fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a49697600052528237016000a2005b8087918401358083526001603f6000209160ff161b8154179055016106aa565b6000929394509080606492630b135d3f60e11b96878652600452896024528160445283370181895afa90873d14906000511416163887818061069a565b93600160808492863d5284888c3781513d1a84526fa2a8918ca85bafe22016d0b997e4df5f600160ff1b03606051105afa5189143d0293610693565b34610141576000806003193601126107d1576020903033016001815460001943014060e01c01018091558152337f997a42216df16c8b9e7caf2fc71c59dba956f1f2b12320f87a80a5879464217d8383a2f35b80fd5b3d546001600160a01b03163d5260203df35b97919099959498939692986060938114818b141615610ac5573d5460a01c15610ab85760059b9a9b1b997fc4d2f044d99707794280032fc14879a220a3f7dc766d75100809624f91d69e973d528b60209c8d9a8b378920895260409b8c918c8484378c832083523d5b8d8103610a9557508c862086526080988d898b378d8a208a528560a0523088015460c05260e03d2084527f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f87527f301013e8a31863902646dc218ecd889c37491c2967a8104d5ff1cf42af0f9ea48a527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660a0524660c0523060e05260a0872083526119013d526042601e209360009a60418414610a5a575b508a15610a1a575b505050505083600052818852603f938460002092835493600198898360ff161b90868216901517610486578e9517905589600052878a528352807fc45e3a0dd412bcad8d62398d74d66b1c8449f38beb10da275e4da0c6d3a811a4856000a28a15610a12578695949392506000558a968a818d378b8b8101965b61099f575b8b8b8b523060a01b600055016000f35b976000808b839e969798999a9b845186019088019481869235938491018337603f19818d0181013591890101355af115610a0857838a918e958e523d90523d60008783013e3d018601601f19169b0197878914610a015796959493928761098a565b508261098f565b3d6000803e3d6000fd5b828b8a526000f35b60009394959a50918091606493630b135d3f60e11b978887526004526024528160445283370181875afa90883d149060005114161694388881808e610910565b600190829c858588958a3d523781513d1a84526fa2a8918ca85bafe22016d0b997e4df5f600160ff1b038b51105afa5188143d029938610908565b9092508581018a8201358b0180359081908501833781209052018c918a9161084f565b63ab143c063d526004601cfd5b633b800a463d526004601cfdfea2646970667358221220d3c4d3ef5d014ffa12aba8a974a78788effac209c2d0add0a68d19f1a19b18ed64736f6c63430008120033"; bytes32 public constant MULTICALLER_WITH_SIGNER_INITCODEHASH = - 0xc54b4e80bb03857655d55c63bc0642e77fc99bbf7794dc378cdeef8e6ebe1e54; + 0x26bc769329f915c0c057ae95434fa59a795c3a23332d8e16241c1461e8ca0f7b; bytes32 public constant MULTICALLER_WITH_SIGNER_CREATE2_SALT = - 0x00000000000000000000000000000000000000000d3c0c72da50c60112190282; + 0x0000000000000000000000000000000000000000c6bc6bef0708920389010934; address public constant MULTICALLER_WITH_SIGNER_CREATE2_DEPLOYED_ADDRESS = - 0x0000000000007e02fB2d04caa1C19Ac15d8E77A3; + 0x0000000000007DeD88fff5c18A2Bb6254ECd4130; Multicaller multicaller; MulticallerWithSender multicallerWithSender; @@ -186,10 +186,10 @@ contract MulticallerTest is TestPlus { // vm.etch(LibMulticaller.MULTICALLER, address(new Multicaller()).code); // multicaller = Multicaller(payable(LibMulticaller.MULTICALLER)); - vm.etch(LibMulticaller.MULTICALLER_WITH_SIGNER, address(new MulticallerWithSigner()).code); - vm.store(LibMulticaller.MULTICALLER_WITH_SIGNER, 0, bytes32(uint256(1 << 160))); - multicallerWithSigner = - MulticallerWithSigner(payable(LibMulticaller.MULTICALLER_WITH_SIGNER)); + // vm.etch(LibMulticaller.MULTICALLER_WITH_SIGNER, address(new MulticallerWithSigner()).code); + // vm.store(LibMulticaller.MULTICALLER_WITH_SIGNER, 0, bytes32(uint256(1 << 160))); + // multicallerWithSigner = + // MulticallerWithSigner(payable(LibMulticaller.MULTICALLER_WITH_SIGNER)); _deployTargets(); }