diff --git a/.gas-snapshot b/.gas-snapshot index 3d48285..09eea30 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,54 +1,54 @@ -GnosisSafeTest:test_gnosis_receive() (gas: 15927) -OrderOriginPermit2Test:test_fillPermit2() (gas: 223464) -OrderOriginPermit2Test:test_fillPermit2_multi() (gas: 1007964) -OrderOriginPermit2Test:test_initiatePermit2() (gas: 233946) -OrderOriginPermit2Test:test_initiatePermit2_multi() (gas: 984506) -OrdersTest:test_fill_ERC20() (gas: 71459) -OrdersTest:test_fill_ETH() (gas: 69090) -OrdersTest:test_fill_both() (gas: 169814) -OrdersTest:test_fill_multiETH() (gas: 132830) -OrdersTest:test_fill_underflowETH() (gas: 115817) -OrdersTest:test_initiate_ERC20() (gas: 82526) -OrdersTest:test_initiate_ETH() (gas: 45597) -OrdersTest:test_initiate_both() (gas: 119816) -OrdersTest:test_initiate_multiERC20() (gas: 175432) -OrdersTest:test_initiate_multiETH() (gas: 76000) -OrdersTest:test_orderExpired() (gas: 28383) -OrdersTest:test_sweepERC20() (gas: 60695) -OrdersTest:test_sweepETH() (gas: 83379) -OrdersTest:test_underflowETH() (gas: 63976) -PassagePermit2Test:test_disallowedEnterPermit2() (gas: 691528) -PassagePermit2Test:test_enterTokenPermit2() (gas: 144090) -PassageTest:test_configureEnter() (gas: 128735) -PassageTest:test_disallowedEnter() (gas: 57503) -PassageTest:test_enter() (gas: 25519) -PassageTest:test_enterToken() (gas: 65326) -PassageTest:test_enterToken_defaultChain() (gas: 63912) -PassageTest:test_enter_defaultChain() (gas: 24055) -PassageTest:test_fallback() (gas: 22093) -PassageTest:test_onlyTokenAdmin() (gas: 17173) -PassageTest:test_receive() (gas: 21487) -PassageTest:test_setUp() (gas: 17000) -PassageTest:test_withdraw() (gas: 60168) -RollupPassagePermit2Test:test_exitTokenPermit2() (gas: 127878) -RollupPassageTest:test_exit() (gas: 22403) -RollupPassageTest:test_exitToken() (gas: 50824) -RollupPassageTest:test_fallback() (gas: 20509) -RollupPassageTest:test_receive() (gas: 19948) -TransactTest:test_configureGas() (gas: 22828) -TransactTest:test_enterTransact() (gas: 103979) -TransactTest:test_onlyGasAdmin() (gas: 8810) -TransactTest:test_setUp() (gas: 17494) -TransactTest:test_transact() (gas: 101449) -TransactTest:test_transact_defaultChain() (gas: 100562) -TransactTest:test_transact_globalGasLimit() (gas: 104972) -TransactTest:test_transact_perTransactGasLimit() (gas: 32776) -ZenithTest:test_addSequencer() (gas: 88101) -ZenithTest:test_badSignature() (gas: 37061) -ZenithTest:test_incorrectHostBlock() (gas: 35075) -ZenithTest:test_notSequencer() (gas: 33887) -ZenithTest:test_notSequencerAdmin() (gas: 10125) -ZenithTest:test_onePerBlock() (gas: 68153) -ZenithTest:test_removeSequencer() (gas: 39476) -ZenithTest:test_setUp() (gas: 8366) -ZenithTest:test_submitBlock() (gas: 63313) \ No newline at end of file +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: 89995) +OrdersTest:test_underflowETH() (gas: 69404) +PassagePermit2Test:test_disallowedEnterPermit2() (gas: 1130187) +PassagePermit2Test:test_enterTokenPermit2() (gas: 150794) +PassageTest:test_configureEnter() (gas: 141651) +PassageTest:test_disallowedEnter() (gas: 58928) +PassageTest:test_enter() (gas: 26523) +PassageTest:test_enterToken() (gas: 66880) +PassageTest:test_enterToken_defaultChain() (gas: 65384) +PassageTest:test_enter_defaultChain() (gas: 24949) +PassageTest:test_fallback() (gas: 22784) +PassageTest:test_onlyTokenAdmin() (gas: 19145) +PassageTest:test_receive() (gas: 22222) +PassageTest:test_setUp() (gas: 23289) +PassageTest:test_withdraw() (gas: 64486) +RollupPassagePermit2Test:test_exitTokenPermit2() (gas: 135717) +RollupPassageTest:test_exit() (gas: 23114) +RollupPassageTest:test_exitToken() (gas: 53266) +RollupPassageTest:test_fallback() (gas: 20910) +RollupPassageTest:test_receive() (gas: 20393) +TransactTest:test_configureGas() (gas: 27486) +TransactTest:test_enterTransact() (gas: 127464) +TransactTest:test_onlyGasAdmin() (gas: 9895) +TransactTest:test_setUp() (gas: 23757) +TransactTest:test_transact() (gas: 107567) +TransactTest:test_transact_defaultChain() (gas: 106574) +TransactTest:test_transact_globalGasLimit() (gas: 117828) +TransactTest:test_transact_perTransactGasLimit() (gas: 34574) +ZenithTest:test_addSequencer() (gas: 98616) +ZenithTest:test_badSignature() (gas: 46355) +ZenithTest:test_incorrectHostBlock() (gas: 42276) +ZenithTest:test_notSequencer() (gas: 39566) +ZenithTest:test_notSequencerAdmin() (gas: 11279) +ZenithTest:test_onePerBlock() (gas: 78387) +ZenithTest:test_removeSequencer() (gas: 50114) +ZenithTest:test_setUp() (gas: 8035) +ZenithTest:test_submitBlock() (gas: 70434) \ No newline at end of file diff --git a/lib/forge-std b/lib/forge-std index ae570fe..c7be2a3 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit ae570fec082bfe1c1f45b0acca4a2b4f84d345ce +Subproject commit c7be2a3481f9e51230880bb0949072c7e3a4da82 diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index c80b675..3790c59 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit c80b675b8db1d951b8b3734df59530d0d3be064b +Subproject commit 3790c59623e99cb0272ddf84e6a17a5979d06b35 diff --git a/lib/safe-smart-account b/lib/safe-smart-account index bf943f8..0095f1a 160000 --- a/lib/safe-smart-account +++ b/lib/safe-smart-account @@ -1 +1 @@ -Subproject commit bf943f80fec5ac647159d26161446ac5d716a294 +Subproject commit 0095f1aa113255d97b476e625760514cc7d10982 diff --git a/lib/stablecoin-evm b/lib/stablecoin-evm index 405efc1..c8c31b2 160000 --- a/lib/stablecoin-evm +++ b/lib/stablecoin-evm @@ -1 +1 @@ -Subproject commit 405efc100c016ed1a437063b6274b4e24ea7b8b1 +Subproject commit c8c31b249341bf3ffb2e8dbff41977c392a260c5 diff --git a/test/Helpers.t.sol b/test/Helpers.t.sol index a2bb7f8..3c4f6fa 100644 --- a/test/Helpers.t.sol +++ b/test/Helpers.t.sol @@ -4,23 +4,13 @@ pragma solidity 0.8.26; // system contracts import {Zenith} from "../src/Zenith.sol"; import {UsesPermit2} from "../src/UsesPermit2.sol"; +import {RollupOrders} from "../src/orders/RollupOrders.sol"; // deps -import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; -import {ERC20Burnable} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol"; import {Test, console2} from "forge-std/Test.sol"; +import {SignetStdTest, TestERC20} from "./SignetStdTest.t.sol"; -contract TestERC20 is ERC20Burnable { - constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {} - - function mint(address recipient, uint256 amount) external { - _mint(recipient, amount); - } -} - -contract Permit2Helpers is Test { - address permit2Contract; - +contract Permit2Helpers is SignetStdTest { /// @notice the address signing the Permit messages and its pk uint256 ownerKey = 123; address owner = vm.addr(ownerKey); @@ -28,6 +18,14 @@ contract Permit2Helpers is Test { // permit consts UsesPermit2.Witness witness; + // single permit + UsesPermit2.Permit2 singlePermit; + ISignatureTransfer.SignatureTransferDetails singleTransferDetails; + + // batch permit + UsesPermit2.Permit2Batch batchPermit; + ISignatureTransfer.SignatureTransferDetails[] batchTransferDetails; + bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; @@ -50,18 +48,6 @@ contract Permit2Helpers is Test { _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME); } - function _setUpPermit2(address token, uint256 amount) internal { - vm.label(owner, "owner"); - - // setup permit2 contract - permit2Contract = 0x000000000022D473030F116dDEE9F6B43aC78BA3; - vm.label(address(permit2Contract), "permit2"); - - // approve permit2 - vm.prank(owner); - TestERC20(token).approve(address(permit2Contract), amount * 10000); - } - /// @notice given a Permit and a Witness, produce a signature from the `owner` function signPermit( uint256 signingKey, @@ -154,7 +140,7 @@ contract Permit2Helpers is Test { /// @notice Builds a domain separator using the current chainId and contract address. function _buildDomainSeparator(bytes32 typeHash, bytes32 nameHash) private view returns (bytes32) { - return keccak256(abi.encode(typeHash, nameHash, block.chainid, permit2Contract)); + return keccak256(abi.encode(typeHash, nameHash, block.chainid, PERMIT2)); } /// @notice Creates an EIP-712 typed data hash @@ -187,22 +173,3 @@ interface IBatchPermit { bytes calldata /*signature*/ ) external; } - -contract HelpersTest is Test { - Zenith public target; - - function setUp() public { - vm.createSelectFork("https://rpc.holesky.ethpandaops.io"); - target = new Zenith(0x29403F107781ea45Bf93710abf8df13F67f2008f); - } - - function check_signature() public { - bytes32 hash = 0xdcd0af9a45fa82dcdd1e4f9ef703d8cd459b6950c0638154c67117e86facf9c1; - uint8 v = 28; - bytes32 r = 0xb89764d107f812dbbebb925711b320d336ff8d03f08570f051123df86334f3f5; - bytes32 s = 0x394cd592577ce6307154045607b9b18ecc1de0eb636e996981477c2d9b1a7675; - address signer = ecrecover(hash, v, r, s); - vm.label(signer, "recovered signer"); - assertEq(signer, 0x5b0517Dc94c413a5871536872605522E54C85a03); - } -} diff --git a/test/Orders.t.sol b/test/Orders.t.sol index 06aa0a8..51c599d 100644 --- a/test/Orders.t.sol +++ b/test/Orders.t.sol @@ -9,18 +9,20 @@ import {OrderOrigin} from "../src/orders/OrderOrigin.sol"; import {TestERC20} from "./Helpers.t.sol"; import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; import {Test, console2} from "forge-std/Test.sol"; +import {SignetStdTest} from "./SignetStdTest.t.sol"; -contract OrdersTest is Test { +contract OrdersTest is SignetStdTest { RollupOrders public target; + IOrders.Input[] public inputs; IOrders.Output[] public outputs; address token; address token2; - uint32 chainId = 3; + address recipient = address(0x123); uint256 amount = 200; - uint256 deadline = block.timestamp; + uint256 deadline; event Filled(IOrders.Output[] outputs); @@ -29,15 +31,17 @@ contract OrdersTest is Test { event Sweep(address indexed recipient, address indexed token, uint256 amount); function setUp() public virtual { - target = new RollupOrders(address(0)); + target = ROLLUP_ORDERS; - // setup token - token = address(new TestERC20("hi", "HI")); + // setup first token + token = address(ROLLUP_WBTC); + vm.prank(ROLLUP_MINTER); TestERC20(token).mint(address(this), amount * 10000); TestERC20(token).approve(address(target), amount * 10000); // setup second token - token2 = address(new TestERC20("bye", "BYE")); + token2 = address(ROLLUP_WETH); + vm.prank(ROLLUP_MINTER); TestERC20(token2).mint(address(this), amount * 10000); TestERC20(token2).approve(address(target), amount * 10000); @@ -45,8 +49,10 @@ contract OrdersTest is Test { IOrders.Input memory input = IOrders.Input(token, amount); inputs.push(input); - IOrders.Output memory output = IOrders.Output(token, amount, recipient, chainId); + IOrders.Output memory output = IOrders.Output(token, amount, recipient, ROLLUP_CHAIN_ID); outputs.push(output); + + deadline = block.timestamp; } // input ERC20 @@ -143,9 +149,6 @@ contract OrdersTest is Test { } function test_sweepETH() public { - // set self as Builder - vm.coinbase(address(this)); - // initiate an ETH order inputs[0].token = address(0); target.initiate{value: amount}(deadline, inputs, outputs); @@ -161,9 +164,6 @@ contract OrdersTest is Test { } function test_sweepERC20() public { - // set self as Builder - vm.coinbase(address(this)); - // send ERC20 to the contract TestERC20(token).transfer(address(target), amount); @@ -194,7 +194,7 @@ contract OrdersTest is Test { function test_fill_both() public { // add ETH output - outputs.push(IOrders.Output(address(0), amount * 2, recipient, chainId)); + outputs.push(IOrders.Output(address(0), amount * 2, recipient, ROLLUP_CHAIN_ID)); // expect Outputs are filled, ERC20 is transferred vm.expectEmit(); @@ -211,7 +211,7 @@ contract OrdersTest is Test { // change first output to ETH outputs[0].token = address(0); // add second ETH oputput - outputs.push(IOrders.Output(address(0), amount * 2, recipient, chainId)); + outputs.push(IOrders.Output(address(0), amount * 2, recipient, ROLLUP_CHAIN_ID)); // expect Order event is initiated vm.expectEmit(); @@ -226,7 +226,7 @@ contract OrdersTest is Test { // change first output to ETH outputs[0].token = address(0); // add second ETH output - outputs.push(IOrders.Output(address(0), 1, recipient, chainId)); + outputs.push(IOrders.Output(address(0), 1, recipient, ROLLUP_CHAIN_ID)); // total ETH outputs should be `amount` + 1; function should underflow only sending `amount` vm.expectRevert(); diff --git a/test/Passage.t.sol b/test/Passage.t.sol index f48dab5..1687b0a 100644 --- a/test/Passage.t.sol +++ b/test/Passage.t.sol @@ -10,63 +10,47 @@ 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 {SignetStdTest} from "./SignetStdTest.t.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -contract PassageTest is Test { +contract PassageTest is SignetStdTest { using Address for address payable; Passage public target; address token; address newToken; - uint256 chainId = 3; address recipient = address(0x123); uint256 amount = 200; - address to = address(0x01); - bytes data = abi.encodeWithSelector(ERC20.transfer.selector, recipient, amount); - uint256 value = 100; - uint256 gas = 10_000_000; - uint256 maxFeePerGas = 50; - event Enter(uint256 indexed rollupChainId, address indexed rollupRecipient, uint256 amount); event EnterToken( uint256 indexed rollupChainId, address indexed rollupRecipient, address indexed token, uint256 amount ); - event Transact( - uint256 indexed rollupChainId, - address indexed sender, - address indexed to, - bytes data, - uint256 value, - uint256 gas, - uint256 maxFeePerGas - ); - - event Withdrawal(address indexed token, address indexed recipient, uint256 amount); - event EnterConfigured(address indexed token, bool indexed canEnter); - function setUp() public { - // deploy token one, configured at deploy time - token = address(new TestERC20("hi", "HI")); - TestERC20(token).mint(address(this), amount * 10000); + event Withdrawal(address indexed token, address indexed recipient, uint256 amount); + function setUp() public virtual { // deploy target - address[] memory initialEnterTokens = new address[](1); - initialEnterTokens[0] = token; - target = new Passage(block.chainid + 1, address(this), initialEnterTokens, address(0)); + target = HOST_PASSAGE; + + // setup token + token = address(HOST_WETH); + // mint WETH by sending ETH + payable(token).sendValue(amount * 10000); TestERC20(token).approve(address(target), amount * 10000); - // deploy token two, don't configure - newToken = address(new TestERC20("bye", "BYE")); + // 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); } function test_setUp() public { - assertEq(target.defaultRollupChainId(), block.chainid + 1); - assertEq(target.tokenAdmin(), address(this)); + assertEq(target.defaultRollupChainId(), ROLLUP_CHAIN_ID); + assertEq(target.tokenAdmin(), TOKEN_ADMIN); assertTrue(target.canEnter(token)); assertFalse(target.canEnter(newToken)); } @@ -89,28 +73,32 @@ contract PassageTest is Test { // enter not allowed by default assertFalse(target.canEnter(newToken)); vm.expectRevert(abi.encodeWithSelector(Passage.DisallowedEnter.selector, newToken)); - target.enterToken(chainId, recipient, newToken, amount); + target.enterToken(ROLLUP_CHAIN_ID, recipient, newToken, amount); // allow enter + vm.startPrank(TOKEN_ADMIN); vm.expectEmit(); emit EnterConfigured(newToken, true); target.configureEnter(newToken, true); + vm.stopPrank(); // enter is allowed assertTrue(target.canEnter(newToken)); vm.expectEmit(); - emit EnterToken(chainId, recipient, newToken, amount); - target.enterToken(chainId, recipient, newToken, amount); + emit EnterToken(ROLLUP_CHAIN_ID, recipient, newToken, amount); + target.enterToken(ROLLUP_CHAIN_ID, recipient, newToken, amount); // disallow enter + vm.startPrank(TOKEN_ADMIN); vm.expectEmit(); emit EnterConfigured(newToken, false); target.configureEnter(newToken, false); + vm.stopPrank(); // enter not allowed again assertFalse(target.canEnter(newToken)); vm.expectRevert(abi.encodeWithSelector(Passage.DisallowedEnter.selector, newToken)); - target.enterToken(chainId, recipient, newToken, amount); + target.enterToken(ROLLUP_CHAIN_ID, recipient, newToken, amount); } function test_receive() public { @@ -127,8 +115,8 @@ contract PassageTest is Test { function test_enter() public { vm.expectEmit(); - emit Enter(chainId, recipient, amount); - target.enter{value: amount}(chainId, recipient); + emit Enter(ROLLUP_CHAIN_ID, recipient, amount); + target.enter{value: amount}(ROLLUP_CHAIN_ID, recipient); } function test_enter_defaultChain() public { @@ -139,11 +127,11 @@ contract PassageTest is Test { function test_enterToken() public { vm.expectEmit(); - emit EnterToken(chainId, recipient, token, amount); + emit EnterToken(ROLLUP_CHAIN_ID, recipient, token, amount); vm.expectCall( token, abi.encodeWithSelector(ERC20.transferFrom.selector, address(this), address(target), amount) ); - target.enterToken(chainId, recipient, token, amount); + target.enterToken(ROLLUP_CHAIN_ID, recipient, token, amount); } function test_enterToken_defaultChain() public { @@ -156,8 +144,9 @@ contract PassageTest is Test { } function test_withdraw() public { - TestERC20(token).mint(address(target), amount); + IERC20(token).transfer(address(target), amount); + vm.startPrank(TOKEN_ADMIN); vm.expectEmit(); emit Withdrawal(token, recipient, amount); vm.expectCall(token, abi.encodeWithSelector(ERC20.transfer.selector, recipient, amount)); @@ -165,7 +154,7 @@ contract PassageTest is Test { } } -contract RollupPassageTest is Test { +contract RollupPassageTest is SignetStdTest { using Address for address payable; RollupPassage public target; @@ -178,11 +167,12 @@ contract RollupPassageTest is Test { event ExitToken(address indexed hostRecipient, address indexed token, uint256 amount); function setUp() public virtual { - // deploy target - target = new RollupPassage(address(0)); + // setup target + target = ROLLUP_PASSAGE; - // deploy token - token = address(new TestERC20("hi", "HI")); + // setup token + token = address(ROLLUP_WETH); + vm.prank(ROLLUP_MINTER); TestERC20(token).mint(address(this), amount * 10000); TestERC20(token).approve(address(target), amount * 10000); } diff --git a/test/Permit2Orders.t.sol b/test/Permit2Orders.t.sol index 5c9afdd..5b65fab 100644 --- a/test/Permit2Orders.t.sol +++ b/test/Permit2Orders.t.sol @@ -10,200 +10,176 @@ import {Permit2Helpers, IBatchPermit, TestERC20} from "./Helpers.t.sol"; import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol"; import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; import {Test, console2} from "forge-std/Test.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -contract Permit2BatchTest is Permit2Helpers { - // batch permit - UsesPermit2.Permit2Batch permit2; - ISignatureTransfer.SignatureTransferDetails[] transferDetails; - - function _setupBatchPermit(address token, uint256 amount) internal { - // create a batch permit with generic details - permit2.permit.permitted.push(ISignatureTransfer.TokenPermissions({token: token, amount: amount})); - permit2.permit.nonce = 0; - permit2.permit.deadline = block.timestamp; - permit2.owner = owner; - } -} - -contract OrderOriginPermit2Test is Permit2BatchTest { +contract OrderOriginPermit2Test is Permit2Helpers { RollupOrders public target; IOrders.Input[] public inputs; IOrders.Output[] public outputs; - mapping(address => bool) isToken; - address token; - uint32 chainId = 3; - address recipient = address(0x123); + address recipient = address(0xdeadbeef); uint256 amount = 200; - uint256 deadline = block.timestamp; - - address tokenRecipient = address(0xdeadbeef); + uint256 deadline; event Order(uint256 deadline, IOrders.Input[] inputs, IOrders.Output[] outputs); event Filled(IOrders.Output[] outputs); function setUp() public virtual { - vm.createSelectFork("https://ethereum-rpc.publicnode.com"); - // deploy token - token = address(new TestERC20("hi", "HI")); - TestERC20(token).mint(owner, amount * 10000); - isToken[token] = true; + // setup Orders contract + target = ROLLUP_ORDERS; + vm.label(address(target), "orders"); + vm.label(address(PERMIT2), "permit2"); + vm.label(owner, "owner"); - // setup permit2 contract & permit details - _setUpPermit2(token, amount); - _setupBatchPermit(token, amount); + // setup token + token = address(ROLLUP_WBTC); + // mint tokens to owner + vm.prank(ROLLUP_MINTER); + TestERC20(token).mint(owner, amount * 10000); + // approve permit2 from owner + vm.prank(owner); + TestERC20(token).approve(address(PERMIT2), amount * 10000); - // deploy Orders contract - target = new RollupOrders(address(permit2Contract)); - vm.label(address(target), "orders"); + // set basic permit details + batchPermit.permit.nonce = 0; + batchPermit.permit.deadline = block.timestamp; + batchPermit.owner = owner; + batchPermit.permit.permitted.push(ISignatureTransfer.TokenPermissions({token: token, amount: amount})); + batchTransferDetails.push(ISignatureTransfer.SignatureTransferDetails({to: recipient, requestedAmount: amount})); // setup Order Inputs/Outputs IOrders.Input memory input = IOrders.Input(token, amount); inputs.push(input); - IOrders.Output memory output = IOrders.Output(token, amount, recipient, chainId); + IOrders.Output memory output = IOrders.Output(token, amount, recipient, ROLLUP_CHAIN_ID); outputs.push(output); + deadline = block.timestamp; + // construct Orders witness witness = target.outputWitness(outputs); // sign permit + witness - permit2.signature = signPermit(ownerKey, address(target), permit2.permit, witness); + batchPermit.signature = signPermit(ownerKey, address(target), batchPermit.permit, witness); } function test_initiatePermit2() public { - // construct transfer details - transferDetails.push(ISignatureTransfer.SignatureTransferDetails({to: tokenRecipient, requestedAmount: amount})); - // expect Order event is initiated, ERC20 is transferred vm.expectEmit(); - emit Order(permit2.permit.deadline, inputs, outputs); + emit Order(batchPermit.permit.deadline, inputs, outputs); vm.expectCall( - address(permit2Contract), + address(PERMIT2), abi.encodeWithSelector( IBatchPermit.permitWitnessTransferFrom.selector, - permit2.permit, - transferDetails, + batchPermit.permit, + batchTransferDetails, owner, witness.witnessHash, witness.witnessTypeString, - permit2.signature + batchPermit.signature ) ); - vm.expectCall(token, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, tokenRecipient, amount)); - target.initiatePermit2(tokenRecipient, outputs, permit2); + vm.expectCall(token, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, recipient, amount)); + target.initiatePermit2(recipient, outputs, batchPermit); } // input multiple ERC20s function test_initiatePermit2_multi() public { - // construct transfer details - transferDetails.push(ISignatureTransfer.SignatureTransferDetails({to: tokenRecipient, requestedAmount: amount})); - // setup second token - address token2 = address(new TestERC20("bye", "BYE")); + address token2 = address(ROLLUP_WETH); + // mint tokens to owner + vm.prank(ROLLUP_MINTER); TestERC20(token2).mint(owner, amount * 10000); + // approve permit2 from owner vm.prank(owner); - TestERC20(token2).approve(address(permit2Contract), amount * 10000); - - // add second token input - inputs.push(IOrders.Input(token2, amount * 2)); + TestERC20(token2).approve(address(PERMIT2), amount * 10000); - // add TokenPermissions - permit2.permit.permitted.push(ISignatureTransfer.TokenPermissions({token: token2, amount: amount * 2})); + // add second token to Inputs, TokenPermissions, and TransferDetails + inputs.push(IOrders.Input(token2, amount)); + batchPermit.permit.permitted.push(ISignatureTransfer.TokenPermissions({token: token2, amount: amount})); + batchTransferDetails.push(ISignatureTransfer.SignatureTransferDetails({to: recipient, requestedAmount: amount})); - // add TransferDetails - transferDetails.push( - ISignatureTransfer.SignatureTransferDetails({to: tokenRecipient, requestedAmount: amount * 2}) - ); - - // re-sign new permit - permit2.signature = signPermit(ownerKey, address(target), permit2.permit, witness); + // re-sign new permit (witness is the same because Outputs haven't changed) + batchPermit.signature = signPermit(ownerKey, address(target), batchPermit.permit, witness); // expect Order event is emitted, ERC20 is transferred vm.expectEmit(); - emit Order(permit2.permit.deadline, inputs, outputs); + emit Order(batchPermit.permit.deadline, inputs, outputs); vm.expectCall( - address(permit2Contract), + address(PERMIT2), abi.encodeWithSelector( IBatchPermit.permitWitnessTransferFrom.selector, - permit2.permit, - transferDetails, + batchPermit.permit, + batchTransferDetails, owner, witness.witnessHash, witness.witnessTypeString, - permit2.signature + batchPermit.signature ) ); - vm.expectCall(token, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, tokenRecipient, amount)); - vm.expectCall(token2, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, tokenRecipient, amount * 2)); - target.initiatePermit2(tokenRecipient, outputs, permit2); + vm.expectCall(token, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, recipient, amount)); + vm.expectCall(token2, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, recipient, amount)); + target.initiatePermit2(recipient, outputs, batchPermit); } function test_fillPermit2() public { - // construct transfer details - transferDetails.push(ISignatureTransfer.SignatureTransferDetails({to: recipient, requestedAmount: amount})); - vm.expectEmit(); emit Filled(outputs); vm.expectCall( - address(permit2Contract), + address(PERMIT2), abi.encodeWithSelector( IBatchPermit.permitWitnessTransferFrom.selector, - permit2.permit, - transferDetails, + batchPermit.permit, + batchTransferDetails, owner, witness.witnessHash, witness.witnessTypeString, - permit2.signature + batchPermit.signature ) ); vm.expectCall(token, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, recipient, amount)); - target.fillPermit2(outputs, permit2); + target.fillPermit2(outputs, batchPermit); } function test_fillPermit2_multi() public { - // construct transfer details - transferDetails.push(ISignatureTransfer.SignatureTransferDetails({to: recipient, requestedAmount: amount})); - // setup second token - address token2 = address(new TestERC20("bye", "BYE")); + address token2 = address(ROLLUP_WETH); + // mint tokens to owner + vm.prank(ROLLUP_MINTER); TestERC20(token2).mint(owner, amount * 10000); + // approve permit2 from owner vm.prank(owner); - TestERC20(token2).approve(address(permit2Contract), amount * 10000); - - // add second token output - outputs.push(IOrders.Output(token2, amount * 2, recipient, chainId)); - - // add TokenPermissions - permit2.permit.permitted.push(ISignatureTransfer.TokenPermissions({token: token2, amount: amount * 2})); + TestERC20(token2).approve(address(PERMIT2), amount * 10000); - // add TransferDetails - transferDetails.push(ISignatureTransfer.SignatureTransferDetails({to: recipient, requestedAmount: amount * 2})); + // add second token to Outputs, TokenPermissions, and TransferDetails + outputs.push(IOrders.Output(token2, amount, recipient, ROLLUP_CHAIN_ID)); + batchPermit.permit.permitted.push(ISignatureTransfer.TokenPermissions({token: token2, amount: amount})); + batchTransferDetails.push(ISignatureTransfer.SignatureTransferDetails({to: recipient, requestedAmount: amount})); // re-sign new permit witness = target.outputWitness(outputs); - permit2.signature = signPermit(ownerKey, address(target), permit2.permit, witness); + batchPermit.signature = signPermit(ownerKey, address(target), batchPermit.permit, witness); // expect Filled event is emitted, ERC20 is transferred vm.expectEmit(); emit Filled(outputs); vm.expectCall( - address(permit2Contract), + address(PERMIT2), abi.encodeWithSelector( IBatchPermit.permitWitnessTransferFrom.selector, - permit2.permit, - transferDetails, + batchPermit.permit, + batchTransferDetails, owner, witness.witnessHash, witness.witnessTypeString, - permit2.signature + batchPermit.signature ) ); vm.expectCall(token, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, recipient, amount)); - vm.expectCall(token2, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, recipient, amount * 2)); - target.fillPermit2(outputs, permit2); + vm.expectCall(token2, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, recipient, amount)); + target.fillPermit2(outputs, batchPermit); } } diff --git a/test/Permit2Passage.t.sol b/test/Permit2Passage.t.sol index 580787e..8af9bdd 100644 --- a/test/Permit2Passage.t.sol +++ b/test/Permit2Passage.t.sol @@ -11,30 +11,16 @@ import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol" import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; import {ERC20Burnable} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {Test, console2} from "forge-std/Test.sol"; +import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol"; -contract SharedPermit2Test is Permit2Helpers { - // single permit - UsesPermit2.Permit2 permit2; - ISignatureTransfer.SignatureTransferDetails transferDetails; - - function _setupSinglePermit(address token, uint256 amount) internal { - // create a single permit with generic details - permit2.permit = ISignatureTransfer.PermitTransferFrom({ - permitted: ISignatureTransfer.TokenPermissions({token: token, amount: amount}), - nonce: 0, - deadline: block.timestamp - }); - permit2.owner = owner; - } -} +contract PassagePermit2Test is Permit2Helpers { + using Address for address payable; -contract PassagePermit2Test is SharedPermit2Test { Passage public target; // token consts address token; uint256 amount = 200; - uint256 chainId = 3; address recipient = address(0x123); event EnterToken( @@ -42,125 +28,135 @@ contract PassagePermit2Test is SharedPermit2Test { ); function setUp() public virtual { - vm.createSelectFork("https://ethereum-rpc.publicnode.com"); - - // deploy token - token = address(new TestERC20("hi", "HI")); - TestERC20(token).mint(owner, amount * 10000); - - // configure token for passage - address[] memory initialEnterTokens = new address[](2); - initialEnterTokens[0] = token; - - // setup permit2 contract & permit details - _setUpPermit2(token, amount); - _setupSinglePermit(token, amount); - - // deploy Passage - target = new Passage(block.chainid + 1, address(this), initialEnterTokens, address(permit2Contract)); + // setup Passage + target = HOST_PASSAGE; vm.label(address(target), "passage"); + vm.label(address(PERMIT2), "permit2"); + vm.label(owner, "owner"); + + // setup token + token = address(HOST_WETH); + // mint WETH by sending ETH + payable(token).sendValue(amount * 10000); + // send WETH to Permit2 signer + TestERC20(token).transfer(owner, amount * 10000); + // approve permit2 from owner + vm.prank(owner); + TestERC20(token).approve(address(PERMIT2), amount * 10000); + + // set basic permit details + singlePermit.permit.nonce = 0; + singlePermit.permit.deadline = block.timestamp; + singlePermit.owner = owner; + singlePermit.permit.permitted = ISignatureTransfer.TokenPermissions({token: token, amount: amount}); + singleTransferDetails = + ISignatureTransfer.SignatureTransferDetails({to: address(target), requestedAmount: amount}); // construct Enter witness - witness = target.enterWitness(chainId, recipient); + witness = target.enterWitness(ROLLUP_CHAIN_ID, recipient); // sign permit + witness - permit2.signature = signPermit(ownerKey, address(target), permit2.permit, witness); - - // construct transfer details - transferDetails = ISignatureTransfer.SignatureTransferDetails({to: address(target), requestedAmount: amount}); + singlePermit.signature = signPermit(ownerKey, address(target), singlePermit.permit, witness); } function test_enterTokenPermit2() public { vm.expectEmit(); - emit EnterToken(chainId, recipient, token, amount); + emit EnterToken(ROLLUP_CHAIN_ID, recipient, token, amount); vm.expectCall( - address(permit2Contract), + address(PERMIT2), abi.encodeWithSelector( ISinglePermit.permitWitnessTransferFrom.selector, - permit2.permit, - transferDetails, + singlePermit.permit, + singleTransferDetails, owner, witness.witnessHash, witness.witnessTypeString, - permit2.signature + singlePermit.signature ) ); vm.expectCall(token, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, address(target), amount)); - target.enterTokenPermit2(chainId, recipient, permit2); + target.enterTokenPermit2(ROLLUP_CHAIN_ID, recipient, singlePermit); } function test_disallowedEnterPermit2() public { // deploy new token & approve permit2 - address newToken = address(new TestERC20("bye", "BYE")); + address newToken = address(new TestERC20("bye", "BYE", 18)); + // mint tokens to owner TestERC20(newToken).mint(owner, amount * 10000); + // approve permit2 from owner vm.prank(owner); - TestERC20(newToken).approve(address(permit2Contract), amount * 10000); + TestERC20(newToken).approve(address(PERMIT2), amount * 10000); - // edit permit token to new token - permit2.permit.permitted.token = newToken; + // modify permit details + singlePermit.permit.permitted = ISignatureTransfer.TokenPermissions({token: newToken, amount: amount}); - // re-sign permit + witness - permit2.signature = signPermit(ownerKey, address(target), permit2.permit, witness); + // re-sign permit + same recipient witness + singlePermit.signature = signPermit(ownerKey, address(target), singlePermit.permit, witness); // expect revert DisallowedEnter vm.expectRevert(abi.encodeWithSelector(Passage.DisallowedEnter.selector, newToken)); - target.enterTokenPermit2(chainId, recipient, permit2); + target.enterTokenPermit2(ROLLUP_CHAIN_ID, recipient, singlePermit); } } -contract RollupPassagePermit2Test is SharedPermit2Test { +contract RollupPassagePermit2Test is Permit2Helpers { RollupPassage public target; // token consts address token; uint256 amount = 200; - uint256 chainId = 3; address recipient = address(0x123); event ExitToken(address indexed hostRecipient, address indexed token, uint256 amount); function setUp() public virtual { - vm.createSelectFork("https://ethereum-rpc.publicnode.com"); - - // deploy token & approve permit2 - token = address(new TestERC20("hi", "HI")); + // setup RollupPassage + target = ROLLUP_PASSAGE; + vm.label(address(target), "rollup_passage"); + vm.label(address(PERMIT2), "permit2"); + vm.label(owner, "owner"); + + // setup token + token = address(ROLLUP_WBTC); + // mint tokens to owner + vm.prank(ROLLUP_MINTER); TestERC20(token).mint(owner, amount * 10000); + // approve permit2 from owner + vm.prank(owner); + TestERC20(token).approve(address(PERMIT2), amount * 10000); - // setup permit2 contract & permit details - _setUpPermit2(token, amount); - _setupSinglePermit(token, amount); - - // deploy RollupPassage - target = new RollupPassage(address(permit2Contract)); - vm.label(address(target), "passage"); + // set basic permit details + singlePermit.permit.nonce = 0; + singlePermit.permit.deadline = block.timestamp; + singlePermit.owner = owner; + singlePermit.permit.permitted = ISignatureTransfer.TokenPermissions({token: token, amount: amount}); + singleTransferDetails = + ISignatureTransfer.SignatureTransferDetails({to: address(target), requestedAmount: amount}); // construct Exit witness witness = target.exitWitness(recipient); // sign permit + witness - permit2.signature = signPermit(ownerKey, address(target), permit2.permit, witness); - - // construct transfer details - transferDetails = ISignatureTransfer.SignatureTransferDetails({to: address(target), requestedAmount: amount}); + singlePermit.signature = signPermit(ownerKey, address(target), singlePermit.permit, witness); } function test_exitTokenPermit2() public { vm.expectEmit(); emit ExitToken(recipient, token, amount); vm.expectCall( - address(permit2Contract), + address(PERMIT2), abi.encodeWithSelector( ISinglePermit.permitWitnessTransferFrom.selector, - permit2.permit, - transferDetails, + singlePermit.permit, + singleTransferDetails, owner, witness.witnessHash, witness.witnessTypeString, - permit2.signature + singlePermit.signature ) ); vm.expectCall(token, abi.encodeWithSelector(ERC20.transferFrom.selector, owner, address(target), amount)); vm.expectCall(token, abi.encodeWithSelector(ERC20Burnable.burn.selector, amount)); - target.exitTokenPermit2(recipient, permit2); + target.exitTokenPermit2(recipient, singlePermit); } } diff --git a/test/SignetStd.sol b/test/SignetStd.sol new file mode 100644 index 0000000..84928df --- /dev/null +++ b/test/SignetStd.sol @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {RollupOrders} from "../src/orders/RollupOrders.sol"; +import {RollupPassage} from "../src/passage/RollupPassage.sol"; +import {Zenith} from "../src/Zenith.sol"; +import {Transactor} from "../src/Transactor.sol"; +import {HostOrders} from "../src/orders/HostOrders.sol"; +import {Passage} from "../src/passage/Passage.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; + +/// @title PecorinoConstants +/// @author init4 +/// @notice Constants for the Pecorino testnet. +/// @dev These constants are used to configure the SignetStd contract in its +/// constructor, if the chain ID matches the Pecorino testnet chain ID. +library PecorinoConstants { + /// @notice The Pecorino Rollup chain ID. + uint32 constant ROLLUP_CHAIN_ID = 14174; + /// @notice The Rollup Passage contract for the Pecorino testnet. + RollupPassage constant ROLLUP_PASSAGE = RollupPassage(payable(0x0000000000007369676E65742D70617373616765)); + /// @notice The Rollup Orders contract for the Pecorino testnet. + RollupOrders constant ROLLUP_ORDERS = RollupOrders(0x000000000000007369676E65742D6f7264657273); + /// @notice WETH token address for the Pecorino testnet. + IERC20 constant ROLLUP_WETH = IERC20(0x0000000000000000007369676e65742d77657468); + /// @notice WBTC token address for the Pecorino testnet. + IERC20 constant ROLLUP_WBTC = IERC20(0x0000000000000000007369676e65742D77627463); + /// @notice WUSD token address for the Pecorino testnet. + IERC20 constant ROLLUP_WUSD = IERC20(0x0000000000000000007369676e65742D77757364); + + /// @notice The Pecorino host chain ID. + uint32 constant HOST_CHAIN_ID = 3151908; + /// @notice The Passage contract on the host network. + Passage constant HOST_PASSAGE = Passage(payable(0x12585352AA1057443D6163B539EfD4487f023182)); + /// @notice The Orders contract on the host network. + HostOrders constant HOST_ORDERS = HostOrders(0x0A4f505364De0Aa46c66b15aBae44eBa12ab0380); + /// @notice The Zenith contract for the Pecorino testnet. + Zenith constant HOST_ZENITH = Zenith(0xf17E98baF73F7C78a42D73DF4064de5B7A20EcA6); + /// @notice The Transactor contract on the host network. + Transactor constant HOST_TRANSACTOR = Transactor(0x3903279B59D3F5194053dA8d1f0C7081C8892Ce4); + /// @notice USDC token for the Pecorino testnet host chain. + IERC20 constant HOST_USDC = IERC20(0x65Fb255585458De1F9A246b476aa8d5C5516F6fd); + /// @notice USDT token for the Pecorino testnet host chain. + IERC20 constant HOST_USDT = IERC20(0xb9Df1b911B6cf6935b2a918Ba03dF2372E94e267); + /// @notice WBTC token for the Pecorino testnet host chain. + IERC20 constant HOST_WBTC = IERC20(0xfb29F7d7a4CE607D6038d44150315e5F69BEa08A); + /// @notice WETH token for the Pecorino testnet host chain. + IERC20 constant HOST_WETH = IERC20(0xd03d085B78067A18155d3B29D64914df3D19A53C); + + /// @notice The token admin address, used for configuring tokens on Passage and for withdrawals. + address constant TOKEN_ADMIN = address(0x11Aa4EBFbf7a481617c719a2Df028c9DA1a219aa); + /// @notice The gas admin address, used for configuring gas limits on Transactor. + address constant GAS_ADMIN = address(0x29403F107781ea45Bf93710abf8df13F67f2008f); + /// @notice The sequencer admin address, used for configuring sequencer settings on Zenith. + address constant SEQUENCER_ADMIN = address(0x29403F107781ea45Bf93710abf8df13F67f2008f); +} + +contract SignetStd { + /// SHARED CONSTANTS + /// @notice The native asset address, used as a sentinel for native USD on + /// the rollup, or native ETH on the host. + address constant NATIVE_ASSET = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + /// @notice Permit2 contract address, which is the same on all chains. + address constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; + + /// ROLLUP CONSTANTS + /// @notice The chain ID of the rollup. + uint32 internal ROLLUP_CHAIN_ID; + /// @notice The Rollup Passage contract. + RollupPassage internal ROLLUP_PASSAGE; + /// @notice The Rollup Orders contract. + RollupOrders internal ROLLUP_ORDERS; + /// @notice The WETH token address. + IERC20 internal ROLLUP_WETH; + /// @notice The WBTC token address. + IERC20 internal ROLLUP_WBTC; + /// @notice The WUSD token address. + IERC20 internal ROLLUP_WUSD; + /// @notice The system address that mints tokens on the rollup. + address internal ROLLUP_MINTER = address(0x00000000000000000000746f6b656E61646d696E); + + /// HOST CONSTANTS + /// @notice The chain ID of the host network. + uint32 internal HOST_CHAIN_ID; + /// @notice The Passage contract on the host network. + Passage internal HOST_PASSAGE; + /// @notice The Orders contract on the host network. + HostOrders internal HOST_ORDERS; + /// @notice The Zenith contract. + Zenith internal HOST_ZENITH; + /// @notice The Transact contract on the host network. + Transactor internal HOST_TRANSACTOR; + /// @notice The USDC token address on the host network. + IERC20 internal HOST_USDC; + /// @notice The USDT token address on the host network. + IERC20 internal HOST_USDT; + /// @notice The WBTC token address on the host network. + IERC20 internal HOST_WBTC; + /// @notice The WETH token address on the host network. + IERC20 internal HOST_WETH; + /// @notice The token admin address, used for configuring tokens on Passage and for withdrawals. + address internal TOKEN_ADMIN; + /// @notice The gas admin address, used for configuring gas limits on Transactor. + address internal GAS_ADMIN; + /// @notice The sequencer admin address, used for configuring sequencer settings on Zenith. + address internal SEQUENCER_ADMIN; + + constructor() { + setupStd(); + } + + function setupStd() internal virtual { + // Auto-configure based on the chain ID. + if (block.chainid == PecorinoConstants.ROLLUP_CHAIN_ID || block.chainid == PecorinoConstants.HOST_CHAIN_ID) { + ROLLUP_CHAIN_ID = PecorinoConstants.ROLLUP_CHAIN_ID; + ROLLUP_PASSAGE = PecorinoConstants.ROLLUP_PASSAGE; + ROLLUP_ORDERS = PecorinoConstants.ROLLUP_ORDERS; + ROLLUP_WETH = PecorinoConstants.ROLLUP_WETH; + ROLLUP_WBTC = PecorinoConstants.ROLLUP_WBTC; + ROLLUP_WUSD = PecorinoConstants.ROLLUP_WUSD; + + HOST_CHAIN_ID = PecorinoConstants.HOST_CHAIN_ID; + HOST_PASSAGE = PecorinoConstants.HOST_PASSAGE; + HOST_ORDERS = PecorinoConstants.HOST_ORDERS; + HOST_ZENITH = PecorinoConstants.HOST_ZENITH; + HOST_TRANSACTOR = PecorinoConstants.HOST_TRANSACTOR; + HOST_USDC = PecorinoConstants.HOST_USDC; + HOST_USDT = PecorinoConstants.HOST_USDT; + HOST_WBTC = PecorinoConstants.HOST_WBTC; + HOST_WETH = PecorinoConstants.HOST_WETH; + TOKEN_ADMIN = PecorinoConstants.TOKEN_ADMIN; + GAS_ADMIN = PecorinoConstants.GAS_ADMIN; + SEQUENCER_ADMIN = PecorinoConstants.SEQUENCER_ADMIN; + } else { + revert("Unsupported chain ID"); + } + } +} diff --git a/test/SignetStdTest.t.sol b/test/SignetStdTest.t.sol new file mode 100644 index 0000000..24e70e5 --- /dev/null +++ b/test/SignetStdTest.t.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {RollupOrders} from "../src/orders/RollupOrders.sol"; +import {RollupPassage} from "../src/passage/RollupPassage.sol"; +import {Zenith} from "../src/Zenith.sol"; +import {Transactor} from "../src/Transactor.sol"; +import {HostOrders} from "../src/orders/HostOrders.sol"; +import {Passage} from "../src/passage/Passage.sol"; +// utils +import {SignetStd} from "./SignetStd.sol"; +import {ERC20} from "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; +import {ERC20Burnable} from "openzeppelin-contracts/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import {Test} from "forge-std/Test.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; + +contract SignetStdTest is SignetStd, Test { + function setupStd() internal virtual override { + // if Foundry chain ID, deploy test contracts + if (block.chainid == 31337) { + ROLLUP_CHAIN_ID = 31337; // Localhost chain ID + ROLLUP_PASSAGE = new RollupPassage(PERMIT2); + ROLLUP_ORDERS = new RollupOrders(PERMIT2); + ROLLUP_WETH = new TestERC20("Wrapped Ether", "WETH", 18); + ROLLUP_WBTC = new TestERC20("Wrapped Bitcoin", "WBTC", 8); + ROLLUP_WUSD = IERC20(0x0000000000000000007369676e65742D77757364); + + HOST_CHAIN_ID = 31337; // Localhost chain ID + HOST_USDC = new TestERC20("USD Coin", "USDC", 6); + HOST_USDT = new TestERC20("Tether USD", "USDT", 6); + HOST_WBTC = new TestERC20("Wrapped Bitcoin", "WBTC", 8); + HOST_WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); + TOKEN_ADMIN = address(this); + GAS_ADMIN = address(this); + SEQUENCER_ADMIN = address(this); + // after setting up tokens and admin addresses, deploy system contracts + HOST_PASSAGE = new Passage(ROLLUP_CHAIN_ID, TOKEN_ADMIN, initialEnterTokens(), PERMIT2); + HOST_ORDERS = new HostOrders(PERMIT2); + HOST_ZENITH = new Zenith(SEQUENCER_ADMIN); + HOST_TRANSACTOR = new Transactor(ROLLUP_CHAIN_ID, GAS_ADMIN, HOST_PASSAGE, 30_000_000, 5_000_000); + + // etch WUSD modified WETH9 code to the Rollup WUSD address + vm.etch( + 0x0000000000000000007369676e65742D77757364, + hex"6060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014757806318160ddd146101a157806323b872dd146101ca5780632e1a7d4d14610243578063313ce5671461026657806370a082311461029557806395d89b41146102e2578063a9059cbb14610370578063d0e30db0146103ca578063dd62ed3e146103d4575b6100b7610440565b005b34156100c457600080fd5b6100cc6104dd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010c5780820151818401526020810190506100f1565b50505050905090810190601f1680156101395780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015257600080fd5b610187600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061057b565b604051808215151515815260200191505060405180910390f35b34156101ac57600080fd5b6101b461066d565b6040518082815260200191505060405180910390f35b34156101d557600080fd5b610229600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061068c565b604051808215151515815260200191505060405180910390f35b341561024e57600080fd5b61026460048080359060200190919050506109d9565b005b341561027157600080fd5b610279610b05565b604051808260ff1660ff16815260200191505060405180910390f35b34156102a057600080fd5b6102cc600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b18565b6040518082815260200191505060405180910390f35b34156102ed57600080fd5b6102f5610b30565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561033557808201518184015260208101905061031a565b50505050905090810190601f1680156103625780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561037b57600080fd5b6103b0600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610bce565b604051808215151515815260200191505060405180910390f35b6103d2610440565b005b34156103df57600080fd5b61042a600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610be3565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105735780601f1061054857610100808354040283529160200191610573565b820191906000526020600020905b81548152906001019060200180831161055657829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156106dc57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141580156107b457507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108cf5781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561084457600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a2757600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501515610ab457600080fd5b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b600260009054906101000a900460ff1681565b60036020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bc65780601f10610b9b57610100808354040283529160200191610bc6565b820191906000526020600020905b815481529060010190602001808311610ba957829003601f168201915b505050505081565b6000610bdb33848461068c565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a72305820deb4c2ccab3c2fdca32ab3f46728389c2fe2c165d5fafa07661e4e004f6c344a0029" + ); + + // etch WETH9 code to the Host WETH address + vm.etch( + 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, + hex"6060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b9578063095ea7b31461014757806318160ddd146101a157806323b872dd146101ca5780632e1a7d4d14610243578063313ce5671461026657806370a082311461029557806395d89b41146102e2578063a9059cbb14610370578063d0e30db0146103ca578063dd62ed3e146103d4575b6100b7610440565b005b34156100c457600080fd5b6100cc6104dd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561010c5780820151818401526020810190506100f1565b50505050905090810190601f1680156101395780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561015257600080fd5b610187600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061057b565b604051808215151515815260200191505060405180910390f35b34156101ac57600080fd5b6101b461066d565b6040518082815260200191505060405180910390f35b34156101d557600080fd5b610229600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061068c565b604051808215151515815260200191505060405180910390f35b341561024e57600080fd5b61026460048080359060200190919050506109d9565b005b341561027157600080fd5b610279610b05565b604051808260ff1660ff16815260200191505060405180910390f35b34156102a057600080fd5b6102cc600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b18565b6040518082815260200191505060405180910390f35b34156102ed57600080fd5b6102f5610b30565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561033557808201518184015260208101905061031a565b50505050905090810190601f1680156103625780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561037b57600080fd5b6103b0600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610bce565b604051808215151515815260200191505060405180910390f35b6103d2610440565b005b34156103df57600080fd5b61042a600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610be3565b6040518082815260200191505060405180910390f35b34600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055503373ffffffffffffffffffffffffffffffffffffffff167fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c346040518082815260200191505060405180910390a2565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105735780601f1061054857610100808354040283529160200191610573565b820191906000526020600020905b81548152906001019060200180831161055657829003601f168201915b505050505081565b600081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60003073ffffffffffffffffffffffffffffffffffffffff1631905090565b600081600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156106dc57600080fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141580156107b457507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414155b156108cf5781600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015151561084457600080fd5b81600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a3600190509392505050565b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a2757600080fd5b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501515610ab457600080fd5b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040518082815260200191505060405180910390a250565b600260009054906101000a900460ff1681565b60036020528060005260406000206000915090505481565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610bc65780601f10610b9b57610100808354040283529160200191610bc6565b820191906000526020600020905b815481529060010190602001808311610ba957829003601f168201915b505050505081565b6000610bdb33848461068c565b905092915050565b60046020528160005260406000206020528060005260406000206000915091505054815600a165627a7a72305820deb4c2ccab3c2fdca32ab3f46728389c2fe2c165d5fafa07661e4e004f6c344a0029" + ); + + // etch Permit2 code to the Permit2 address + vm.etch( + PERMIT2, + hex"6040608081526004908136101561001557600080fd5b600090813560e01c80630d58b1db1461126c578063137c29fe146110755780632a2d80d114610db75780632b67b57014610bde57806330f28b7a14610ade5780633644e51514610a9d57806336c7851614610a285780633ff9dcb1146109a85780634fe02b441461093f57806365d9723c146107ac57806387517c451461067a578063927da105146105c3578063cc53287f146104a3578063edd9444b1461033a5763fe8ec1a7146100c657600080fd5b346103365760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff833581811161033257610114903690860161164b565b60243582811161032e5761012b903690870161161a565b6101336114e6565b9160843585811161032a5761014b9036908a016115c1565b98909560a43590811161032657610164913691016115c1565b969095815190610173826113ff565b606b82527f5065726d697442617463685769746e6573735472616e7366657246726f6d285460208301527f6f6b656e5065726d697373696f6e735b5d207065726d69747465642c61646472838301527f657373207370656e6465722c75696e74323536206e6f6e63652c75696e74323560608301527f3620646561646c696e652c000000000000000000000000000000000000000000608083015282519a8b9181610222602085018096611f93565b918237018a8152039961025b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09b8c8101835282611437565b5190209085515161026b81611ebb565b908a5b8181106102f95750506102f6999a6102ed9183516102a081610294602082018095611f66565b03848101835282611437565b519020602089810151858b015195519182019687526040820192909252336060820152608081019190915260a081019390935260643560c08401528260e081015b03908101835282611437565b51902093611cf7565b80f35b8061031161030b610321938c5161175e565b51612054565b61031b828661175e565b52611f0a565b61026e565b8880fd5b8780fd5b8480fd5b8380fd5b5080fd5b5091346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103365767ffffffffffffffff9080358281116103325761038b903690830161164b565b60243583811161032e576103a2903690840161161a565b9390926103ad6114e6565b9160643590811161049f576103c4913691016115c1565b949093835151976103d489611ebb565b98885b81811061047d5750506102f697988151610425816103f9602082018095611f66565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611437565b5190206020860151828701519083519260208401947ffcf35f5ac6a2c28868dc44c302166470266239195f02b0ee408334829333b7668652840152336060840152608083015260a082015260a081526102ed8161141b565b808b61031b8261049461030b61049a968d5161175e565b9261175e565b6103d7565b8680fd5b5082346105bf57602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103325780359067ffffffffffffffff821161032e576104f49136910161161a565b929091845b848110610504578580f35b8061051a610515600193888861196c565b61197c565b61052f84610529848a8a61196c565b0161197c565b3389528385528589209173ffffffffffffffffffffffffffffffffffffffff80911692838b528652868a20911690818a5285528589207fffffffffffffffffffffffff000000000000000000000000000000000000000081541690558551918252848201527f89b1add15eff56b3dfe299ad94e01f2b52fbcb80ae1a3baea6ae8c04cb2b98a4853392a2016104f9565b8280fd5b50346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610676816105ff6114a0565b936106086114c3565b6106106114e6565b73ffffffffffffffffffffffffffffffffffffffff968716835260016020908152848420928816845291825283832090871683528152919020549251938316845260a083901c65ffffffffffff169084015260d09190911c604083015281906060820190565b0390f35b50346103365760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336576106b26114a0565b906106bb6114c3565b916106c46114e6565b65ffffffffffff926064358481169081810361032a5779ffffffffffff0000000000000000000000000000000000000000947fda9fa7c1b00402c17d0161b249b1ab8bbec047c5a52207b9c112deffd817036b94338a5260016020527fffffffffffff0000000000000000000000000000000000000000000000000000858b209873ffffffffffffffffffffffffffffffffffffffff809416998a8d5260205283878d209b169a8b8d52602052868c209486156000146107a457504216925b8454921697889360a01b16911617179055815193845260208401523392a480f35b905092610783565b5082346105bf5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576107e56114a0565b906107ee6114c3565b9265ffffffffffff604435818116939084810361032a57338852602091600183528489209673ffffffffffffffffffffffffffffffffffffffff80911697888b528452858a20981697888a5283528489205460d01c93848711156109175761ffff9085840316116108f05750907f55eb90d810e1700b35a8e7e25395ff7f2b2259abd7415ca2284dfb1c246418f393929133895260018252838920878a528252838920888a5282528389209079ffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffff000000000000000000000000000000000000000000000000000083549260d01b16911617905582519485528401523392a480f35b84517f24d35a26000000000000000000000000000000000000000000000000000000008152fd5b5084517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b503461033657807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610336578060209273ffffffffffffffffffffffffffffffffffffffff61098f6114a0565b1681528084528181206024358252845220549051908152f35b5082346105bf57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf577f3704902f963766a4e561bbaab6e6cdc1b1dd12f6e9e99648da8843b3f46b918d90359160243533855284602052818520848652602052818520818154179055815193845260208401523392a280f35b8234610a9a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610a9a57610a606114a0565b610a686114c3565b610a706114e6565b6064359173ffffffffffffffffffffffffffffffffffffffff8316830361032e576102f6936117a1565b80fd5b503461033657817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657602090610ad7611b1e565b9051908152f35b508290346105bf576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf57610b1a3661152a565b90807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c36011261033257610b4c611478565b9160e43567ffffffffffffffff8111610bda576102f694610b6f913691016115c1565b939092610b7c8351612054565b6020840151828501519083519260208401947f939c21a48a8dbe3a9a2404a1d46691e4d39f6583d6ec6b35714604c986d801068652840152336060840152608083015260a082015260a08152610bd18161141b565b51902091611c25565b8580fd5b509134610336576101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033657610c186114a0565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc360160c08112610332576080855191610c51836113e3565b1261033257845190610c6282611398565b73ffffffffffffffffffffffffffffffffffffffff91602435838116810361049f578152604435838116810361049f57602082015265ffffffffffff606435818116810361032a5788830152608435908116810361049f576060820152815260a435938285168503610bda576020820194855260c4359087830182815260e43567ffffffffffffffff811161032657610cfe90369084016115c1565b929093804211610d88575050918591610d786102f6999a610d7e95610d238851611fbe565b90898c511690519083519260208401947ff3841cd1ff0085026a6327b620b67997ce40f282c88a8e905a7a5626e310f3d086528401526060830152608082015260808152610d70816113ff565b519020611bd9565b916120c7565b519251169161199d565b602492508a51917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b5091346103365760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc93818536011261033257610df36114a0565b9260249081359267ffffffffffffffff9788851161032a578590853603011261049f578051978589018981108282111761104a578252848301358181116103265785019036602383011215610326578382013591610e50836115ef565b90610e5d85519283611437565b838252602093878584019160071b83010191368311611046578801905b828210610fe9575050508a526044610e93868801611509565b96838c01978852013594838b0191868352604435908111610fe557610ebb90369087016115c1565b959096804211610fba575050508998995151610ed681611ebb565b908b5b818110610f9757505092889492610d7892610f6497958351610f02816103f98682018095611f66565b5190209073ffffffffffffffffffffffffffffffffffffffff9a8b8b51169151928551948501957faf1b0d30d2cab0380e68f0689007e3254993c596f2fdd0aaa7f4d04f794408638752850152830152608082015260808152610d70816113ff565b51169082515192845b848110610f78578580f35b80610f918585610f8b600195875161175e565b5161199d565b01610f6d565b80610311610fac8e9f9e93610fb2945161175e565b51611fbe565b9b9a9b610ed9565b8551917fcd21db4f000000000000000000000000000000000000000000000000000000008352820152fd5b8a80fd5b6080823603126110465785608091885161100281611398565b61100b85611509565b8152611018838601611509565b838201526110278a8601611607565b8a8201528d611037818701611607565b90820152815201910190610e7a565b8c80fd5b84896041867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b5082346105bf576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126105bf576110b03661152a565b91807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7c360112610332576110e2611478565b67ffffffffffffffff93906101043585811161049f5761110590369086016115c1565b90936101243596871161032a57611125610bd1966102f6983691016115c1565b969095825190611134826113ff565b606482527f5065726d69745769746e6573735472616e7366657246726f6d28546f6b656e5060208301527f65726d697373696f6e73207065726d69747465642c6164647265737320737065848301527f6e6465722c75696e74323536206e6f6e63652c75696e7432353620646561646c60608301527f696e652c0000000000000000000000000000000000000000000000000000000060808301528351948591816111e3602085018096611f93565b918237018b8152039361121c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe095868101835282611437565b5190209261122a8651612054565b6020878101518589015195519182019687526040820192909252336060820152608081019190915260a081019390935260e43560c08401528260e081016102e1565b5082346105bf576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261033257813567ffffffffffffffff92838211610bda5736602383011215610bda5781013592831161032e576024906007368386831b8401011161049f57865b8581106112e5578780f35b80821b83019060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc83360301126103265761139288876001946060835161132c81611398565b611368608461133c8d8601611509565b9485845261134c60448201611509565b809785015261135d60648201611509565b809885015201611509565b918291015273ffffffffffffffffffffffffffffffffffffffff80808093169516931691166117a1565b016112da565b6080810190811067ffffffffffffffff8211176113b457604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6060810190811067ffffffffffffffff8211176113b457604052565b60a0810190811067ffffffffffffffff8211176113b457604052565b60c0810190811067ffffffffffffffff8211176113b457604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176113b457604052565b60c4359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b600080fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b6044359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b359073ffffffffffffffffffffffffffffffffffffffff8216820361149b57565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc01906080821261149b576040805190611563826113e3565b8082941261149b57805181810181811067ffffffffffffffff8211176113b457825260043573ffffffffffffffffffffffffffffffffffffffff8116810361149b578152602435602082015282526044356020830152606435910152565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020838186019501011161149b57565b67ffffffffffffffff81116113b45760051b60200190565b359065ffffffffffff8216820361149b57565b9181601f8401121561149b5782359167ffffffffffffffff831161149b576020808501948460061b01011161149b57565b91909160608184031261149b576040805191611666836113e3565b8294813567ffffffffffffffff9081811161149b57830182601f8201121561149b578035611693816115ef565b926116a087519485611437565b818452602094858086019360061b8501019381851161149b579086899897969594939201925b8484106116e3575050505050855280820135908501520135910152565b90919293949596978483031261149b578851908982019082821085831117611730578a928992845261171487611509565b81528287013583820152815201930191908897969594936116c6565b602460007f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b80518210156117725760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b92919273ffffffffffffffffffffffffffffffffffffffff604060008284168152600160205282828220961695868252602052818120338252602052209485549565ffffffffffff8760a01c16804211611884575082871696838803611812575b5050611810955016926118b5565b565b878484161160001461184f57602488604051907ff96fb0710000000000000000000000000000000000000000000000000000000082526004820152fd5b7fffffffffffffffffffffffff000000000000000000000000000000000000000084846118109a031691161790553880611802565b602490604051907fd81b2f2e0000000000000000000000000000000000000000000000000000000082526004820152fd5b9060006064926020958295604051947f23b872dd0000000000000000000000000000000000000000000000000000000086526004860152602485015260448401525af13d15601f3d116001600051141617161561190e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c45440000000000000000000000006044820152fd5b91908110156117725760061b0190565b3573ffffffffffffffffffffffffffffffffffffffff8116810361149b5790565b9065ffffffffffff908160608401511673ffffffffffffffffffffffffffffffffffffffff908185511694826020820151169280866040809401511695169560009187835260016020528383208984526020528383209916988983526020528282209184835460d01c03611af5579185611ace94927fc6a377bfc4eb120024a8ac08eef205be16b817020812c73223e81d1bdb9708ec98979694508715600014611ad35779ffffffffffff00000000000000000000000000000000000000009042165b60a01b167fffffffffffff00000000000000000000000000000000000000000000000000006001860160d01b1617179055519384938491604091949373ffffffffffffffffffffffffffffffffffffffff606085019616845265ffffffffffff809216602085015216910152565b0390a4565b5079ffffffffffff000000000000000000000000000000000000000087611a60565b600484517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b467f000000000000000000000000000000000000000000000000000000000000000103611b69577f866a5aba21966af95d6c7ab78eb2b2fc913915c28be3b9aa07cc04ff903e3f2890565b60405160208101907f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86682527f9ac997416e8ff9d2ff6bebeb7149f65cdae5e32e2b90440b566bb3044041d36a604082015246606082015230608082015260808152611bd3816113ff565b51902090565b611be1611b1e565b906040519060208201927f190100000000000000000000000000000000000000000000000000000000000084526022830152604282015260428152611bd381611398565b9192909360a435936040840151804211611cc65750602084510151808611611c955750918591610d78611c6594611c60602088015186611e47565b611bd9565b73ffffffffffffffffffffffffffffffffffffffff809151511692608435918216820361149b57611810936118b5565b602490604051907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b959093958051519560409283830151804211611e175750848803611dee57611d2e918691610d7860209b611c608d88015186611e47565b60005b868110611d42575050505050505050565b611d4d81835161175e565b5188611d5a83878a61196c565b01359089810151808311611dbe575091818888886001968596611d84575b50505050505001611d31565b611db395611dad9273ffffffffffffffffffffffffffffffffffffffff6105159351169561196c565b916118b5565b803888888883611d78565b6024908651907f3728b83d0000000000000000000000000000000000000000000000000000000082526004820152fd5b600484517fff633a38000000000000000000000000000000000000000000000000000000008152fd5b6024908551907fcd21db4f0000000000000000000000000000000000000000000000000000000082526004820152fd5b9073ffffffffffffffffffffffffffffffffffffffff600160ff83161b9216600052600060205260406000209060081c6000526020526040600020818154188091551615611e9157565b60046040517f756688fe000000000000000000000000000000000000000000000000000000008152fd5b90611ec5826115ef565b611ed26040519182611437565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611f0082946115ef565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114611f375760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b805160208092019160005b828110611f7f575050505090565b835185529381019392810192600101611f71565b9081519160005b838110611fab575050016000815290565b8060208092840101518185015201611f9a565b60405160208101917f65626cad6cb96493bf6f5ebea28756c966f023ab9e8a83a7101849d5573b3678835273ffffffffffffffffffffffffffffffffffffffff8082511660408401526020820151166060830152606065ffffffffffff9182604082015116608085015201511660a082015260a0815260c0810181811067ffffffffffffffff8211176113b45760405251902090565b6040516020808201927f618358ac3db8dc274f0cd8829da7e234bd48cd73c4a740aede1adec9846d06a1845273ffffffffffffffffffffffffffffffffffffffff81511660408401520151606082015260608152611bd381611398565b919082604091031261149b576020823592013590565b6000843b61222e5750604182036121ac576120e4828201826120b1565b939092604010156117725760209360009360ff6040608095013560f81c5b60405194855216868401526040830152606082015282805260015afa156121a05773ffffffffffffffffffffffffffffffffffffffff806000511691821561217657160361214c57565b60046040517f815e1d64000000000000000000000000000000000000000000000000000000008152fd5b60046040517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b6040513d6000823e3d90fd5b60408203612204576121c0918101906120b1565b91601b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84169360ff1c019060ff8211611f375760209360009360ff608094612102565b60046040517f4be6321b000000000000000000000000000000000000000000000000000000008152fd5b929391601f928173ffffffffffffffffffffffffffffffffffffffff60646020957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0604051988997889687947f1626ba7e000000000000000000000000000000000000000000000000000000009e8f8752600487015260406024870152816044870152868601378b85828601015201168101030192165afa9081156123a857829161232a575b507fffffffff000000000000000000000000000000000000000000000000000000009150160361230057565b60046040517fb0669cbc000000000000000000000000000000000000000000000000000000008152fd5b90506020813d82116123a0575b8161234460209383611437565b810103126103365751907fffffffff0000000000000000000000000000000000000000000000000000000082168203610a9a57507fffffffff0000000000000000000000000000000000000000000000000000000090386122d4565b3d9150612337565b6040513d84823e3d90fdfea164736f6c6343000811000a" + ); + } else { + // otherwise, setup environment with constants + super.setupStd(); + } + } + + function initialEnterTokens() internal view returns (address[] memory) { + address[] memory tokens = new address[](4); + tokens[0] = address(HOST_USDC); + tokens[1] = address(HOST_USDT); + tokens[2] = address(HOST_WBTC); + tokens[3] = address(HOST_WETH); + return tokens; + } +} + +contract TestERC20 is ERC20Burnable { + uint8 private _decimals; + + constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) { + _decimals = decimals_; + } + + function decimals() public view virtual override returns (uint8) { + return _decimals; + } + + function mint(address recipient, uint256 amount) external { + _mint(recipient, amount); + } +} diff --git a/test/Transactor.t.sol b/test/Transactor.t.sol index a445b3f..5d6e3aa 100644 --- a/test/Transactor.t.sol +++ b/test/Transactor.t.sol @@ -5,15 +5,14 @@ pragma solidity 0.8.26; 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 TransactTest is Test { - Passage public passage; +contract TransactTest is SignetStdTest { Transactor public target; - uint256 chainId = 3; + address recipient = address(0x123); uint256 amount = 200; - address to = address(0x01); bytes data = abi.encodeWithSelector(Passage.withdraw.selector, address(this), recipient, amount); uint256 value = 100; @@ -35,28 +34,27 @@ contract TransactTest is Test { // Passage event event Enter(uint256 indexed rollupChainId, address indexed rollupRecipient, uint256 amount); - function setUp() public { + function setUp() public virtual { // deploy target - passage = new Passage(block.chainid + 1, address(this), new address[](0), address(0)); - target = new Transactor(block.chainid + 1, address(this), passage, gas * 6, gas); + target = HOST_TRANSACTOR; } function test_setUp() public { - assertEq(target.defaultRollupChainId(), block.chainid + 1); - assertEq(target.gasAdmin(), address(this)); - assertEq(address(target.passage()), address(passage)); + assertEq(target.defaultRollupChainId(), ROLLUP_CHAIN_ID); + assertEq(target.gasAdmin(), GAS_ADMIN); + assertEq(address(target.passage()), address(HOST_PASSAGE)); assertEq(target.perBlockGasLimit(), gas * 6); assertEq(target.perTransactGasLimit(), gas); } function test_transact() public { vm.expectEmit(address(target)); - emit Transact(chainId, address(this), to, data, value, gas, maxFeePerGas); - target.transact(chainId, to, data, value, gas, maxFeePerGas); + emit Transact(ROLLUP_CHAIN_ID, address(this), to, data, value, gas, maxFeePerGas); + target.transact(ROLLUP_CHAIN_ID, to, data, value, gas, maxFeePerGas); - vm.expectEmit(address(passage)); - emit Enter(chainId, address(this), amount); - target.transact{value: amount}(chainId, to, data, value, gas, maxFeePerGas); + vm.expectEmit(address(HOST_PASSAGE)); + emit Enter(ROLLUP_CHAIN_ID, address(this), amount); + target.transact{value: amount}(ROLLUP_CHAIN_ID, to, data, value, gas, maxFeePerGas); } function test_transact_defaultChain() public { @@ -64,25 +62,25 @@ contract TransactTest is Test { emit Transact(target.defaultRollupChainId(), address(this), to, data, value, gas, maxFeePerGas); target.transact(to, data, value, gas, maxFeePerGas); - vm.expectEmit(address(passage)); + vm.expectEmit(address(HOST_PASSAGE)); emit Enter(target.defaultRollupChainId(), address(this), amount); target.transact{value: amount}(to, data, value, gas, maxFeePerGas); } function test_enterTransact() public { vm.expectEmit(address(target)); - emit Transact(chainId, address(this), to, data, value, gas, maxFeePerGas); - target.enterTransact(chainId, recipient, to, data, value, gas, maxFeePerGas); + emit Transact(ROLLUP_CHAIN_ID, address(this), to, data, value, gas, maxFeePerGas); + target.enterTransact{value: amount}(ROLLUP_CHAIN_ID, recipient, to, data, value, gas, maxFeePerGas); - vm.expectEmit(address(passage)); - emit Enter(chainId, recipient, amount); - target.enterTransact{value: amount}(chainId, recipient, to, data, value, gas, maxFeePerGas); + vm.expectEmit(address(HOST_PASSAGE)); + emit Enter(ROLLUP_CHAIN_ID, recipient, amount); + target.enterTransact{value: amount}(ROLLUP_CHAIN_ID, recipient, to, data, value, gas, maxFeePerGas); } function test_transact_perTransactGasLimit() public { // attempt transact with 5M + 1 gas. vm.expectRevert(Transactor.PerTransactGasLimit.selector); - target.transact(chainId, to, data, value, gas + 1, maxFeePerGas); + target.transact(ROLLUP_CHAIN_ID, to, data, value, gas + 1, maxFeePerGas); } function test_transact_globalGasLimit() public { @@ -107,9 +105,11 @@ contract TransactTest is Test { uint256 newPerTransact = 2_000_000; // 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); diff --git a/test/Zenith.t.sol b/test/Zenith.t.sol index 98d9d2a..50392a0 100644 --- a/test/Zenith.t.sol +++ b/test/Zenith.t.sol @@ -4,9 +4,10 @@ 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 ZenithTest is Test { +contract ZenithTest is SignetStdTest { Zenith public target; Zenith.BlockHeader header; @@ -27,12 +28,15 @@ contract ZenithTest is Test { event SequencerSet(address indexed sequencer, bool indexed permissioned); - function setUp() public { - target = new Zenith(address(this)); + function setUp() public virtual { + target = HOST_ZENITH; + + // configure a local signer as a sequencer + vm.prank(SEQUENCER_ADMIN); target.addSequencer(vm.addr(sequencerKey)); // set default block values - header.rollupChainId = block.chainid + 1; + header.rollupChainId = ROLLUP_CHAIN_ID; header.hostBlockNumber = block.number; header.gasLimit = 30_000_000; header.rewardAddress = address(this); @@ -43,8 +47,7 @@ contract ZenithTest is Test { } function test_setUp() public { - assertEq(target.sequencerAdmin(), address(this)); - assertEq(target.deployBlockNumber(), block.number); + assertEq(target.sequencerAdmin(), SEQUENCER_ADMIN); } // cannot submit block with incorrect host block number @@ -65,7 +68,7 @@ contract ZenithTest is Test { // sign block commitment with correct sequencer key (uint8 v, bytes32 r, bytes32 s) = vm.sign(sequencerKey, commit); - assertEq(target.lastSubmittedAtBlock(header.rollupChainId), 0); + assertNotEq(target.lastSubmittedAtBlock(header.rollupChainId), block.number); // should emit BlockSubmitted event vm.expectEmit(); @@ -122,9 +125,11 @@ contract ZenithTest is Test { 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)); @@ -141,9 +146,11 @@ contract ZenithTest is Test { address sequencer = vm.addr(sequencerKey); assertTrue(target.isSequencer(sequencer)); + vm.startPrank(SEQUENCER_ADMIN); vm.expectEmit(); emit SequencerSet(sequencer, false); target.removeSequencer(sequencer); + vm.stopPrank(); assertFalse(target.isSequencer(sequencer));