diff --git a/contracts/test/ArbitrumProver.t.sol b/contracts/test/ArbitrumProver.t.sol index 8ac55c2..ef58e08 100644 --- a/contracts/test/ArbitrumProver.t.sol +++ b/contracts/test/ArbitrumProver.t.sol @@ -1,50 +1,31 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {Test} from "forge-std/Test.sol"; -import {ERC20Mock} from "openzeppelin-contracts/contracts/mocks/token/ERC20Mock.sol"; import {stdJson} from "forge-std/StdJson.sol"; import {CAIP10} from "../src/libraries/CAIP10.sol"; import {GlobalTypes} from "../src/libraries/GlobalTypes.sol"; import {ArbitrumProver} from "../src/libraries/provers/ArbitrumProver.sol"; import {StateValidator} from "../src/libraries/StateValidator.sol"; -import {ERC7786Base} from "../src/ERC7786Base.sol"; -import {Call} from "../src/RIP7755Structs.sol"; import {RIP7755OutboxToArbitrum} from "../src/outboxes/RIP7755OutboxToArbitrum.sol"; import {MockArbitrumProver} from "./mocks/MockArbitrumProver.sol"; -import {MockBeaconOracle} from "./mocks/MockBeaconOracle.sol"; +import {BaseTest} from "./BaseTest.t.sol"; -contract ArbitrumProverTest is Test, ERC7786Base { +contract ArbitrumProverTest is BaseTest { using stdJson for string; using GlobalTypes for address; using CAIP10 for address; MockArbitrumProver prover; - ERC20Mock mockErc20; - MockBeaconOracle mockBeaconOracle; - - Call[] calls; - address ALICE = makeAddr("alice"); - address FILLER = makeAddr("filler"); - string validProof; - string invalidL1State; - string invalidBlockHeaders; - string invalidL2Storage; - uint256 private _REWARD_AMOUNT = 1 ether; - bytes32 private constant _VERIFIER_STORAGE_LOCATION = - 0x43f1016e17bdb0194ec37b77cf476d255de00011d02616ab831d2e2ce63d9ee2; address private constant _INBOX_CONTRACT = 0x49E2cDC9e81825B6C718ae8244fe0D5b062F4874; function setUp() external { prover = new MockArbitrumProver(); - mockErc20 = new ERC20Mock(); - deployCodeTo("MockBeaconOracle.sol", abi.encode(), 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02); - mockBeaconOracle = MockBeaconOracle(0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02); + approveAddr = address(prover); + _setUp(); - string memory rootPath = vm.projectRoot(); string memory path = string.concat(rootPath, "/test/data/ArbitrumSepoliaProof.json"); string memory invalidPath = string.concat(rootPath, "/test/data/invalids/ArbitrumInvalidL1State.json"); string memory invalidBlockHeadersPath = @@ -58,14 +39,6 @@ contract ArbitrumProverTest is Test, ERC7786Base { invalidL2Storage = vm.readFile(invalidL2StoragePath); } - modifier fundAlice(uint256 amount) { - mockErc20.mint(ALICE, amount); - vm.deal(ALICE, amount); - vm.prank(ALICE); - mockErc20.approve(address(prover), amount); - _; - } - function test_reverts_ifFinalityDelaySecondsStillInProgress() external fundAlice(_REWARD_AMOUNT) { (string memory sender, string memory receiver, bytes memory payload, bytes[] memory attributes) = _initMessage(_REWARD_AMOUNT); @@ -200,8 +173,4 @@ contract ArbitrumProverTest is Test, ERC7786Base { return (sender, receiver, payload, attributes); } - - function _deriveStorageKey(bytes32 messageId) private pure returns (bytes memory) { - return abi.encode(keccak256(abi.encodePacked(messageId, _VERIFIER_STORAGE_LOCATION))); - } } diff --git a/contracts/test/BaseTest.t.sol b/contracts/test/BaseTest.t.sol new file mode 100644 index 0000000..8c171da --- /dev/null +++ b/contracts/test/BaseTest.t.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; +import {ERC20Mock} from "openzeppelin-contracts/contracts/mocks/token/ERC20Mock.sol"; + +import {ERC7786Base} from "../src/ERC7786Base.sol"; +import {Call} from "../src/RIP7755Structs.sol"; + +import {MockBeaconOracle} from "./mocks/MockBeaconOracle.sol"; + +contract BaseTest is Test, ERC7786Base { + ERC20Mock mockErc20; + MockBeaconOracle mockBeaconOracle; + + address approveAddr; + + Call[] calls; + address ALICE = makeAddr("alice"); + address FILLER = makeAddr("filler"); + string rootPath; + string validProof; + string invalidL1State; + string invalidBlockHeaders; + string invalidL2StateRootProof; + string invalidL2Storage; + + uint256 constant _REWARD_AMOUNT = 1 ether; + bytes32 constant _VERIFIER_STORAGE_LOCATION = 0x43f1016e17bdb0194ec37b77cf476d255de00011d02616ab831d2e2ce63d9ee2; + + function _setUp() internal { + mockErc20 = new ERC20Mock(); + + deployCodeTo("MockBeaconOracle.sol", abi.encode(), 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02); + mockBeaconOracle = MockBeaconOracle(0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02); + + rootPath = vm.projectRoot(); + } + + modifier fundAlice(uint256 amount) { + mockErc20.mint(ALICE, amount); + vm.deal(ALICE, amount); + vm.prank(ALICE); + mockErc20.approve(approveAddr, amount); + _; + } + + function _deriveStorageKey(bytes32 messageId) internal pure returns (bytes memory) { + return abi.encode(keccak256(abi.encodePacked(messageId, _VERIFIER_STORAGE_LOCATION))); + } +} diff --git a/contracts/test/HashiProver.t.sol b/contracts/test/HashiProver.t.sol index 207d67f..dade565 100644 --- a/contracts/test/HashiProver.t.sol +++ b/contracts/test/HashiProver.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {Test} from "forge-std/Test.sol"; -import {ERC20Mock} from "openzeppelin-contracts/contracts/mocks/token/ERC20Mock.sol"; import {stdJson} from "forge-std/StdJson.sol"; import {HashiProver} from "../src/libraries/provers/HashiProver.sol"; @@ -11,13 +9,12 @@ import {CAIP10} from "../src/libraries/CAIP10.sol"; import {GlobalTypes} from "../src/libraries/GlobalTypes.sol"; import {StateValidator} from "../src/libraries/StateValidator.sol"; import {RIP7755OutboxToHashi} from "../src/outboxes/RIP7755OutboxToHashi.sol"; -import {ERC7786Base} from "../src/ERC7786Base.sol"; -import {Call} from "../src/RIP7755Structs.sol"; import {MockShoyuBashi} from "./mocks/MockShoyuBashi.sol"; import {MockHashiProver} from "./mocks/MockHashiProver.sol"; +import {BaseTest} from "./BaseTest.t.sol"; -contract HashiProverTest is Test, ERC7786Base { +contract HashiProverTest is BaseTest { using stdJson for string; using GlobalTypes for address; using BlockHeaders for bytes; @@ -27,35 +24,18 @@ contract HashiProverTest is Test, ERC7786Base { address private constant _INBOX_CONTRACT = 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512; MockHashiProver prover; - ERC20Mock mockErc20; MockShoyuBashi shoyuBashi; - Call[] calls; - address ALICE = makeAddr("alice"); - address FILLER = makeAddr("filler"); - string validProof; - uint256 private constant _REWARD_AMOUNT = 1 ether; - bytes32 private constant _VERIFIER_STORAGE_LOCATION = - 0x43f1016e17bdb0194ec37b77cf476d255de00011d02616ab831d2e2ce63d9ee2; - function setUp() external { shoyuBashi = new MockShoyuBashi(); prover = new MockHashiProver(); - mockErc20 = new ERC20Mock(); + approveAddr = address(prover); + _setUp(); - string memory rootPath = vm.projectRoot(); string memory path = string.concat(rootPath, "/test/data/HashiProverProof.json"); validProof = vm.readFile(path); } - modifier fundAlice(uint256 amount) { - mockErc20.mint(ALICE, amount); - vm.deal(ALICE, amount); - vm.prank(ALICE); - mockErc20.approve(address(prover), amount); - _; - } - function test_reverts_ifFinalityDelaySecondsStillInProgress() external fundAlice(_REWARD_AMOUNT) { (string memory sender, string memory receiver, bytes memory payload, bytes[] memory attributes) = _initMessage(_REWARD_AMOUNT); @@ -154,8 +134,4 @@ contract HashiProverTest is Test, ERC7786Base { return (sender, receiver, payload, attributes); } - - function _deriveStorageKey(bytes32 messageId) private pure returns (bytes memory) { - return abi.encode(keccak256(abi.encodePacked(messageId, _VERIFIER_STORAGE_LOCATION))); - } } diff --git a/contracts/test/OPStackProver.t.sol b/contracts/test/OPStackProver.t.sol index 738a37b..e03e469 100644 --- a/contracts/test/OPStackProver.t.sol +++ b/contracts/test/OPStackProver.t.sol @@ -1,66 +1,39 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {Test} from "forge-std/Test.sol"; -import {ERC20Mock} from "openzeppelin-contracts/contracts/mocks/token/ERC20Mock.sol"; import {stdJson} from "forge-std/StdJson.sol"; import {OPStackProver} from "../src/libraries/provers/OPStackProver.sol"; import {CAIP10} from "../src/libraries/CAIP10.sol"; import {GlobalTypes} from "../src/libraries/GlobalTypes.sol"; import {StateValidator} from "../src/libraries/StateValidator.sol"; -import {ERC7786Base} from "../src/ERC7786Base.sol"; -import {Call} from "../src/RIP7755Structs.sol"; import {RIP7755OutboxToOPStack} from "../src/outboxes/RIP7755OutboxToOPStack.sol"; -import {MockBeaconOracle} from "./mocks/MockBeaconOracle.sol"; import {MockOPStackProver} from "./mocks/MockOPStackProver.sol"; +import {BaseTest} from "./BaseTest.t.sol"; -contract RIP7755OutboxOPStackValidatorTest is Test, ERC7786Base { +contract OPStackProverTest is BaseTest { using stdJson for string; using GlobalTypes for address; using CAIP10 for address; MockOPStackProver prover; - ERC20Mock mockErc20; - MockBeaconOracle mockBeaconOracle; - - Call[] calls; - address ALICE = makeAddr("alice"); - address FILLER = makeAddr("filler"); - string validProof; - string invalidL1StorageProof; - string invalidL2StateRootProof; - string invalidL2StorageProof; - uint256 private _REWARD_AMOUNT = 1 ether; - bytes32 private constant _VERIFIER_STORAGE_LOCATION = - 0x43f1016e17bdb0194ec37b77cf476d255de00011d02616ab831d2e2ce63d9ee2; address private constant _INBOX_CONTRACT = 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512; function setUp() external { prover = new MockOPStackProver(); - mockErc20 = new ERC20Mock(); - deployCodeTo("MockBeaconOracle.sol", abi.encode(), 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02); - mockBeaconOracle = MockBeaconOracle(0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02); + approveAddr = address(prover); + _setUp(); - string memory rootPath = vm.projectRoot(); string memory path = string.concat(rootPath, "/test/data/OPSepoliaProof.json"); string memory invalidL1StoragePath = string.concat(rootPath, "/test/data/invalids/OPInvalidL1Storage.json"); string memory invalidL2StateRootPath = string.concat(rootPath, "/test/data/invalids/OPInvalidL2StateRoot.json"); string memory invalidL2StoragePath = string.concat(rootPath, "/test/data/invalids/OPInvalidL2Storage.json"); validProof = vm.readFile(path); - invalidL1StorageProof = vm.readFile(invalidL1StoragePath); + invalidL1State = vm.readFile(invalidL1StoragePath); invalidL2StateRootProof = vm.readFile(invalidL2StateRootPath); - invalidL2StorageProof = vm.readFile(invalidL2StoragePath); - } - - modifier fundAlice(uint256 amount) { - mockErc20.mint(ALICE, amount); - vm.deal(ALICE, amount); - vm.prank(ALICE); - mockErc20.approve(address(prover), amount); - _; + invalidL2Storage = vm.readFile(invalidL2StoragePath); } function test_validate_reverts_ifFinalityDelaySecondsInProgress() external fundAlice(_REWARD_AMOUNT) { @@ -127,7 +100,7 @@ contract RIP7755OutboxOPStackValidatorTest is Test, ERC7786Base { _initMessage(_REWARD_AMOUNT); bytes32 messageId = keccak256(abi.encode(sender, receiver, payload, attributes)); - bytes memory storageProofData = _buildProofAndEncodeProof(invalidL1StorageProof); + bytes memory storageProofData = _buildProofAndEncodeProof(invalidL1State); bytes memory inboxStorageKey = _deriveStorageKey(messageId); vm.prank(FILLER); @@ -153,7 +126,7 @@ contract RIP7755OutboxOPStackValidatorTest is Test, ERC7786Base { _initMessage(_REWARD_AMOUNT); bytes32 messageId = keccak256(abi.encode(sender, receiver, payload, attributes)); - bytes memory storageProofData = _buildProofAndEncodeProof(invalidL2StorageProof); + bytes memory storageProofData = _buildProofAndEncodeProof(invalidL2Storage); bytes memory inboxStorageKey = _deriveStorageKey(messageId); vm.prank(FILLER); @@ -233,8 +206,4 @@ contract RIP7755OutboxOPStackValidatorTest is Test, ERC7786Base { return (sender, receiver, payload, attributes); } - - function _deriveStorageKey(bytes32 messageId) private pure returns (bytes memory) { - return abi.encode(keccak256(abi.encodePacked(messageId, _VERIFIER_STORAGE_LOCATION))); - } } diff --git a/contracts/test/RIP7755Inbox.t.sol b/contracts/test/RIP7755Inbox.t.sol index 931736b..bdad171 100644 --- a/contracts/test/RIP7755Inbox.t.sol +++ b/contracts/test/RIP7755Inbox.t.sol @@ -1,20 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {Test} from "forge-std/Test.sol"; - import {DeployRIP7755Inbox} from "../script/DeployRIP7755Inbox.s.sol"; import {CAIP10} from "../src/libraries/CAIP10.sol"; import {GlobalTypes} from "../src/libraries/GlobalTypes.sol"; import {StringsHelper} from "../src/libraries/StringsHelper.sol"; -import {ERC7786Base} from "../src/ERC7786Base.sol"; import {RIP7755Inbox} from "../src/RIP7755Inbox.sol"; import {Call} from "../src/RIP7755Structs.sol"; import {MockPrecheck} from "./mocks/MockPrecheck.sol"; import {MockTarget} from "./mocks/MockTarget.sol"; +import {BaseTest} from "./BaseTest.t.sol"; -contract RIP7755InboxTest is Test, ERC7786Base { +contract RIP7755InboxTest is BaseTest { using GlobalTypes for address; using CAIP10 for address; using StringsHelper for address; @@ -31,10 +29,6 @@ contract RIP7755InboxTest is Test, ERC7786Base { MockPrecheck precheck; MockTarget target; - Call[] calls; - address ALICE = makeAddr("alice"); - address FULFILLER = makeAddr("fulfiller"); - event CallFulfilled(bytes32 indexed requestHash, address indexed fulfilledBy); function setUp() public { @@ -47,12 +41,12 @@ contract RIP7755InboxTest is Test, ERC7786Base { function test_executeMessage_storesFulfillment_withSuccessfulPrecheck() external { Message memory m = _initMessage(true); - vm.prank(FULFILLER); + vm.prank(FILLER); inbox.executeMessage(m.sourceChain, m.sender, m.payload, m.attributes); RIP7755Inbox.FulfillmentInfo memory info = inbox.getFulfillmentInfo(m.messageId); - assertEq(info.fulfiller, FULFILLER); + assertEq(info.fulfiller, FILLER); assertEq(info.timestamp, block.timestamp); } @@ -66,10 +60,10 @@ contract RIP7755InboxTest is Test, ERC7786Base { function test_executeMessage_reverts_callAlreadyFulfilled() external { Message memory m = _initMessage(false); - vm.prank(FULFILLER); + vm.prank(FILLER); inbox.executeMessage(m.sourceChain, m.sender, m.payload, m.attributes); - vm.prank(FULFILLER); + vm.prank(FILLER); vm.expectRevert(RIP7755Inbox.CallAlreadyFulfilled.selector); inbox.executeMessage(m.sourceChain, m.sender, m.payload, m.attributes); } @@ -86,7 +80,7 @@ contract RIP7755InboxTest is Test, ERC7786Base { ); m.payload = abi.encode(calls); - vm.prank(FULFILLER); + vm.prank(FILLER); inbox.executeMessage(m.sourceChain, m.sender, m.payload, m.attributes); assertEq(target.number(), inputNum); @@ -98,8 +92,8 @@ contract RIP7755InboxTest is Test, ERC7786Base { calls.push(Call({to: ALICE.addressToBytes32(), data: "", value: amount})); m.payload = abi.encode(calls); - vm.deal(FULFILLER, amount); - vm.prank(FULFILLER); + vm.deal(FILLER, amount); + vm.prank(FILLER); inbox.executeMessage{value: amount}(m.sourceChain, m.sender, m.payload, m.attributes); assertEq(ALICE.balance, amount); @@ -117,7 +111,7 @@ contract RIP7755InboxTest is Test, ERC7786Base { ); m.payload = abi.encode(calls); - vm.prank(FULFILLER); + vm.prank(FILLER); vm.expectRevert(MockTarget.MockError.selector); inbox.executeMessage(m.sourceChain, m.sender, m.payload, m.attributes); } @@ -125,20 +119,20 @@ contract RIP7755InboxTest is Test, ERC7786Base { function test_executeMessage_storesFulfillment() external { Message memory m = _initMessage(false); - vm.prank(FULFILLER); + vm.prank(FILLER); inbox.executeMessage(m.sourceChain, m.sender, m.payload, m.attributes); RIP7755Inbox.FulfillmentInfo memory info = inbox.getFulfillmentInfo(m.messageId); - assertEq(info.fulfiller, FULFILLER); + assertEq(info.fulfiller, FILLER); assertEq(info.timestamp, block.timestamp); } function test_executeMessage_reverts_ifMsgValueTooHigh() external { Message memory m = _initMessage(false); - vm.deal(FULFILLER, 1); - vm.prank(FULFILLER); + vm.deal(FILLER, 1); + vm.prank(FILLER); vm.expectRevert(abi.encodeWithSelector(RIP7755Inbox.InvalidValue.selector, 0, 1)); inbox.executeMessage{value: 1}(m.sourceChain, m.sender, m.payload, m.attributes); } @@ -146,9 +140,9 @@ contract RIP7755InboxTest is Test, ERC7786Base { function test_executeMessage_emitsEvent() external { Message memory m = _initMessage(false); - vm.prank(FULFILLER); + vm.prank(FILLER); vm.expectEmit(true, true, false, false); - emit CallFulfilled({requestHash: m.messageId, fulfilledBy: FULFILLER}); + emit CallFulfilled({requestHash: m.messageId, fulfilledBy: FILLER}); inbox.executeMessage(m.sourceChain, m.sender, m.payload, m.attributes); } @@ -162,7 +156,7 @@ contract RIP7755InboxTest is Test, ERC7786Base { attributes[1] = abi.encodeWithSelector(_DELAY_ATTRIBUTE_SELECTOR, 10, block.timestamp + 11); attributes[2] = abi.encodeWithSelector(_NONCE_ATTRIBUTE_SELECTOR, 1); attributes[3] = abi.encodeWithSelector(_REQUESTER_ATTRIBUTE_SELECTOR, ALICE.addressToBytes32()); - attributes[4] = abi.encodeWithSelector(_FULFILLER_ATTRIBUTE_SELECTOR, FULFILLER); + attributes[4] = abi.encodeWithSelector(_FULFILLER_ATTRIBUTE_SELECTOR, FILLER); if (isPrecheck) { attributes[5] = abi.encodeWithSelector(_PRECHECK_ATTRIBUTE_SELECTOR, address(precheck)); diff --git a/contracts/test/RIP7755Outbox.t.sol b/contracts/test/RIP7755Outbox.t.sol index fcbd52c..9a0b8aa 100644 --- a/contracts/test/RIP7755Outbox.t.sol +++ b/contracts/test/RIP7755Outbox.t.sol @@ -1,19 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import {Test} from "forge-std/Test.sol"; -import {ERC20Mock} from "openzeppelin-contracts/contracts/mocks/token/ERC20Mock.sol"; - import {CAIP10} from "../src/libraries/CAIP10.sol"; import {GlobalTypes} from "../src/libraries/GlobalTypes.sol"; import {StringsHelper} from "../src/libraries/StringsHelper.sol"; -import {ERC7786Base} from "../src/ERC7786Base.sol"; -import {Call} from "../src/RIP7755Structs.sol"; import {RIP7755Outbox} from "../src/RIP7755Outbox.sol"; import {MockOutbox} from "./mocks/MockOutbox.sol"; +import {BaseTest} from "./BaseTest.t.sol"; -contract RIP7755OutboxTest is Test, ERC7786Base { +contract RIP7755OutboxTest is BaseTest { using GlobalTypes for address; using CAIP10 for address; using StringsHelper for address; @@ -30,11 +26,6 @@ contract RIP7755OutboxTest is Test, ERC7786Base { } MockOutbox outbox; - ERC20Mock mockErc20; - - Call[] calls; - address ALICE = makeAddr("alice"); - address FILLER = makeAddr("filler"); bytes32 private constant _NATIVE_ASSET = 0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee; @@ -45,16 +36,9 @@ contract RIP7755OutboxTest is Test, ERC7786Base { event CrossChainCallCanceled(bytes32 indexed callHash); function setUp() public { + _setUp(); outbox = new MockOutbox(); - mockErc20 = new ERC20Mock(); - } - - modifier fundAlice(uint256 amount) { - mockErc20.mint(ALICE, amount); - vm.deal(ALICE, amount); - vm.prank(ALICE); - mockErc20.approve(address(outbox), amount); - _; + approveAddr = address(outbox); } function test_sendMessage_incrementsNonce(uint256 rewardAmount) external fundAlice(rewardAmount) {