Skip to content

Commit fe0dbae

Browse files
authored
feat: Host fuzz tests (#90)
* zenith fuzz tests * move zenith fuzz * Passage Fuzz * TransactFuzzTest * update snapshot * forge update * fix: impl disallowed enter test
1 parent a2109b4 commit fe0dbae

File tree

8 files changed

+549
-36
lines changed

8 files changed

+549
-36
lines changed

.gas-snapshot

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,60 @@
11
GnosisSafeTest:test_gnosis_receive() (gas: 16106)
2-
OrderOriginPermit2Test:test_fillPermit2() (gas: 174723)
3-
OrderOriginPermit2Test:test_fillPermit2_multi() (gas: 510586)
4-
OrderOriginPermit2Test:test_initiatePermit2() (gas: 187081)
5-
OrderOriginPermit2Test:test_initiatePermit2_multi() (gas: 470943)
6-
OrdersTest:test_fill_ERC20() (gas: 76273)
7-
OrdersTest:test_fill_ETH() (gas: 73740)
8-
OrdersTest:test_fill_both() (gas: 179143)
9-
OrdersTest:test_fill_multiETH() (gas: 141885)
10-
OrdersTest:test_fill_underflowETH() (gas: 120789)
11-
OrdersTest:test_initiate_ERC20() (gas: 90588)
12-
OrdersTest:test_initiate_ETH() (gas: 53217)
13-
OrdersTest:test_initiate_both() (gas: 130158)
14-
OrdersTest:test_initiate_multiERC20() (gas: 186451)
15-
OrdersTest:test_initiate_multiETH() (gas: 86339)
16-
OrdersTest:test_orderExpired() (gas: 32846)
17-
OrdersTest:test_sweepERC20() (gas: 62965)
18-
OrdersTest:test_sweepETH() (gas: 90833)
19-
OrdersTest:test_underflowETH() (gas: 69404)
20-
PassagePermit2Test:test_disallowedEnterPermit2() (gas: 1130187)
21-
PassagePermit2Test:test_enterTokenPermit2() (gas: 150794)
22-
PassageTest:test_configureEnter() (gas: 141651)
23-
PassageTest:test_disallowedEnter() (gas: 58928)
2+
OrderOriginPermit2Test:test_fillPermit2() (gas: 174849)
3+
OrderOriginPermit2Test:test_fillPermit2_multi() (gas: 510712)
4+
OrderOriginPermit2Test:test_initiatePermit2() (gas: 187207)
5+
OrderOriginPermit2Test:test_initiatePermit2_multi() (gas: 471069)
6+
OrdersTest:test_fill_ERC20() (gas: 76399)
7+
OrdersTest:test_fill_ETH() (gas: 73682)
8+
OrdersTest:test_fill_both() (gas: 179085)
9+
OrdersTest:test_fill_multiETH() (gas: 141643)
10+
OrdersTest:test_fill_underflowETH() (gas: 120697)
11+
OrdersTest:test_initiate_ERC20() (gas: 90714)
12+
OrdersTest:test_initiate_ETH() (gas: 53343)
13+
OrdersTest:test_initiate_both() (gas: 130284)
14+
OrdersTest:test_initiate_multiERC20() (gas: 186577)
15+
OrdersTest:test_initiate_multiETH() (gas: 86465)
16+
OrdersTest:test_orderExpired() (gas: 32938)
17+
OrdersTest:test_sweepERC20() (gas: 63091)
18+
OrdersTest:test_sweepETH() (gas: 90901)
19+
OrdersTest:test_underflowETH() (gas: 69496)
20+
PassageFuzzTest:test_disallowedEnter(address,address,uint256) (runs: 266, μ: 19249, ~: 19249)
21+
PassageFuzzTest:test_enter(uint256,address,uint256) (runs: 264, μ: 20920, ~: 20920)
22+
PassageFuzzTest:test_enterToken(uint256,address,uint256) (runs: 264, μ: 66342, ~: 66342)
23+
PassageFuzzTest:test_enterToken_defaultChain(address,uint256) (runs: 262, μ: 67125, ~: 67125)
24+
PassageFuzzTest:test_enter_defaultChain(address,uint56) (runs: 267, μ: 21804, ~: 21804)
25+
PassageFuzzTest:test_fallback(uint256,bytes) (runs: 264, μ: 21921, ~: 21921)
26+
PassageFuzzTest:test_onlyTokenAdmin(address,address,bool,address,uint256) (runs: 267, μ: 16507, ~: 16507)
27+
PassageFuzzTest:test_receive(uint256) (runs: 264, μ: 20719, ~: 20719)
28+
PassageFuzzTest:test_withdraw(address,uint256) (runs: 262, μ: 67480, ~: 67501)
29+
PassagePermit2Test:test_disallowedEnterPermit2() (gas: 1130279)
30+
PassagePermit2Test:test_enterTokenPermit2() (gas: 150920)
31+
PassageTest:test_configureEnter() (gas: 141961)
32+
PassageTest:test_disallowedEnter() (gas: 59020)
2433
PassageTest:test_enter() (gas: 26523)
25-
PassageTest:test_enterToken() (gas: 66880)
26-
PassageTest:test_enterToken_defaultChain() (gas: 65384)
34+
PassageTest:test_enterToken() (gas: 67006)
35+
PassageTest:test_enterToken_defaultChain() (gas: 65510)
2736
PassageTest:test_enter_defaultChain() (gas: 24949)
28-
PassageTest:test_fallback() (gas: 22784)
29-
PassageTest:test_onlyTokenAdmin() (gas: 19145)
30-
PassageTest:test_receive() (gas: 22222)
37+
PassageTest:test_fallback() (gas: 22528)
38+
PassageTest:test_onlyTokenAdmin() (gas: 19237)
39+
PassageTest:test_receive() (gas: 22035)
3140
PassageTest:test_setUp() (gas: 23289)
32-
PassageTest:test_withdraw() (gas: 64486)
33-
RollupPassagePermit2Test:test_exitTokenPermit2() (gas: 135717)
41+
PassageTest:test_withdraw() (gas: 64612)
42+
RollupPassagePermit2Test:test_exitTokenPermit2() (gas: 135843)
3443
RollupPassageTest:test_exit() (gas: 23114)
35-
RollupPassageTest:test_exitToken() (gas: 53266)
36-
RollupPassageTest:test_fallback() (gas: 20910)
37-
RollupPassageTest:test_receive() (gas: 20393)
44+
RollupPassageTest:test_exitToken() (gas: 53367)
45+
RollupPassageTest:test_fallback() (gas: 20654)
46+
RollupPassageTest:test_receive() (gas: 20206)
47+
TransactFuzzTest:test_configureGas(uint256,uint256) (runs: 267, μ: 27723, ~: 27867)
48+
TransactFuzzTest:test_enterTransact_defaultChain_emitsEnter(uint256,address,address,bytes,uint256,uint256,uint256,uint256) (runs: 260, μ: 70502, ~: 70928)
49+
TransactFuzzTest:test_enterTransact_emitsEnter(uint256,address,bytes,uint256,uint256,uint256,uint256) (runs: 261, μ: 70250, ~: 70379)
50+
TransactFuzzTest:test_enterTransact_emitsTransact(uint256,address,bytes,uint256,uint256,uint256,uint256) (runs: 261, μ: 70528, ~: 70634)
51+
TransactFuzzTest:test_onlyGasAdmin(address,uint256,uint256) (runs: 267, μ: 12907, ~: 12907)
52+
TransactFuzzTest:test_transact(uint256,address,address,bytes,uint256,uint256,uint256) (runs: 261, μ: 51025, ~: 51391)
53+
TransactFuzzTest:test_transactWithValue_defaultChain_emitsEnter(address,bytes,uint256,uint256,uint256,uint256) (runs: 261, μ: 71793, ~: 72071)
54+
TransactFuzzTest:test_transactWithValue_defaultChain_emitsTransact(address,bytes,uint256,uint256,uint256,uint256) (runs: 261, μ: 72160, ~: 72413)
55+
TransactFuzzTest:test_transactWithValue_defaultChain_emitsTransact(uint256,address,address,bytes,uint256,uint256,uint256,uint256) (runs: 260, μ: 70765, ~: 71159)
56+
TransactFuzzTest:test_transact_defaultChain(address,address,bytes,uint256,uint256,uint256) (runs: 262, μ: 52898, ~: 53103)
57+
TransactFuzzTest:test_transact_perTransactGasLimit(uint256,address,bytes,uint256,uint256,uint256) (runs: 262, μ: 15980, ~: 15980)
3858
TransactTest:test_configureGas() (gas: 27486)
3959
TransactTest:test_enterTransact() (gas: 127464)
4060
TransactTest:test_onlyGasAdmin() (gas: 9895)
@@ -43,6 +63,12 @@ TransactTest:test_transact() (gas: 107567)
4363
TransactTest:test_transact_defaultChain() (gas: 106574)
4464
TransactTest:test_transact_globalGasLimit() (gas: 117828)
4565
TransactTest:test_transact_perTransactGasLimit() (gas: 34574)
66+
ZenithFuzzTest:test_addSequencer(uint256,(uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 90812, ~: 90812)
67+
ZenithFuzzTest:test_badSignature((uint256,uint256,uint256,address,bytes32),(uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 40335, ~: 40334)
68+
ZenithFuzzTest:test_incorrectHostBlock((uint256,uint256,uint256,address,bytes32),bytes) (runs: 267, μ: 22120, ~: 22115)
69+
ZenithFuzzTest:test_notSequencer(uint256,(uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 32184, ~: 32183)
70+
ZenithFuzzTest:test_notSequencerAdmin(address,address) (runs: 267, μ: 14423, ~: 14423)
71+
ZenithFuzzTest:test_submitBlock((uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 61351, ~: 61351)
4672
ZenithTest:test_addSequencer() (gas: 98616)
4773
ZenithTest:test_badSignature() (gas: 46355)
4874
ZenithTest:test_incorrectHostBlock() (gas: 42276)

lib/openzeppelin-contracts

lib/safe-smart-account

lib/stablecoin-evm

test/fuzz-host/PassageFuzz.t.sol

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
pragma solidity 0.8.26;
3+
4+
// test contracts
5+
import {Passage} from "../../src/passage/Passage.sol";
6+
import {RollupPassage} from "../../src/passage/RollupPassage.sol";
7+
// utils
8+
import {TestERC20} from "../Helpers.t.sol";
9+
import {SignetStdTest} from "../SignetStdTest.t.sol";
10+
import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
11+
import {ERC20Burnable} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol";
12+
import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol";
13+
import {Test, console2} from "forge-std/Test.sol";
14+
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
15+
16+
contract PassageFuzzTest is SignetStdTest {
17+
using Address for address payable;
18+
19+
Passage public target;
20+
address configuredToken;
21+
22+
event Enter(uint256 indexed rollupChainId, address indexed rollupRecipient, uint256 amount);
23+
24+
event EnterToken(
25+
uint256 indexed rollupChainId, address indexed rollupRecipient, address indexed token, uint256 amount
26+
);
27+
28+
event EnterConfigured(address indexed token, bool indexed canEnter);
29+
30+
event Withdrawal(address indexed token, address indexed recipient, uint256 amount);
31+
32+
function setUp() public virtual {
33+
// deploy target
34+
target = HOST_PASSAGE;
35+
36+
// setup token
37+
configuredToken = address(HOST_WETH);
38+
// mint WETH by sending ETH
39+
payable(configuredToken).sendValue(10000 ether);
40+
TestERC20(configuredToken).approve(address(target), 10000 ether);
41+
}
42+
43+
// only the token admin can add or remove new tokens from Passage
44+
function test_onlyTokenAdmin(address caller, address token, bool canEnter, address recipient, uint256 amount)
45+
public
46+
{
47+
vm.assume(caller != TOKEN_ADMIN);
48+
vm.startPrank(caller);
49+
50+
vm.expectRevert(Passage.OnlyTokenAdmin.selector);
51+
target.configureEnter(token, canEnter);
52+
53+
vm.expectRevert(Passage.OnlyTokenAdmin.selector);
54+
target.withdraw(token, recipient, amount);
55+
}
56+
57+
function test_disallowedEnter(address recipient, address newToken, uint256 amount) public {
58+
vm.assume(amount > 0);
59+
vm.assume(target.canEnter(newToken) == false);
60+
vm.mockCall(
61+
newToken,
62+
abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(target), amount),
63+
abi.encode(true)
64+
);
65+
vm.expectRevert(abi.encodeWithSelector(Passage.DisallowedEnter.selector, newToken));
66+
target.enterToken(recipient, newToken, amount);
67+
}
68+
69+
function test_receive(uint256 amount) public {
70+
vm.assume(amount > 0 && amount < payable(address(this)).balance);
71+
vm.expectEmit();
72+
emit Enter(target.defaultRollupChainId(), address(this), amount);
73+
payable(address(target)).sendValue(amount);
74+
}
75+
76+
function test_fallback(uint256 amount, bytes memory data) public {
77+
vm.assume(amount > 0 && amount < payable(address(this)).balance);
78+
vm.expectEmit();
79+
emit Enter(target.defaultRollupChainId(), address(this), amount);
80+
payable(address(target)).functionCallWithValue(data, amount);
81+
}
82+
83+
function test_enter(uint256 rollupChainId, address recipient, uint256 amount) public {
84+
vm.assume(amount > 0 && amount < payable(address(this)).balance);
85+
vm.expectEmit();
86+
emit Enter(rollupChainId, recipient, amount);
87+
target.enter{value: amount}(rollupChainId, recipient);
88+
}
89+
90+
function test_enter_defaultChain(address recipient, uint56 amount) public {
91+
vm.assume(amount > 0 && amount < payable(address(this)).balance);
92+
vm.expectEmit();
93+
emit Enter(target.defaultRollupChainId(), recipient, amount);
94+
target.enter{value: amount}(recipient);
95+
}
96+
97+
function test_enterToken(uint256 rollupChainId, address recipient, uint256 amount) public {
98+
vm.assume(amount > 0 && amount < payable(address(this)).balance);
99+
// mint WETH of the amount
100+
payable(configuredToken).sendValue(amount);
101+
TestERC20(configuredToken).approve(address(target), amount);
102+
103+
vm.expectEmit();
104+
emit EnterToken(rollupChainId, recipient, configuredToken, amount);
105+
vm.expectCall(
106+
configuredToken, abi.encodeWithSelector(ERC20.transferFrom.selector, address(this), address(target), amount)
107+
);
108+
target.enterToken(rollupChainId, recipient, configuredToken, amount);
109+
}
110+
111+
function test_enterToken_defaultChain(address recipient, uint256 amount) public {
112+
vm.assume(amount > 0 && amount < payable(address(this)).balance);
113+
// mint WETH of the amount
114+
payable(configuredToken).sendValue(amount);
115+
TestERC20(configuredToken).approve(address(target), amount);
116+
117+
vm.expectEmit();
118+
emit EnterToken(target.defaultRollupChainId(), recipient, configuredToken, amount);
119+
vm.expectCall(
120+
configuredToken, abi.encodeWithSelector(ERC20.transferFrom.selector, address(this), address(target), amount)
121+
);
122+
target.enterToken(recipient, configuredToken, amount);
123+
}
124+
125+
function test_withdraw(address recipient, uint256 amount) public {
126+
vm.assume(amount > 0 && amount < payable(address(this)).balance);
127+
payable(configuredToken).sendValue(amount);
128+
IERC20(configuredToken).transfer(address(target), amount);
129+
130+
vm.startPrank(TOKEN_ADMIN);
131+
vm.expectEmit();
132+
emit Withdrawal(configuredToken, recipient, amount);
133+
vm.expectCall(configuredToken, abi.encodeWithSelector(ERC20.transfer.selector, recipient, amount));
134+
target.withdraw(configuredToken, recipient, amount);
135+
}
136+
}

0 commit comments

Comments
 (0)