Skip to content

Commit

Permalink
Merge pull request #29 from base-org/jack/multi-chain
Browse files Browse the repository at this point in the history
update opstack tests based on local multi-chain
  • Loading branch information
jackchuma authored Nov 24, 2024
2 parents 3679c0b + 81b4f5a commit 97c42f6
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 203 deletions.
2 changes: 2 additions & 0 deletions contracts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ out/
# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/*/111111/
/broadcast/*/111112/
/broadcast/**/dry-run/

# Docs
Expand Down
40 changes: 29 additions & 11 deletions contracts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ OPTIMISM_REQUEST_HASH = 0xe38ad8c9e84178325f28799eb3aaae72551b2eea7920c43d88854e
FULFILLER_ADDRESS = 0x23214A0864FC0014CAb6030267738F01AFfdd547
MOCK_VERIFIER_ADDRESS = 0x49E2cDC9e81825B6C718ae8244fe0D5b062F4874

# Default Anvil Keys
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
CHAIN_A_KEY=0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a
CHAIN_B_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d

CHAIN_A_URL=http://localhost:8546
CHAIN_B_URL=http://localhost:8547

ARBITRUM_RPC = $(ARBITRUM_SEPOLIA_RPC)
OPTIMISM_RPC = $(CHAIN_B_URL)
BASE_RPC = $(CHAIN_A_URL)

test:
forge fmt
forge test
Expand All @@ -16,34 +28,40 @@ coverage:
forge coverage

deploy-mock:
forge create --rpc-url $(ARBITRUM_SEPOLIA_RPC) --private-key $(PRIVATE_KEY) test/mocks/MockVerifier.sol:MockVerifier
forge create --rpc-url $(ARBITRUM_RPC) --private-key $(PRIVATE_KEY) test/mocks/MockVerifier.sol:MockVerifier

deploy-mock-opt-sep:
forge create --rpc-url $(OPTIMISM_SEPOLIA_RPC) --private-key $(PRIVATE_KEY) test/mocks/MockVerifier.sol:MockVerifier
forge create --rpc-url $(OPTIMISM_RPC) --private-key $(PRIVATE_KEY) test/mocks/MockVerifier.sol:MockVerifier

read-mock:
cast call $(MOCK_VERIFIER_ADDRESS) "getFulfillmentInfo(bytes32)(uint96,address)" $(ARBITRUM_REQUEST_HASH) --rpc-url $(ARBITRUM_SEPOLIA_RPC)
cast call $(MOCK_VERIFIER_ADDRESS) "getFulfillmentInfo(bytes32)(uint96,address)" $(ARBITRUM_REQUEST_HASH) --rpc-url $(ARBITRUM_RPC)

set-mock:
cast send $(MOCK_VERIFIER_ADDRESS) "storeFulfillmentInfo(bytes32,address)" $(ARBITRUM_REQUEST_HASH) $(FULFILLER_ADDRESS) --rpc-url $(ARBITRUM_SEPOLIA_RPC) --private-key $(PRIVATE_KEY)
cast send $(MOCK_VERIFIER_ADDRESS) "storeFulfillmentInfo(bytes32,address)" $(ARBITRUM_REQUEST_HASH) $(FULFILLER_ADDRESS) --rpc-url $(ARBITRUM_RPC) --private-key $(PRIVATE_KEY)

read-mock-op:
cast call $(MOCK_VERIFIER_ADDRESS) "getFulfillmentInfo(bytes32)(uint96,address)" $(OPTIMISM_REQUEST_HASH) --rpc-url $(OPTIMISM_SEPOLIA_RPC)
cast call $(MOCK_VERIFIER_ADDRESS) "getFulfillmentInfo(bytes32)(uint96,address)" $(OPTIMISM_REQUEST_HASH) --rpc-url $(OPTIMISM_RPC)

set-mock-op:
cast send $(MOCK_VERIFIER_ADDRESS) "storeFulfillmentInfo(bytes32,address)" $(OPTIMISM_REQUEST_HASH) $(FULFILLER_ADDRESS) --rpc-url $(OPTIMISM_SEPOLIA_RPC) --private-key $(PRIVATE_KEY)
cast send $(MOCK_VERIFIER_ADDRESS) "storeFulfillmentInfo(bytes32,address)" $(OPTIMISM_REQUEST_HASH) $(FULFILLER_ADDRESS) --rpc-url $(OPTIMISM_RPC) --private-key $(PRIVATE_KEY)

deploy-arbitrum-sepolia:
forge script script/chains/DeployArbitrum.s.sol:DeployArbitrum --rpc-url $(ARBITRUM_SEPOLIA_RPC) --broadcast --verify --etherscan-api-key $(ARBISCAN_API_KEY) -vvvv
forge script script/chains/DeployArbitrum.s.sol:DeployArbitrum --rpc-url $(ARBITRUM_RPC) --broadcast -vvvv

deploy-optimism-sepolia:
forge script script/chains/DeployBase.s.sol:DeployBase --rpc-url $(OPTIMISM_RPC) --broadcast -vvvv

deploy-base-sepolia:
forge script script/chains/DeployBase.s.sol:DeployBase --rpc-url $(BASE_SEPOLIA_RPC) --broadcast --verify --etherscan-api-key $(BASESCAN_API_KEY) -vvvv
forge script script/chains/DeployBase.s.sol:DeployBase --rpc-url $(BASE_RPC) --private-key $(PRIVATE_KEY) --broadcast -vvvv

verify-arb-sepolia:
forge verify-contract 0xeE962eD1671F655a806cB22623eEA8A7cCc233bC src/RIP7755Inbox.sol:RIP7755Inbox --rpc-url $(ARBITRUM_SEPOLIA_RPC) --etherscan-api-key $(ARBISCAN_API_KEY)
forge verify-contract 0xeE962eD1671F655a806cB22623eEA8A7cCc233bC src/RIP7755Inbox.sol:RIP7755Inbox --rpc-url $(ARBITRUM_RPC) --etherscan-api-key $(ARBISCAN_API_KEY)

verify-base-sepolia:
forge verify-contract 0xB482b292878FDe64691d028A2237B34e91c7c7ea src/RIP7755Inbox.sol:RIP7755Inbox --rpc-url $(BASE_SEPOLIA_RPC) --etherscan-api-key $(BASESCAN_API_KEY)
forge verify-contract 0xB482b292878FDe64691d028A2237B34e91c7c7ea src/RIP7755Inbox.sol:RIP7755Inbox --rpc-url $(BASE_RPC) --etherscan-api-key $(BASESCAN_API_KEY)

submit-request:
forge script script/actions/SubmitRequest.s.sol:SubmitRequest --rpc-url $(ARBITRUM_SEPOLIA_RPC) --broadcast -vvvv
forge script script/actions/SubmitRequest.s.sol:SubmitRequest --rpc-url $(OPTIMISM_RPC) --broadcast -vvvv

fulfill-request:
forge script script/actions/SubmitToInbox.s.sol:SubmitToInbox --rpc-url $(OPTIMISM_RPC) --broadcast -vvvv
34 changes: 18 additions & 16 deletions contracts/script/actions/SubmitRequest.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,28 @@ contract SubmitRequest is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
RIP7755Outbox outbox = RIP7755Outbox(0xBCd5762cF9B07EF5597014c350CE2efB2b0DB2D2);
Call[] memory calls = new Call[](1);
calls[0] = Call({to: 0x8C1a617BdB47342F9C17Ac8750E0b070c372C721, value: 1, data: ""});

CrossChainRequest memory request = CrossChainRequest({
requester: 0x8C1a617BdB47342F9C17Ac8750E0b070c372C721,
calls: calls,
destinationChainId: 84532, // base sepolia chain ID
inboxContract: 0xB482b292878FDe64691d028A2237B34e91c7c7ea, // RIP7755Inbox on Base Sepolia
l2Oracle: 0x4C8BA32A5DAC2A720bb35CeDB51D6B067D104205, // Base Sepolia AnchorStateRegistry on Sepolia
l2OracleStorageKey: 0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49, // AnchorStateRegistry storage slot
rewardAsset: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE,
rewardAmount: 2,
finalityDelaySeconds: 1 weeks,
nonce: 0,
expiry: block.timestamp + 2 weeks,
extraData: new bytes[](0)
});
CrossChainRequest memory request = _getRequest();

vm.startBroadcast(pk);
outbox.requestCrossChainCall{value: request.rewardAmount}(request);
vm.stopBroadcast();
}

function _getRequest() private pure returns (CrossChainRequest memory) {
return CrossChainRequest({
requester: 0x328809Bc894f92807417D2dAD6b7C998c1aFdac6,
calls: new Call[](0),
destinationChainId: 11155420,
inboxContract: 0x49E2cDC9e81825B6C718ae8244fe0D5b062F4874, // RIP7755Inbox on Optimism Sepolia
l2Oracle: 0x218CD9489199F321E1177b56385d333c5B598629, // Anchor State Registry on Sepolia
l2OracleStorageKey: 0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49, // Anchor State Registry storage slot
rewardAsset: 0x2e234DAe75C793f67A35089C9d99245E1C58470b,
rewardAmount: 1 ether,
finalityDelaySeconds: 10,
nonce: 1,
expiry: 1828828574,
extraData: new bytes[](0)
});
}
}
37 changes: 37 additions & 0 deletions contracts/script/actions/SubmitToInbox.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {Script} from "forge-std/Script.sol";

import {RIP7755Inbox} from "../../src/RIP7755Inbox.sol";
import {CrossChainRequest, Call} from "../../src/RIP7755Structs.sol";

contract SubmitToInbox is Script {
function run() external {
uint256 pk = vm.envUint("PRIVATE_KEY");
RIP7755Inbox inbox = RIP7755Inbox(0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512);

CrossChainRequest memory request = _getRequest();

vm.startBroadcast(pk);
inbox.fulfill(request, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266);
vm.stopBroadcast();
}

function _getRequest() private pure returns (CrossChainRequest memory) {
return CrossChainRequest({
requester: 0x328809Bc894f92807417D2dAD6b7C998c1aFdac6,
calls: new Call[](0),
destinationChainId: 111112,
inboxContract: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512, // RIP7755Inbox on mock Chain B
l2Oracle: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512, // Anchor State Registry on mock L1
l2OracleStorageKey: 0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49, // Anchor State Registry storage slot
rewardAsset: 0x2e234DAe75C793f67A35089C9d99245E1C58470b,
rewardAmount: 1 ether,
finalityDelaySeconds: 10,
nonce: 1,
expiry: 1828828574,
extraData: new bytes[](0)
});
}
}
15 changes: 5 additions & 10 deletions contracts/src/libraries/provers/OPStackProver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ library OPStackProver {
function validate(bytes calldata proof, Target memory target) internal view returns (uint256, bytes memory) {
RIP7755Proof memory proofData = abi.decode(proof, (RIP7755Proof));

// Set the expected storage key and value for the `RIP7755Inbox` on the destination OP Stack chain
// NOTE: the following two lines are temporarily commented out for hacky tests
// proofData.dstL2AccountProofParams.storageKey = target.l2StorageKey;
// proofData.dstL2AccountProofParams.storageValue = _encodeFulfillmentInfo(fulfillmentInfo);
// Set the expected storage key for the L1 storage slot
proofData.dstL2StateRootProofParams.storageKey = abi.encode(target.l1StorageKey);
// Set the expected storage key for the `RIP7755Inbox` storage slot
proofData.dstL2AccountProofParams.storageKey = abi.encode(target.l2StorageKey);

// We first need to validate knowledge of the destination L2 chain's state root.
// StateValidator.validateState will accomplish each of the following 4 steps:
Expand Down Expand Up @@ -119,12 +119,7 @@ library OPStackProver {
// This library function will accomplish the following 2 steps:
// 5. Validate L2 account proof where `account` here is `RIP7755Inbox` on destination chain
// 6. Validate storage proof proving FulfillmentInfo in `RIP7755Inbox` storage
// NOTE: the following line is a temporary line used to validate proof logic. Will be removed in the near future.
bool validL2Storage = 0xAd6A7addf807D846A590E76C5830B609F831Ba2E.validateAccountStorage(
l2StateRoot, proofData.dstL2AccountProofParams
);
// bool validL2Storage =
// target.l2Address.validateAccountStorage(proofData.l2StateRoot, proofData.dstL2AccountProofParams);
bool validL2Storage = target.l2Address.validateAccountStorage(l2StateRoot, proofData.dstL2AccountProofParams);

if (!validL2Storage) {
revert InvalidL2Storage();
Expand Down
12 changes: 6 additions & 6 deletions contracts/test/OPStackProver.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ contract RIP7755OutboxOPStackValidatorTest is Test {

bytes memory storageProofData = _buildProofAndEncodeProof(validProof);
bytes memory inboxStorageKey = _deriveStorageKey(request);
request.finalityDelaySeconds = type(uint256).max;
request.finalityDelaySeconds = type(uint256).max - 1 ether;

vm.prank(FILLER);
vm.expectRevert(RIP7755OutboxToOPStack.FinalityDelaySecondsInProgress.selector);
Expand Down Expand Up @@ -183,13 +183,13 @@ contract RIP7755OutboxOPStackValidatorTest is Test {

function _initRequest(uint256 rewardAmount) private view returns (CrossChainRequest memory) {
return CrossChainRequest({
requester: ALICE,
requester: 0x328809Bc894f92807417D2dAD6b7C998c1aFdac6,
calls: calls,
destinationChainId: 11155420,
inboxContract: 0x49E2cDC9e81825B6C718ae8244fe0D5b062F4874, // RIP7755Inbox on Optimism Sepolia
l2Oracle: 0x218CD9489199F321E1177b56385d333c5B598629, // Anchor State Registry on Sepolia
destinationChainId: 111112,
inboxContract: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512, // RIP7755Inbox on mock Chain B
l2Oracle: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512, // Anchor State Registry on mock L1
l2OracleStorageKey: 0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49, // Anchor State Registry storage slot
rewardAsset: address(mockErc20),
rewardAsset: 0x2e234DAe75C793f67A35089C9d99245E1C58470b,
rewardAmount: rewardAmount,
finalityDelaySeconds: 10,
nonce: 1,
Expand Down
Loading

0 comments on commit 97c42f6

Please sign in to comment.