From b68a7ba2fe2b07c76a0c316639a7881854d73b03 Mon Sep 17 00:00:00 2001 From: Anna Carroll Date: Mon, 29 Sep 2025 17:24:57 -0400 Subject: [PATCH 1/7] zenith fuzz tests --- test/fuzz/ZenithFuzz.t.sol | 150 +++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 test/fuzz/ZenithFuzz.t.sol diff --git a/test/fuzz/ZenithFuzz.t.sol b/test/fuzz/ZenithFuzz.t.sol new file mode 100644 index 0000000..0230de9 --- /dev/null +++ b/test/fuzz/ZenithFuzz.t.sol @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity 0.8.26; + +// test contracts +import {Zenith} from "../../src/Zenith.sol"; +// utils +import {SignetStdTest} from "../SignetStdTest.t.sol"; +import {Test, console2} from "forge-std/Test.sol"; + +contract ZenithFuzzTest is SignetStdTest { + Zenith public target; + + uint256 sequencerKey = 123; + + event BlockSubmitted( + address indexed sequencer, + uint256 indexed rollupChainId, + uint256 gasLimit, + address rewardAddress, + bytes32 blockDataHash + ); + + event SequencerSet(address indexed sequencer, bool indexed permissioned); + + function setUp() public virtual { + target = HOST_ZENITH; + + // configure a local signer as a sequencer + vm.prank(SEQUENCER_ADMIN); + target.addSequencer(vm.addr(sequencerKey)); + } + + // cannot submit block with incorrect host block number + function test_incorrectHostBlock(Zenith.BlockHeader memory header, bytes memory blockData) public { + vm.assume(header.hostBlockNumber != block.number); + + // sign block commitment with sequencer key + bytes32 commit = target.blockCommitment(header); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit); + + vm.expectRevert(Zenith.IncorrectHostBlock.selector); + target.submitBlock(header, v, r, s, blockData); + } + + // can submit block successfully with acceptable header & correct signature provided + function test_submitBlock(Zenith.BlockHeader memory header, bytes memory blockData) public { + vm.assume(header.hostBlockNumber == block.number); + + // sign block commitment with correct sequencer key + bytes32 commit = target.blockCommitment(header); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit); + + assertNotEq(target.lastSubmittedAtBlock(header.rollupChainId), block.number); + + // should emit BlockSubmitted event + vm.expectEmit(); + emit BlockSubmitted( + vm.addr(sequencerKey), header.rollupChainId, header.gasLimit, header.rewardAddress, header.blockDataHash + ); + target.submitBlock(header, v, r, s, blockData); + + assertEq(target.lastSubmittedAtBlock(header.rollupChainId), block.number); + } + + // cannot submit block with invalid sequencer signer from non-permissioned key + function test_notSequencer(uint256 notSequencerKey, Zenith.BlockHeader memory header, bytes memory blockData) + public + { + vm.assume(notSequencerKey != sequencerKey); + vm.assume( + notSequencerKey != 0 + && notSequencerKey < 115792089237316195423570985008687907852837564279074904382605163141518161494337 + ); + vm.assume(header.hostBlockNumber == block.number); + + // sign block commitment with NOT sequencer key + bytes32 commit = target.blockCommitment(header); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(notSequencerKey, commit); + + vm.expectRevert(abi.encodeWithSelector(Zenith.BadSignature.selector, vm.addr(notSequencerKey))); + target.submitBlock(header, v, r, s, blockData); + } + + // cannot submit block with sequencer signature over different block header data + function test_badSignature( + Zenith.BlockHeader memory header1, + Zenith.BlockHeader memory header2, + bytes memory blockData + ) public { + // assume the two headers are different in some way + vm.assume( + header1.rollupChainId != header2.rollupChainId || header1.hostBlockNumber != header2.hostBlockNumber + || header1.gasLimit != header2.gasLimit || header1.rewardAddress != header2.rewardAddress + || header1.blockDataHash != header2.blockDataHash + ); + vm.assume(header2.hostBlockNumber == block.number); + + // sign original block commitment with sequencer key + bytes32 commit1 = target.blockCommitment(header1); + bytes32 commit2 = target.blockCommitment(header2); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit1); + + address derivedSigner = ecrecover(commit2, v, r, s); + vm.expectRevert(abi.encodeWithSelector(Zenith.BadSignature.selector, derivedSigner)); + target.submitBlock(header2, v, r, s, blockData); + } + + function test_addSequencer(uint256 notSequencerKey, Zenith.BlockHeader memory header, bytes memory blockData) + public + { + vm.assume(notSequencerKey != sequencerKey); + vm.assume( + notSequencerKey != 0 + && notSequencerKey < 115792089237316195423570985008687907852837564279074904382605163141518161494337 + ); + vm.assume(header.hostBlockNumber == block.number); + + address newSequencer = vm.addr(notSequencerKey); + assertFalse(target.isSequencer(newSequencer)); + + vm.startPrank(SEQUENCER_ADMIN); + vm.expectEmit(); + emit SequencerSet(newSequencer, true); + target.addSequencer(newSequencer); + vm.stopPrank(); + + assertTrue(target.isSequencer(newSequencer)); + + // can sign block now with new sequencer key + bytes32 commit = target.blockCommitment(header); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(notSequencerKey, commit); + vm.expectEmit(); + emit BlockSubmitted( + newSequencer, header.rollupChainId, header.gasLimit, header.rewardAddress, header.blockDataHash + ); + target.submitBlock(header, v, r, s, blockData); + } + + function test_notSequencerAdmin(address caller, address sequencer) public { + vm.assume(caller != SEQUENCER_ADMIN); + vm.startPrank(caller); + + vm.expectRevert(Zenith.OnlySequencerAdmin.selector); + target.addSequencer(sequencer); + + vm.expectRevert(Zenith.OnlySequencerAdmin.selector); + target.removeSequencer(sequencer); + } +} From ec01b6144fdc2da1ccd21a3293f285ac517971e8 Mon Sep 17 00:00:00 2001 From: Anna Carroll Date: Mon, 29 Sep 2025 18:24:27 -0400 Subject: [PATCH 2/7] move zenith fuzz --- test/{fuzz => fuzz-host}/ZenithFuzz.t.sol | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{fuzz => fuzz-host}/ZenithFuzz.t.sol (100%) diff --git a/test/fuzz/ZenithFuzz.t.sol b/test/fuzz-host/ZenithFuzz.t.sol similarity index 100% rename from test/fuzz/ZenithFuzz.t.sol rename to test/fuzz-host/ZenithFuzz.t.sol From 86754e6afdf44ca75ea61c1c4d8bd16ce9f779a3 Mon Sep 17 00:00:00 2001 From: Anna Carroll Date: Mon, 29 Sep 2025 18:24:41 -0400 Subject: [PATCH 3/7] Passage Fuzz --- test/fuzz-host/PassageFuzz.t.sol | 135 +++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 test/fuzz-host/PassageFuzz.t.sol diff --git a/test/fuzz-host/PassageFuzz.t.sol b/test/fuzz-host/PassageFuzz.t.sol new file mode 100644 index 0000000..4dbdad4 --- /dev/null +++ b/test/fuzz-host/PassageFuzz.t.sol @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity 0.8.26; + +// test contracts +import {Passage} from "../../src/passage/Passage.sol"; +import {RollupPassage} from "../../src/passage/RollupPassage.sol"; +// utils +import {TestERC20} from "../Helpers.t.sol"; +import {SignetStdTest} from "../SignetStdTest.t.sol"; +import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +import {ERC20Burnable} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol"; +import {Test, console2} from "forge-std/Test.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; + +contract PassageFuzzTest is SignetStdTest { + using Address for address payable; + + Passage public target; + address configuredToken; + + event Enter(uint256 indexed rollupChainId, address indexed rollupRecipient, uint256 amount); + + event EnterToken( + uint256 indexed rollupChainId, address indexed rollupRecipient, address indexed token, uint256 amount + ); + + event EnterConfigured(address indexed token, bool indexed canEnter); + + event Withdrawal(address indexed token, address indexed recipient, uint256 amount); + + function setUp() public virtual { + // deploy target + target = HOST_PASSAGE; + + // setup token + configuredToken = address(HOST_WETH); + // mint WETH by sending ETH + payable(configuredToken).sendValue(10000 ether); + TestERC20(configuredToken).approve(address(target), 10000 ether); + + // // deploy new token that's not configured on Passage + // newToken = address(new TestERC20("bye", "BYE", 18)); + // TestERC20(newToken).mint(address(this), amount * 10000); + // TestERC20(newToken).approve(address(target), amount * 10000); + } + + // only the token admin can add or remove new tokens from Passage + function test_onlyTokenAdmin(address caller, address token, bool canEnter, address recipient, uint256 amount) + public + { + vm.assume(caller != TOKEN_ADMIN); + vm.startPrank(caller); + + vm.expectRevert(Passage.OnlyTokenAdmin.selector); + target.configureEnter(token, canEnter); + + vm.expectRevert(Passage.OnlyTokenAdmin.selector); + target.withdraw(token, recipient, amount); + } + + // function test_disallowedEnter(address recipient, address newToken, uint256 amount) public { + // vm.assume(target.canEnter(newToken) == false); + // vm.expectRevert(abi.encodeWithSelector(Passage.DisallowedEnter.selector, newToken)); + // target.enterToken(recipient, newToken, amount); + // } + + function test_receive(uint256 amount) public { + vm.assume(amount > 0 && amount < payable(address(this)).balance); + vm.expectEmit(); + emit Enter(target.defaultRollupChainId(), address(this), amount); + payable(address(target)).sendValue(amount); + } + + function test_fallback(uint256 amount, bytes memory data) public { + vm.assume(amount > 0 && amount < payable(address(this)).balance); + vm.expectEmit(); + emit Enter(target.defaultRollupChainId(), address(this), amount); + payable(address(target)).functionCallWithValue(data, amount); + } + + function test_enter(uint256 rollupChainId, address recipient, uint256 amount) public { + vm.assume(amount > 0 && amount < payable(address(this)).balance); + vm.expectEmit(); + emit Enter(rollupChainId, recipient, amount); + target.enter{value: amount}(rollupChainId, recipient); + } + + function test_enter_defaultChain(address recipient, uint56 amount) public { + vm.assume(amount > 0 && amount < payable(address(this)).balance); + vm.expectEmit(); + emit Enter(target.defaultRollupChainId(), recipient, amount); + target.enter{value: amount}(recipient); + } + + function test_enterToken(uint256 rollupChainId, address recipient, uint256 amount) public { + vm.assume(amount > 0 && amount < payable(address(this)).balance); + // mint WETH of the amount + payable(configuredToken).sendValue(amount); + TestERC20(configuredToken).approve(address(target), amount); + + vm.expectEmit(); + emit EnterToken(rollupChainId, recipient, configuredToken, amount); + vm.expectCall( + configuredToken, abi.encodeWithSelector(ERC20.transferFrom.selector, address(this), address(target), amount) + ); + target.enterToken(rollupChainId, recipient, configuredToken, amount); + } + + function test_enterToken_defaultChain(address recipient, uint256 amount) public { + vm.assume(amount > 0 && amount < payable(address(this)).balance); + // mint WETH of the amount + payable(configuredToken).sendValue(amount); + TestERC20(configuredToken).approve(address(target), amount); + + vm.expectEmit(); + emit EnterToken(target.defaultRollupChainId(), recipient, configuredToken, amount); + vm.expectCall( + configuredToken, abi.encodeWithSelector(ERC20.transferFrom.selector, address(this), address(target), amount) + ); + target.enterToken(recipient, configuredToken, amount); + } + + function test_withdraw(address recipient, uint256 amount) public { + vm.assume(amount > 0 && amount < payable(address(this)).balance); + payable(configuredToken).sendValue(amount); + IERC20(configuredToken).transfer(address(target), amount); + + vm.startPrank(TOKEN_ADMIN); + vm.expectEmit(); + emit Withdrawal(configuredToken, recipient, amount); + vm.expectCall(configuredToken, abi.encodeWithSelector(ERC20.transfer.selector, recipient, amount)); + target.withdraw(configuredToken, recipient, amount); + } +} From fe9e7e6fd8a32336cf2e936428fbc2ba1cd0790c Mon Sep 17 00:00:00 2001 From: Anna Carroll Date: Mon, 29 Sep 2025 18:52:47 -0400 Subject: [PATCH 4/7] TransactFuzzTest --- test/fuzz-host/TransactorFuzz.t.sol | 201 ++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 test/fuzz-host/TransactorFuzz.t.sol diff --git a/test/fuzz-host/TransactorFuzz.t.sol b/test/fuzz-host/TransactorFuzz.t.sol new file mode 100644 index 0000000..21574c8 --- /dev/null +++ b/test/fuzz-host/TransactorFuzz.t.sol @@ -0,0 +1,201 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity 0.8.26; + +// test contracts +import {Transactor} from "../../src/Transactor.sol"; +import {Passage} from "../../src/passage/Passage.sol"; +// utils +import {SignetStdTest} from "../SignetStdTest.t.sol"; +import {Test, console2} from "forge-std/Test.sol"; + +contract TransactFuzzTest is SignetStdTest { + Transactor public target; + + event Transact( + uint256 indexed rollupChainId, + address indexed sender, + address indexed to, + bytes data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas + ); + + event GasConfigured(uint256 perBlock, uint256 perTransact); + + // Passage event + event Enter(uint256 indexed rollupChainId, address indexed rollupRecipient, uint256 amount); + + function setUp() public virtual { + // deploy target + target = HOST_TRANSACTOR; + } + + function test_transact( + uint256 rollupChainId, + address sender, + address to, + bytes memory data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas + ) public { + vm.assume(gas <= target.perTransactGasLimit() && gas <= target.perBlockGasLimit()); + + vm.startPrank(sender); + vm.expectEmit(address(target)); + emit Transact(rollupChainId, sender, to, data, value, gas, maxFeePerGas); + target.transact(rollupChainId, to, data, value, gas, maxFeePerGas); + } + + function test_enterTransact_emitsEnter( + uint256 rollupChainId, + address to, + bytes memory data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas, + uint256 amount + ) public { + vm.assume(gas <= target.perTransactGasLimit() && gas <= target.perBlockGasLimit()); + vm.assume(amount > 0 && amount < payable(address(this)).balance); + + vm.expectEmit(address(HOST_PASSAGE)); + emit Enter(rollupChainId, address(this), amount); + target.transact{value: amount}(rollupChainId, to, data, value, gas, maxFeePerGas); + } + + function test_enterTransact_emitsTransact( + uint256 rollupChainId, + address to, + bytes memory data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas, + uint256 amount + ) public { + vm.assume(gas <= target.perTransactGasLimit() && gas <= target.perBlockGasLimit()); + vm.assume(amount > 0 && amount < payable(address(this)).balance); + + vm.expectEmit(address(target)); + emit Transact(rollupChainId, address(this), to, data, value, gas, maxFeePerGas); + target.transact{value: amount}(rollupChainId, to, data, value, gas, maxFeePerGas); + } + + function test_transact_defaultChain( + address sender, + address to, + bytes memory data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas + ) public { + vm.assume(gas <= target.perTransactGasLimit() && gas <= target.perBlockGasLimit()); + + vm.startPrank(sender); + vm.expectEmit(address(target)); + emit Transact(ROLLUP_CHAIN_ID, sender, to, data, value, gas, maxFeePerGas); + target.transact(to, data, value, gas, maxFeePerGas); + } + + function test_transactWithValue_defaultChain_emitsEnter( + address to, + bytes memory data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas, + uint256 amount + ) public { + vm.assume(gas <= target.perTransactGasLimit() && gas <= target.perBlockGasLimit()); + vm.assume(amount > 0 && amount < payable(address(this)).balance); + + vm.expectEmit(address(HOST_PASSAGE)); + emit Enter(ROLLUP_CHAIN_ID, address(this), amount); + target.transact{value: amount}(to, data, value, gas, maxFeePerGas); + } + + function test_transactWithValue_defaultChain_emitsTransact( + address to, + bytes memory data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas, + uint256 amount + ) public { + vm.assume(gas <= target.perTransactGasLimit() && gas <= target.perBlockGasLimit()); + vm.assume(amount > 0 && amount < payable(address(this)).balance); + + vm.expectEmit(address(target)); + emit Transact(ROLLUP_CHAIN_ID, address(this), to, data, value, gas, maxFeePerGas); + target.transact{value: amount}(to, data, value, gas, maxFeePerGas); + } + + function test_enterTransact_defaultChain_emitsEnter( + uint256 rollupChainId, + address recipient, + address to, + bytes memory data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas, + uint256 amount + ) public { + vm.assume(gas <= target.perTransactGasLimit() && gas <= target.perBlockGasLimit()); + vm.assume(amount > 0 && amount < payable(address(this)).balance); + + vm.expectEmit(address(HOST_PASSAGE)); + emit Enter(rollupChainId, recipient, amount); + target.enterTransact{value: amount}(rollupChainId, recipient, to, data, value, gas, maxFeePerGas); + } + + function test_transactWithValue_defaultChain_emitsTransact( + uint256 rollupChainId, + address recipient, + address to, + bytes memory data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas, + uint256 amount + ) public { + vm.assume(gas <= target.perTransactGasLimit() && gas <= target.perBlockGasLimit()); + vm.assume(amount > 0 && amount < payable(address(this)).balance); + + vm.expectEmit(address(target)); + emit Transact(rollupChainId, address(this), to, data, value, gas, maxFeePerGas); + target.enterTransact{value: amount}(rollupChainId, recipient, to, data, value, gas, maxFeePerGas); + } + + function test_transact_perTransactGasLimit( + uint256 rollupChainId, + address to, + bytes memory data, + uint256 value, + uint256 gas, + uint256 maxFeePerGas + ) public { + vm.assume(gas > target.perTransactGasLimit()); + vm.expectRevert(Transactor.PerTransactGasLimit.selector); + target.transact(rollupChainId, to, data, value, gas, maxFeePerGas); + } + + function test_onlyGasAdmin(address caller, uint256 perBlockGas, uint256 perTransactGas) public { + vm.assume(caller != GAS_ADMIN); + vm.startPrank(caller); + + vm.expectRevert(Transactor.OnlyGasAdmin.selector); + target.configureGas(perBlockGas, perTransactGas); + } + + function test_configureGas(uint256 newPerBlock, uint256 newPerTransact) public { + // configure gas + vm.startPrank(GAS_ADMIN); + vm.expectEmit(); + emit GasConfigured(newPerBlock, newPerTransact); + target.configureGas(newPerBlock, newPerTransact); + vm.stopPrank(); + + assertEq(target.perBlockGasLimit(), newPerBlock); + assertEq(target.perTransactGasLimit(), newPerTransact); + } +} From 74260e948cbfce97d5640136ba318e0a7aa8ff8a Mon Sep 17 00:00:00 2001 From: Anna Carroll Date: Mon, 29 Sep 2025 18:55:36 -0400 Subject: [PATCH 5/7] update snapshot --- .gas-snapshot | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.gas-snapshot b/.gas-snapshot index 07b0353..5ecd4a1 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -17,6 +17,14 @@ OrdersTest:test_orderExpired() (gas: 32846) OrdersTest:test_sweepERC20() (gas: 62965) OrdersTest:test_sweepETH() (gas: 90833) OrdersTest:test_underflowETH() (gas: 69404) +PassageFuzzTest:test_enter(uint256,address,uint256) (runs: 261, μ: 20920, ~: 20920) +PassageFuzzTest:test_enterToken(uint256,address,uint256) (runs: 261, μ: 66400, ~: 66400) +PassageFuzzTest:test_enterToken_defaultChain(address,uint256) (runs: 260, μ: 67183, ~: 67183) +PassageFuzzTest:test_enter_defaultChain(address,uint56) (runs: 263, μ: 21804, ~: 21804) +PassageFuzzTest:test_fallback(uint256,bytes) (runs: 260, μ: 22179, ~: 22177) +PassageFuzzTest:test_onlyTokenAdmin(address,address,bool,address,uint256) (runs: 263, μ: 16415, ~: 16415) +PassageFuzzTest:test_receive(uint256) (runs: 260, μ: 20906, ~: 20906) +PassageFuzzTest:test_withdraw(address,uint256) (runs: 260, μ: 67525, ~: 67549) PassagePermit2Test:test_disallowedEnterPermit2() (gas: 1130187) PassagePermit2Test:test_enterTokenPermit2() (gas: 150794) PassageTest:test_configureEnter() (gas: 141651) @@ -35,6 +43,17 @@ RollupPassageTest:test_exit() (gas: 23114) RollupPassageTest:test_exitToken() (gas: 53266) RollupPassageTest:test_fallback() (gas: 20910) RollupPassageTest:test_receive() (gas: 20393) +TransactFuzzTest:test_configureGas(uint256,uint256) (runs: 263, μ: 27720, ~: 27867) +TransactFuzzTest:test_enterTransact_defaultChain_emitsEnter(uint256,address,address,bytes,uint256,uint256,uint256,uint256) (runs: 259, μ: 70500, ~: 70928) +TransactFuzzTest:test_enterTransact_emitsEnter(uint256,address,bytes,uint256,uint256,uint256,uint256) (runs: 258, μ: 70248, ~: 70379) +TransactFuzzTest:test_enterTransact_emitsTransact(uint256,address,bytes,uint256,uint256,uint256,uint256) (runs: 258, μ: 70527, ~: 70634) +TransactFuzzTest:test_onlyGasAdmin(address,uint256,uint256) (runs: 263, μ: 12907, ~: 12907) +TransactFuzzTest:test_transact(uint256,address,address,bytes,uint256,uint256,uint256) (runs: 259, μ: 51022, ~: 51391) +TransactFuzzTest:test_transactWithValue_defaultChain_emitsEnter(address,bytes,uint256,uint256,uint256,uint256) (runs: 259, μ: 71790, ~: 72071) +TransactFuzzTest:test_transactWithValue_defaultChain_emitsTransact(address,bytes,uint256,uint256,uint256,uint256) (runs: 259, μ: 72158, ~: 72413) +TransactFuzzTest:test_transactWithValue_defaultChain_emitsTransact(uint256,address,address,bytes,uint256,uint256,uint256,uint256) (runs: 259, μ: 70763, ~: 71159) +TransactFuzzTest:test_transact_defaultChain(address,address,bytes,uint256,uint256,uint256) (runs: 259, μ: 52896, ~: 53103) +TransactFuzzTest:test_transact_perTransactGasLimit(uint256,address,bytes,uint256,uint256,uint256) (runs: 261, μ: 15980, ~: 15980) TransactTest:test_configureGas() (gas: 27486) TransactTest:test_enterTransact() (gas: 127464) TransactTest:test_onlyGasAdmin() (gas: 9895) @@ -43,6 +62,12 @@ TransactTest:test_transact() (gas: 107567) TransactTest:test_transact_defaultChain() (gas: 106574) TransactTest:test_transact_globalGasLimit() (gas: 117828) TransactTest:test_transact_perTransactGasLimit() (gas: 34574) +ZenithFuzzTest:test_addSequencer(uint256,(uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 90812, ~: 90812) +ZenithFuzzTest:test_badSignature((uint256,uint256,uint256,address,bytes32),(uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 40335, ~: 40334) +ZenithFuzzTest:test_incorrectHostBlock((uint256,uint256,uint256,address,bytes32),bytes) (runs: 263, μ: 22120, ~: 22115) +ZenithFuzzTest:test_notSequencer(uint256,(uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 32184, ~: 32183) +ZenithFuzzTest:test_notSequencerAdmin(address,address) (runs: 263, μ: 14423, ~: 14423) +ZenithFuzzTest:test_submitBlock((uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 61351, ~: 61351) ZenithTest:test_addSequencer() (gas: 98616) ZenithTest:test_badSignature() (gas: 46355) ZenithTest:test_incorrectHostBlock() (gas: 42276) From 0c98fb663b6c30c8e0b2d2ca299311fb3eb7ecc6 Mon Sep 17 00:00:00 2001 From: Anna Carroll Date: Thu, 9 Oct 2025 10:23:19 -0400 Subject: [PATCH 6/7] forge update --- lib/forge-std | 2 +- lib/openzeppelin-contracts | 2 +- lib/safe-smart-account | 2 +- lib/stablecoin-evm | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/forge-std b/lib/forge-std index c7be2a3..8e40513 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit c7be2a3481f9e51230880bb0949072c7e3a4da82 +Subproject commit 8e40513d678f392f398620b3ef2b418648b33e89 diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index 3790c59..45558b8 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit 3790c59623e99cb0272ddf84e6a17a5979d06b35 +Subproject commit 45558b816d34485fe4b0830d1f5206f241a34b77 diff --git a/lib/safe-smart-account b/lib/safe-smart-account index 0095f1a..d6b4fca 160000 --- a/lib/safe-smart-account +++ b/lib/safe-smart-account @@ -1 +1 @@ -Subproject commit 0095f1aa113255d97b476e625760514cc7d10982 +Subproject commit d6b4fca7138b6235bc54744c1f7cc147422b7245 diff --git a/lib/stablecoin-evm b/lib/stablecoin-evm index c8c31b2..f1dfc9e 160000 --- a/lib/stablecoin-evm +++ b/lib/stablecoin-evm @@ -1 +1 @@ -Subproject commit c8c31b249341bf3ffb2e8dbff41977c392a260c5 +Subproject commit f1dfc9eb54aacc6db137470d6ab99b1f8216aaa4 From 2d679684efa6301362f29980d2f2c72e23626ec5 Mon Sep 17 00:00:00 2001 From: Anna Carroll Date: Thu, 9 Oct 2025 10:23:43 -0400 Subject: [PATCH 7/7] fix: impl disallowed enter test --- .gas-snapshot | 107 ++++++++++++++++--------------- test/fuzz-host/PassageFuzz.t.sol | 21 +++--- 2 files changed, 65 insertions(+), 63 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 5ecd4a1..92b3688 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,59 +1,60 @@ GnosisSafeTest:test_gnosis_receive() (gas: 16106) -OrderOriginPermit2Test:test_fillPermit2() (gas: 174723) -OrderOriginPermit2Test:test_fillPermit2_multi() (gas: 510586) -OrderOriginPermit2Test:test_initiatePermit2() (gas: 187081) -OrderOriginPermit2Test:test_initiatePermit2_multi() (gas: 470943) -OrdersTest:test_fill_ERC20() (gas: 76273) -OrdersTest:test_fill_ETH() (gas: 73740) -OrdersTest:test_fill_both() (gas: 179143) -OrdersTest:test_fill_multiETH() (gas: 141885) -OrdersTest:test_fill_underflowETH() (gas: 120789) -OrdersTest:test_initiate_ERC20() (gas: 90588) -OrdersTest:test_initiate_ETH() (gas: 53217) -OrdersTest:test_initiate_both() (gas: 130158) -OrdersTest:test_initiate_multiERC20() (gas: 186451) -OrdersTest:test_initiate_multiETH() (gas: 86339) -OrdersTest:test_orderExpired() (gas: 32846) -OrdersTest:test_sweepERC20() (gas: 62965) -OrdersTest:test_sweepETH() (gas: 90833) -OrdersTest:test_underflowETH() (gas: 69404) -PassageFuzzTest:test_enter(uint256,address,uint256) (runs: 261, μ: 20920, ~: 20920) -PassageFuzzTest:test_enterToken(uint256,address,uint256) (runs: 261, μ: 66400, ~: 66400) -PassageFuzzTest:test_enterToken_defaultChain(address,uint256) (runs: 260, μ: 67183, ~: 67183) -PassageFuzzTest:test_enter_defaultChain(address,uint56) (runs: 263, μ: 21804, ~: 21804) -PassageFuzzTest:test_fallback(uint256,bytes) (runs: 260, μ: 22179, ~: 22177) -PassageFuzzTest:test_onlyTokenAdmin(address,address,bool,address,uint256) (runs: 263, μ: 16415, ~: 16415) -PassageFuzzTest:test_receive(uint256) (runs: 260, μ: 20906, ~: 20906) -PassageFuzzTest:test_withdraw(address,uint256) (runs: 260, μ: 67525, ~: 67549) -PassagePermit2Test:test_disallowedEnterPermit2() (gas: 1130187) -PassagePermit2Test:test_enterTokenPermit2() (gas: 150794) -PassageTest:test_configureEnter() (gas: 141651) -PassageTest:test_disallowedEnter() (gas: 58928) +OrderOriginPermit2Test:test_fillPermit2() (gas: 174849) +OrderOriginPermit2Test:test_fillPermit2_multi() (gas: 510712) +OrderOriginPermit2Test:test_initiatePermit2() (gas: 187207) +OrderOriginPermit2Test:test_initiatePermit2_multi() (gas: 471069) +OrdersTest:test_fill_ERC20() (gas: 76399) +OrdersTest:test_fill_ETH() (gas: 73682) +OrdersTest:test_fill_both() (gas: 179085) +OrdersTest:test_fill_multiETH() (gas: 141643) +OrdersTest:test_fill_underflowETH() (gas: 120697) +OrdersTest:test_initiate_ERC20() (gas: 90714) +OrdersTest:test_initiate_ETH() (gas: 53343) +OrdersTest:test_initiate_both() (gas: 130284) +OrdersTest:test_initiate_multiERC20() (gas: 186577) +OrdersTest:test_initiate_multiETH() (gas: 86465) +OrdersTest:test_orderExpired() (gas: 32938) +OrdersTest:test_sweepERC20() (gas: 63091) +OrdersTest:test_sweepETH() (gas: 90901) +OrdersTest:test_underflowETH() (gas: 69496) +PassageFuzzTest:test_disallowedEnter(address,address,uint256) (runs: 266, μ: 19249, ~: 19249) +PassageFuzzTest:test_enter(uint256,address,uint256) (runs: 264, μ: 20920, ~: 20920) +PassageFuzzTest:test_enterToken(uint256,address,uint256) (runs: 264, μ: 66342, ~: 66342) +PassageFuzzTest:test_enterToken_defaultChain(address,uint256) (runs: 262, μ: 67125, ~: 67125) +PassageFuzzTest:test_enter_defaultChain(address,uint56) (runs: 267, μ: 21804, ~: 21804) +PassageFuzzTest:test_fallback(uint256,bytes) (runs: 264, μ: 21921, ~: 21921) +PassageFuzzTest:test_onlyTokenAdmin(address,address,bool,address,uint256) (runs: 267, μ: 16507, ~: 16507) +PassageFuzzTest:test_receive(uint256) (runs: 264, μ: 20719, ~: 20719) +PassageFuzzTest:test_withdraw(address,uint256) (runs: 262, μ: 67480, ~: 67501) +PassagePermit2Test:test_disallowedEnterPermit2() (gas: 1130279) +PassagePermit2Test:test_enterTokenPermit2() (gas: 150920) +PassageTest:test_configureEnter() (gas: 141961) +PassageTest:test_disallowedEnter() (gas: 59020) PassageTest:test_enter() (gas: 26523) -PassageTest:test_enterToken() (gas: 66880) -PassageTest:test_enterToken_defaultChain() (gas: 65384) +PassageTest:test_enterToken() (gas: 67006) +PassageTest:test_enterToken_defaultChain() (gas: 65510) PassageTest:test_enter_defaultChain() (gas: 24949) -PassageTest:test_fallback() (gas: 22784) -PassageTest:test_onlyTokenAdmin() (gas: 19145) -PassageTest:test_receive() (gas: 22222) +PassageTest:test_fallback() (gas: 22528) +PassageTest:test_onlyTokenAdmin() (gas: 19237) +PassageTest:test_receive() (gas: 22035) PassageTest:test_setUp() (gas: 23289) -PassageTest:test_withdraw() (gas: 64486) -RollupPassagePermit2Test:test_exitTokenPermit2() (gas: 135717) +PassageTest:test_withdraw() (gas: 64612) +RollupPassagePermit2Test:test_exitTokenPermit2() (gas: 135843) RollupPassageTest:test_exit() (gas: 23114) -RollupPassageTest:test_exitToken() (gas: 53266) -RollupPassageTest:test_fallback() (gas: 20910) -RollupPassageTest:test_receive() (gas: 20393) -TransactFuzzTest:test_configureGas(uint256,uint256) (runs: 263, μ: 27720, ~: 27867) -TransactFuzzTest:test_enterTransact_defaultChain_emitsEnter(uint256,address,address,bytes,uint256,uint256,uint256,uint256) (runs: 259, μ: 70500, ~: 70928) -TransactFuzzTest:test_enterTransact_emitsEnter(uint256,address,bytes,uint256,uint256,uint256,uint256) (runs: 258, μ: 70248, ~: 70379) -TransactFuzzTest:test_enterTransact_emitsTransact(uint256,address,bytes,uint256,uint256,uint256,uint256) (runs: 258, μ: 70527, ~: 70634) -TransactFuzzTest:test_onlyGasAdmin(address,uint256,uint256) (runs: 263, μ: 12907, ~: 12907) -TransactFuzzTest:test_transact(uint256,address,address,bytes,uint256,uint256,uint256) (runs: 259, μ: 51022, ~: 51391) -TransactFuzzTest:test_transactWithValue_defaultChain_emitsEnter(address,bytes,uint256,uint256,uint256,uint256) (runs: 259, μ: 71790, ~: 72071) -TransactFuzzTest:test_transactWithValue_defaultChain_emitsTransact(address,bytes,uint256,uint256,uint256,uint256) (runs: 259, μ: 72158, ~: 72413) -TransactFuzzTest:test_transactWithValue_defaultChain_emitsTransact(uint256,address,address,bytes,uint256,uint256,uint256,uint256) (runs: 259, μ: 70763, ~: 71159) -TransactFuzzTest:test_transact_defaultChain(address,address,bytes,uint256,uint256,uint256) (runs: 259, μ: 52896, ~: 53103) -TransactFuzzTest:test_transact_perTransactGasLimit(uint256,address,bytes,uint256,uint256,uint256) (runs: 261, μ: 15980, ~: 15980) +RollupPassageTest:test_exitToken() (gas: 53367) +RollupPassageTest:test_fallback() (gas: 20654) +RollupPassageTest:test_receive() (gas: 20206) +TransactFuzzTest:test_configureGas(uint256,uint256) (runs: 267, μ: 27723, ~: 27867) +TransactFuzzTest:test_enterTransact_defaultChain_emitsEnter(uint256,address,address,bytes,uint256,uint256,uint256,uint256) (runs: 260, μ: 70502, ~: 70928) +TransactFuzzTest:test_enterTransact_emitsEnter(uint256,address,bytes,uint256,uint256,uint256,uint256) (runs: 261, μ: 70250, ~: 70379) +TransactFuzzTest:test_enterTransact_emitsTransact(uint256,address,bytes,uint256,uint256,uint256,uint256) (runs: 261, μ: 70528, ~: 70634) +TransactFuzzTest:test_onlyGasAdmin(address,uint256,uint256) (runs: 267, μ: 12907, ~: 12907) +TransactFuzzTest:test_transact(uint256,address,address,bytes,uint256,uint256,uint256) (runs: 261, μ: 51025, ~: 51391) +TransactFuzzTest:test_transactWithValue_defaultChain_emitsEnter(address,bytes,uint256,uint256,uint256,uint256) (runs: 261, μ: 71793, ~: 72071) +TransactFuzzTest:test_transactWithValue_defaultChain_emitsTransact(address,bytes,uint256,uint256,uint256,uint256) (runs: 261, μ: 72160, ~: 72413) +TransactFuzzTest:test_transactWithValue_defaultChain_emitsTransact(uint256,address,address,bytes,uint256,uint256,uint256,uint256) (runs: 260, μ: 70765, ~: 71159) +TransactFuzzTest:test_transact_defaultChain(address,address,bytes,uint256,uint256,uint256) (runs: 262, μ: 52898, ~: 53103) +TransactFuzzTest:test_transact_perTransactGasLimit(uint256,address,bytes,uint256,uint256,uint256) (runs: 262, μ: 15980, ~: 15980) TransactTest:test_configureGas() (gas: 27486) TransactTest:test_enterTransact() (gas: 127464) TransactTest:test_onlyGasAdmin() (gas: 9895) @@ -64,9 +65,9 @@ TransactTest:test_transact_globalGasLimit() (gas: 117828) TransactTest:test_transact_perTransactGasLimit() (gas: 34574) ZenithFuzzTest:test_addSequencer(uint256,(uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 90812, ~: 90812) ZenithFuzzTest:test_badSignature((uint256,uint256,uint256,address,bytes32),(uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 40335, ~: 40334) -ZenithFuzzTest:test_incorrectHostBlock((uint256,uint256,uint256,address,bytes32),bytes) (runs: 263, μ: 22120, ~: 22115) +ZenithFuzzTest:test_incorrectHostBlock((uint256,uint256,uint256,address,bytes32),bytes) (runs: 267, μ: 22120, ~: 22115) ZenithFuzzTest:test_notSequencer(uint256,(uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 32184, ~: 32183) -ZenithFuzzTest:test_notSequencerAdmin(address,address) (runs: 263, μ: 14423, ~: 14423) +ZenithFuzzTest:test_notSequencerAdmin(address,address) (runs: 267, μ: 14423, ~: 14423) ZenithFuzzTest:test_submitBlock((uint256,uint256,uint256,address,bytes32),bytes) (runs: 256, μ: 61351, ~: 61351) ZenithTest:test_addSequencer() (gas: 98616) ZenithTest:test_badSignature() (gas: 46355) diff --git a/test/fuzz-host/PassageFuzz.t.sol b/test/fuzz-host/PassageFuzz.t.sol index 4dbdad4..0dfc910 100644 --- a/test/fuzz-host/PassageFuzz.t.sol +++ b/test/fuzz-host/PassageFuzz.t.sol @@ -38,11 +38,6 @@ contract PassageFuzzTest is SignetStdTest { // mint WETH by sending ETH payable(configuredToken).sendValue(10000 ether); TestERC20(configuredToken).approve(address(target), 10000 ether); - - // // deploy new token that's not configured on Passage - // newToken = address(new TestERC20("bye", "BYE", 18)); - // TestERC20(newToken).mint(address(this), amount * 10000); - // TestERC20(newToken).approve(address(target), amount * 10000); } // only the token admin can add or remove new tokens from Passage @@ -59,11 +54,17 @@ contract PassageFuzzTest is SignetStdTest { target.withdraw(token, recipient, amount); } - // function test_disallowedEnter(address recipient, address newToken, uint256 amount) public { - // vm.assume(target.canEnter(newToken) == false); - // vm.expectRevert(abi.encodeWithSelector(Passage.DisallowedEnter.selector, newToken)); - // target.enterToken(recipient, newToken, amount); - // } + function test_disallowedEnter(address recipient, address newToken, uint256 amount) public { + vm.assume(amount > 0); + vm.assume(target.canEnter(newToken) == false); + vm.mockCall( + newToken, + abi.encodeWithSelector(IERC20.transferFrom.selector, address(this), address(target), amount), + abi.encode(true) + ); + vm.expectRevert(abi.encodeWithSelector(Passage.DisallowedEnter.selector, newToken)); + target.enterToken(recipient, newToken, amount); + } function test_receive(uint256 amount) public { vm.assume(amount > 0 && amount < payable(address(this)).balance);