Skip to content

Commit f4c92b6

Browse files
authored
Refactor TrailsRouter to accept Multicall3 address as a constructor argument (#83)
* Refactor TrailsRouter to accept Multicall3 address as a constructor argument - Updated TrailsRouter contract to initialize MULTICALL3 address via constructor instead of as an immutable variable. - Modified deployRouter function to pass Multicall3 address during TrailsRouter deployment. - Added a mock AlwaysFailingMulticall3 for testing purposes to simulate failure scenarios in tests. - Updated relevant test cases to reflect changes in constructor and deployment logic. * Update gas snapshots and modify expectedRouterAddress to include Multicall3 address - Adjusted gas usage for various test cases in TrailsRouter and TrailsRouterTest to reflect recent performance changes. - Updated expectedRouterAddress function in TrailsRouterDeploymentTest and TrailsRouterShimDeploymentTest to incorporate the Multicall3 address in the CREATE2 address calculation. * Change MULTICALL3 to immutable in TrailsRouter contract - Updated the MULTICALL3 state variable in the TrailsRouter contract to be immutable, ensuring it can only be set once during contract deployment. This change enhances gas efficiency and contract integrity. * Update gas snapshots for TrailsRouter and TrailsRouterTest - Adjusted gas usage metrics for various test cases in TrailsRouter and TrailsRouterTest to reflect recent performance optimizations. - Minor updates made to individual test cases for consistency and accuracy in gas calculations. * Update TrailsRouter contract to rename state variables to immutable variables - Changed the comment for the MULTICALL3 variable to clarify its immutable status, enhancing code readability and consistency with naming conventions.
1 parent 7a45b1e commit f4c92b6

File tree

7 files changed

+46
-29
lines changed

7 files changed

+46
-29
lines changed

.gas-snapshot

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,20 @@ TrailsIntentEntrypointTest:testNonceIncrementsOnDeposit() (gas: 91830)
5252
TrailsIntentEntrypointTest:testPermitAmountExcessiveWithFee() (gas: 61879)
5353
TrailsIntentEntrypointTest:testPermitAmountInsufficientWithFee() (gas: 60889)
5454
TrailsIntentEntrypointTest:testVersionConstant() (gas: 10506)
55-
TrailsRouterDeploymentTest:test_DeployTrailsRouter_SameAddress() (gas: 1856117)
56-
TrailsRouterDeploymentTest:test_DeployTrailsRouter_Success() (gas: 1846511)
57-
TrailsRouterDeploymentTest:test_DeployedRouter_HasCorrectConfiguration() (gas: 1846307)
58-
TrailsRouterShimDeploymentTest:test_DeployRouterShim_SameAddress() (gas: 7530847)
59-
TrailsRouterShimDeploymentTest:test_DeployRouterShim_Success() (gas: 4873481)
60-
TrailsRouterShimDeploymentTest:test_DeployedContract_HasCorrectConfiguration() (gas: 4873526)
55+
TrailsRouterDeploymentTest:test_DeployTrailsRouter_SameAddress() (gas: 1864438)
56+
TrailsRouterDeploymentTest:test_DeployTrailsRouter_Success() (gas: 1852254)
57+
TrailsRouterDeploymentTest:test_DeployedRouter_HasCorrectConfiguration() (gas: 1852050)
58+
TrailsRouterShimDeploymentTest:test_DeployRouterShim_SameAddress() (gas: 7613006)
59+
TrailsRouterShimDeploymentTest:test_DeployRouterShim_Success() (gas: 4916218)
60+
TrailsRouterShimDeploymentTest:test_DeployedContract_HasCorrectConfiguration() (gas: 4916264)
6161
TrailsRouterShimTest:testConstructorValidation() (gas: 69336)
6262
TrailsRouterShimTest:testForwardToRouterReturnValue() (gas: 713355)
6363
TrailsRouterShimTest:testRouterAddressImmutable() (gas: 1391679)
6464
TrailsRouterShimTest:test_constructor_revert_zeroRouter() (gas: 68984)
65-
TrailsRouterShimTest:test_delegatecall_forwards_and_sets_sentinel_sstore_inactive() (gas: 1848663)
65+
TrailsRouterShimTest:test_delegatecall_forwards_and_sets_sentinel_sstore_inactive() (gas: 1848930)
6666
TrailsRouterShimTest:test_delegatecall_forwards_and_sets_sentinel_tstore_active() (gas: 38392)
6767
TrailsRouterShimTest:test_delegatecall_router_revert_bubbles_as_RouterCallFailed() (gas: 82109)
68-
TrailsRouterShimTest:test_delegatecall_sets_sentinel_with_sstore_when_no_tstore() (gas: 1830888)
68+
TrailsRouterShimTest:test_delegatecall_sets_sentinel_with_sstore_when_no_tstore() (gas: 1831155)
6969
TrailsRouterShimTest:test_delegatecall_sets_sentinel_with_tstore_when_supported() (gas: 20706)
7070
TrailsRouterShimTest:test_direct_handleSequenceDelegateCall_reverts_not_delegatecall() (gas: 9840)
7171
TrailsRouterShimTest:test_forwardToRouter_return_data_handling() (gas: 729052)
@@ -78,7 +78,7 @@ TrailsRouterShimTest:test_handleSequenceDelegateCall_with_eth_value() (gas: 3210
7878
TrailsRouterShimTest:test_handleSequenceDelegateCall_zero_call_value() (gas: 26873)
7979
TrailsRouterShimTest:test_sentinel_setting_with_different_op_hashes() (gas: 36405)
8080
TrailsRouterTest:testDelegateCallWithETH() (gas: 326226)
81-
TrailsRouterTest:testExecute_WithFailingMulticall() (gas: 450176)
81+
TrailsRouterTest:testExecute_WithFailingMulticall() (gas: 156745)
8282
TrailsRouterTest:testHandleSequenceDelegateCall_InjectAndCall() (gas: 72655)
8383
TrailsRouterTest:testHandleSequenceDelegateCall_RefundAndSweep() (gas: 85388)
8484
TrailsRouterTest:testHandleSequenceDelegateCall_Sweep() (gas: 48693)
@@ -133,7 +133,7 @@ TrailsRouterTest:test_pullAmountAndExecute_WithToken_ShouldTransferAndExecute()
133133
TrailsRouterTest:test_pullAmountAndExecute_WithValidToken_ShouldTransferAndExecute() (gas: 75490)
134134
TrailsRouterTest:test_pullAndExecute_WithETH_NoEthSent() (gas: 18454)
135135
TrailsRouterTest:test_pullAndExecute_WithETH_ShouldTransferAndExecute() (gas: 72439)
136-
TrailsRouterTest:test_pullAndExecute_WithFailingMulticall() (gas: 494404)
136+
TrailsRouterTest:test_pullAndExecute_WithFailingMulticall() (gas: 202286)
137137
TrailsRouterTest:test_pullAndExecute_WithToken_IncorrectValue() (gas: 60552)
138138
TrailsRouterTest:test_pullAndExecute_WithValidToken_ShouldTransferFullBalanceAndExecute() (gas: 77324)
139139
TrailsRouterTest:test_refundAndSweep_erc20_partialRefund() (gas: 110365)

script/TrailsRouter.s.sol

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ contract Deploy is SingletonDeployer {
2424

2525
function deployRouter(uint256 pk) public returns (address) {
2626
bytes32 salt = bytes32(0);
27+
address multicall3 = 0xcA11bde05977b3631167028862bE2a173976CA11;
2728

28-
// Deploy TrailsRouter
29-
bytes memory initCode = type(TrailsRouter).creationCode;
29+
// Deploy TrailsRouter with constructor arguments
30+
bytes memory initCode = abi.encodePacked(type(TrailsRouter).creationCode, abi.encode(multicall3));
3031
address router = _deployIfNotAlready("TrailsRouter", initCode, salt, pk);
3132

3233
return router;

src/TrailsRouter.sol

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ contract TrailsRouter is IDelegatedExtension, ITrailsRouter, DelegatecallGuard,
2424
// Immutable Variables
2525
// -------------------------------------------------------------------------
2626

27-
address public immutable MULTICALL3 = 0xcA11bde05977b3631167028862bE2a173976CA11;
27+
address public immutable MULTICALL3;
28+
29+
// -------------------------------------------------------------------------
30+
// Constructor
31+
// -------------------------------------------------------------------------
32+
33+
constructor(address _multicall3) {
34+
MULTICALL3 = _multicall3;
35+
}
2836

2937
// -------------------------------------------------------------------------
3038
// Errors

test/TrailsRouter.t.sol

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ contract RevertingReceiver {
4949
}
5050
}
5151

52+
// Mock multicall that always fails (for testing storage conflicts)
53+
contract AlwaysFailingMulticall3 {
54+
function aggregate3(IMulticall3.Call3[] calldata) external payable {
55+
revert("MockMulticall3: forced failure");
56+
}
57+
58+
function aggregate3Value(IMulticall3.Call3Value[] calldata) external payable {
59+
revert("MockMulticall3: forced failure");
60+
}
61+
}
62+
5263
contract MockTarget {
5364
uint256 public lastAmount;
5465
bool public shouldRevert;
@@ -199,7 +210,7 @@ contract TrailsRouterTest is Test {
199210
MockMulticall3 mockMulticall3 = new MockMulticall3();
200211
vm.etch(0xcA11bde05977b3631167028862bE2a173976CA11, address(mockMulticall3).code);
201212

202-
router = new TrailsRouter();
213+
router = new TrailsRouter(0xcA11bde05977b3631167028862bE2a173976CA11);
203214
getter = new MockSenderGetter();
204215
mockToken = new MockERC20("MockToken", "MTK", 18);
205216
failingToken = new FailingToken();
@@ -865,17 +876,13 @@ contract TrailsRouterTest is Test {
865876
// Save original multicall code
866877
bytes memory originalCode = 0xcA11bde05977b3631167028862bE2a173976CA11.code;
867878

868-
// Deploy and etch failing multicall
869-
MockMulticall3 failingMulticall = new MockMulticall3();
879+
// Deploy and etch always-failing multicall (doesn't use storage, always reverts)
880+
AlwaysFailingMulticall3 failingMulticall = new AlwaysFailingMulticall3();
870881
vm.etch(0xcA11bde05977b3631167028862bE2a173976CA11, address(failingMulticall).code);
871882

872883
// Verify the etch worked
873884
assertEq(keccak256(0xcA11bde05977b3631167028862bE2a173976CA11.code), keccak256(address(failingMulticall).code));
874885

875-
// Set the failure flag directly in storage since delegatecall uses caller's storage
876-
// The shouldFail variable is at slot 0 in MockMulticall3
877-
vm.store(address(router), bytes32(0), bytes32(uint256(1))); // Set shouldFail = true in router's storage
878-
879886
IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](1);
880887
calls[0] = IMulticall3.Call3({
881888
target: address(getter), allowFailure: false, callData: abi.encodeWithSignature("getSender()")
@@ -901,13 +908,10 @@ contract TrailsRouterTest is Test {
901908
// Save original multicall code
902909
bytes memory originalCode = 0xcA11bde05977b3631167028862bE2a173976CA11.code;
903910

904-
// Mock multicall3 to return failure
905-
MockMulticall3 failingMulticall = new MockMulticall3();
911+
// Deploy and etch always-failing multicall (doesn't use storage, always reverts)
912+
AlwaysFailingMulticall3 failingMulticall = new AlwaysFailingMulticall3();
906913
vm.etch(0xcA11bde05977b3631167028862bE2a173976CA11, address(failingMulticall).code);
907914

908-
// Set the failure flag directly in storage since delegatecall uses caller's storage
909-
vm.store(address(router), bytes32(0), bytes32(uint256(1))); // Set shouldFail = true in router's storage
910-
911915
IMulticall3.Call3[] memory calls = new IMulticall3.Call3[](1);
912916
calls[0] = IMulticall3.Call3({
913917
target: address(getter), allowFailure: false, callData: abi.encodeWithSignature("getSender()")

test/TrailsRouterShim.t.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ contract TrailsRouterShimTest is Test {
253253

254254
// Verify sentinel by re-etching TrailsRouter and validating via delegated entrypoint
255255
bytes memory original = address(shimImpl).code;
256-
vm.etch(holder, address(new TrailsRouter()).code);
256+
vm.etch(holder, address(new TrailsRouter(0xcA11bde05977b3631167028862bE2a173976CA11)).code);
257257

258258
address payable recipient = payable(address(0x111));
259259
vm.deal(holder, callValue);
@@ -309,7 +309,7 @@ contract TrailsRouterShimTest is Test {
309309

310310
// Verify via TrailsRouter delegated validation
311311
bytes memory original = address(shimImpl).code;
312-
vm.etch(holder, address(new TrailsRouter()).code);
312+
vm.etch(holder, address(new TrailsRouter(0xcA11bde05977b3631167028862bE2a173976CA11)).code);
313313
address payable recipient = payable(address(0x112));
314314
vm.deal(holder, 1 ether);
315315
bytes memory data =

test/script/TrailsRouter.s.t.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ contract TrailsRouterDeploymentTest is Test {
2626

2727
// Expected predetermined address (calculated using CREATE2)
2828
function expectedRouterAddress() internal pure returns (address payable) {
29-
return Create2Utils.calculateCreate2Address(type(TrailsRouter).creationCode, Create2Utils.standardSalt());
29+
address multicall3 = 0xcA11bde05977b3631167028862bE2a173976CA11;
30+
bytes memory initCode = abi.encodePacked(type(TrailsRouter).creationCode, abi.encode(multicall3));
31+
return Create2Utils.calculateCreate2Address(initCode, Create2Utils.standardSalt());
3032
}
3133

3234
// -------------------------------------------------------------------------

test/script/TrailsRouterShim.s.t.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ contract TrailsRouterShimDeploymentTest is Test {
2727

2828
// Expected predetermined addresses (calculated using CREATE2)
2929
function expectedRouterAddress() internal pure returns (address payable) {
30-
return Create2Utils.calculateCreate2Address(type(TrailsRouter).creationCode, Create2Utils.standardSalt());
30+
address multicall3 = 0xcA11bde05977b3631167028862bE2a173976CA11;
31+
bytes memory initCode = abi.encodePacked(type(TrailsRouter).creationCode, abi.encode(multicall3));
32+
return Create2Utils.calculateCreate2Address(initCode, Create2Utils.standardSalt());
3133
}
3234

3335
function expectedShimAddress() internal pure returns (address payable) {

0 commit comments

Comments
 (0)