diff --git a/.env.example b/.env.example index 8c82c68..ec03052 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,47 @@ -ARBITRUM_RPC_URL= # Arbitrum Sepolia URL -ETHEREUM_RPC_URL= # Ethereum Sepolia URL +ARBITRUM_RPC_URL= +ETHEREUM_RPC_URL= +ZKSYNC_RPC_URL= OPTIMISM_RPC_URL= -LINEA_SEPOLIA= # Ethereum Sepolia URL \ No newline at end of file +LINEA_RPC_URL= +SCROLL_RPC_URL= + +OWNER=0xCc2ACDd7eF3e9841d42E00199D4cF5bcdCa77a7e + +DEPLOYER_PRIVATE_KEY= + +ETHEREUM_CHAIN_ID= + +# Arbitrum Envs +ARBITRUM_CHAIN_ID= +ARBITRUM_OUTBOX= +ARBITRUM_ROOTS_SLOT= + +#Linea Envs +LINEA_CHAIN_ID= +LINEA_ROLLUP= +LINEA_STATE_ROOT_HASHES_SLOT= +LINEA_L2_MESSAGE_SERVICE= + +# Scroll Envs +SCROLL_CHAIN_ID= +SCROLL_CHAIN_SEPOLIA= +SCROLL_FINALIZED_STATE_ROOT_SLOT= +L1_SCROLL_MESSENGER= +L2_SCROLL_MESSENGER= + +# Optimism Envs +OPTIMISM_CHAIN_ID= +OPTIMISM_ANCHOR_GAME_SLOT= +OPTIMISM_ANCHOR_STATE_REGISTRY= +OPTIMISM_L1_CROSS_DOMAIN_MESSENGER_PROXY= +OPTIMISM_L2_CROSS_DOMAIN_MESSENGER= + +# ZkSync Envs +ZKSYNC_CHAIN_ID= +ZKSYNC_DIAMOND= +ZKSYNC_GATEWAY_ZK_CHAIN= +ZKSYNC_L2_LOGS_ROOT_HASH_SLOT= +ZKSYNC_GATEWAY_CHAIN_ID= + + + diff --git a/deployments/arbitrum-sepolia.json b/deployments/arbitrum-sepolia.json new file mode 100644 index 0000000..daffab6 --- /dev/null +++ b/deployments/arbitrum-sepolia.json @@ -0,0 +1,22 @@ +{ + "contracts": { + "broadcaster": "0x2e6f2Cb4bf4E4D2166F83958442a180825B94248", + "receiver": "0x712535fE2e24df51917DB5438EB3dA90437F70AF", + "buffer": "0x0000000048C4Ed10cF14A02B9E0AbDDA5227b071", + "pusher": "0x5a5C4f3D0F0Efaeed2aEc9B59B67eC62a4666D88" + }, + "copies": { + "ethereum-sepolia": { + "linea-sepolia": "0x3E36338736c590753F071D90779b0449bD576834", + "scroll-sepolia": "0x2635119429AFE9ed4b5dC38f71D12f1A241231Ec", + "optimism-sepolia": "0x9B22f2bB9a5ECbEd10984f47c1A5FE8C551Fbf6a", + "zksync-sepolia": "0xf5e56d9d93267631f69dB9388d38e9c487830bD4" + } + }, + "provers": { + "ethereum-sepolia": { + "pointer": "0x2B48c5BeE8A3C63bbD5f5Be10bFCcda2ab372BF0", + "prover": "0x9b7478a19530735ef5DC022c3f00Bf303acc6950" + } + } +} \ No newline at end of file diff --git a/deployments/ethereum-sepolia.json b/deployments/ethereum-sepolia.json new file mode 100644 index 0000000..4d46a91 --- /dev/null +++ b/deployments/ethereum-sepolia.json @@ -0,0 +1,35 @@ +{ + "contracts": { + "broadcaster": "0x2e6f2Cb4bf4E4D2166F83958442a180825B94248", + "receiver": "0x712535fE2e24df51917DB5438EB3dA90437F70AF" + }, + "pushers": { + "arbitrum-sepolia": "0x5a5C4f3D0F0Efaeed2aEc9B59B67eC62a4666D88", + "linea-sepolia": "0x2aC21Fcfd6905eF13FA9bc0F874f3524029cB443", + "scroll-sepolia": "0xF99b4E792aCaBa74cb2d1A5D3fDBDFfe630C0a8e", + "zksync-sepolia": "0xc69281Edb758A5dDD7A13e12b4F3d81b14Bd983B", + "optimism-sepolia": "0x2c4ded0d5883646AEAD86a6C748c871afa819125" + }, + "provers": { + "arbitrum-sepolia": { + "pointer": "0x95D7Dd7F981ADFaA6a8C8446a2d026Bef16949d6", + "prover": "0x3ed2414D931f28Ef85D2E5e74e509d6FEDB812F6" + }, + "linea-sepolia": { + "pointer": "0x99ED6a6C9749D624b2D6aF881cdcaE5248Eb290b", + "prover": "0x3E36338736c590753F071D90779b0449bD576834" + }, + "scroll-sepolia": { + "pointer": "0x3FAe4F166289B46122b8236e948268d7846edeB6", + "prover": "0x2635119429AFE9ed4b5dC38f71D12f1A241231Ec" + }, + "optimism-sepolia": { + "pointer": "0xba8A90CE0DF7cCBFd2d8cC47D53BdA0303E4e24a", + "prover": "0x9B22f2bB9a5ECbEd10984f47c1A5FE8C551Fbf6a" + }, + "zksync-sepolia": { + "pointer": "0x7cac647e088b7361953f37C0C3BaA092748b8E7F", + "prover": "0xf5e56d9d93267631f69dB9388d38e9c487830bD4" + } + } +} \ No newline at end of file diff --git a/deployments/linea-sepolia.json b/deployments/linea-sepolia.json new file mode 100644 index 0000000..7040372 --- /dev/null +++ b/deployments/linea-sepolia.json @@ -0,0 +1,22 @@ +{ + "contracts": { + "broadcaster": "0x2e6f2Cb4bf4E4D2166F83958442a180825B94248", + "receiver": "0x712535fE2e24df51917DB5438EB3dA90437F70AF", + "buffer": "0xCd455Df9F48Af8C86427fE3F86787D95330F65AA", + "pusher": "0x2aC21Fcfd6905eF13FA9bc0F874f3524029cB443" + }, + "copies": { + "ethereum-sepolia": { + "arbitrum-sepolia": "0x3ed2414D931f28Ef85D2E5e74e509d6FEDB812F6", + "scroll-sepolia": "0x2635119429AFE9ed4b5dC38f71D12f1A241231Ec", + "optimism-sepolia": "0x9B22f2bB9a5ECbEd10984f47c1A5FE8C551Fbf6a", + "zksync-sepolia": "0xf5e56d9d93267631f69dB9388d38e9c487830bD4" + } + }, + "provers": { + "ethereum-sepolia": { + "pointer": "0x2B48c5BeE8A3C63bbD5f5Be10bFCcda2ab372BF0", + "prover": "0xCde1e6b2Dc517838c1eD4544c588e177F83D64E1" + } + } +} \ No newline at end of file diff --git a/deployments/optimism-sepolia.json b/deployments/optimism-sepolia.json new file mode 100644 index 0000000..b187d66 --- /dev/null +++ b/deployments/optimism-sepolia.json @@ -0,0 +1,22 @@ +{ + "contracts": { + "broadcaster": "0x2e6f2Cb4bf4E4D2166F83958442a180825B94248", + "receiver": "0x712535fE2e24df51917DB5438EB3dA90437F70AF", + "buffer": "0xaC0a6EB6407b9C13c3B374219B2f91fda4DF47C5", + "pusher": "0x2c4ded0d5883646AEAD86a6C748c871afa819125" + }, + "copies": { + "ethereum-sepolia": { + "arbitrum-sepolia": "0x3ed2414D931f28Ef85D2E5e74e509d6FEDB812F6", + "linea-sepolia": "0x3E36338736c590753F071D90779b0449bD576834", + "scroll-sepolia": "0x2635119429AFE9ed4b5dC38f71D12f1A241231Ec", + "zksync-sepolia": "0xf5e56d9d93267631f69dB9388d38e9c487830bD4" + } + }, + "provers": { + "ethereum-sepolia": { + "pointer": "0x2B48c5BeE8A3C63bbD5f5Be10bFCcda2ab372BF0", + "prover": "0xBEFC80AD06A03f1e15c71e370D935a25820a7E19" + } + } +} \ No newline at end of file diff --git a/deployments/scroll-sepolia.json b/deployments/scroll-sepolia.json new file mode 100644 index 0000000..13ece6a --- /dev/null +++ b/deployments/scroll-sepolia.json @@ -0,0 +1,22 @@ +{ + "contracts": { + "broadcaster": "0x2e6f2Cb4bf4E4D2166F83958442a180825B94248", + "receiver": "0x712535fE2e24df51917DB5438EB3dA90437F70AF", + "buffer": "0x12e91f63cC0F43434141396AC0E9f5b1A0e103D6", + "pusher": "0xF99b4E792aCaBa74cb2d1A5D3fDBDFfe630C0a8e" + }, + "copies": { + "ethereum-sepolia": { + "arbitrum-sepolia": "0x3ed2414D931f28Ef85D2E5e74e509d6FEDB812F6", + "linea-sepolia": "0x3E36338736c590753F071D90779b0449bD576834", + "optimism-sepolia": "0x9B22f2bB9a5ECbEd10984f47c1A5FE8C551Fbf6a", + "zksync-sepolia": "0xf5e56d9d93267631f69dB9388d38e9c487830bD4" + } + }, + "provers": { + "ethereum-sepolia": { + "pointer": "0x2B48c5BeE8A3C63bbD5f5Be10bFCcda2ab372BF0", + "prover": "0x852060961640ff9569946000E049c44c13bCEe98" + } + } +} \ No newline at end of file diff --git a/deployments/zksync-sepolia.json b/deployments/zksync-sepolia.json new file mode 100644 index 0000000..4b1760d --- /dev/null +++ b/deployments/zksync-sepolia.json @@ -0,0 +1,22 @@ +{ + "contracts": { + "broadcaster": "0x5483634580acDB4f0134E09025732DF9784e46e3", + "receiver": "0x712535fE2e24df51917DB5438EB3dA90437F70AF", + "buffer": "0x4309FcAA812F729A2c6Fc9b67094296389eC919c", + "pusher": "0xc69281Edb758A5dDD7A13e12b4F3d81b14Bd983B" + }, + "copies": { + "ethereum-sepolia": { + "arbitrum-sepolia": "0x3ed2414D931f28Ef85D2E5e74e509d6FEDB812F6", + "linea-sepolia": "0x3E36338736c590753F071D90779b0449bD576834", + "scroll-sepolia": "0x2635119429AFE9ed4b5dC38f71D12f1A241231Ec", + "optimism-sepolia": "0x9B22f2bB9a5ECbEd10984f47c1A5FE8C551Fbf6a" + } + }, + "provers": { + "ethereum-sepolia": { + "pointer": "0x2B48c5BeE8A3C63bbD5f5Be10bFCcda2ab372BF0", + "prover": "0xAD72b787ECCEA11C97770207862BF0a3c35C138e" + } + } +} \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index fb55229..a3750be 100644 --- a/foundry.toml +++ b/foundry.toml @@ -3,7 +3,9 @@ src = "src/contracts" out = "out" libs = ["lib"] solc = "0.8.30" - +script = "scripts" +optimizer = true +optimizer_runs = 200 via_ir = true fs_permissions = [ @@ -14,7 +16,9 @@ fs_permissions = [ { access = 'read', path = './test/payloads/taiko' }, { access = 'read', path = './test/payloads/linea' }, { access = 'read', path = './test/payloads/scroll' }, + + { access = "read-write", path = "./deployments" }, { access = 'read', path = './out' }, ] -# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index b02015a..6dc10ec 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -5,7 +5,7 @@ import '@nomicfoundation/hardhat-toolbox-viem' const config: HardhatUserConfig = { solidity: { - version: '0.8.28', + version: '0.8.30', settings: { evmVersion: 'cancun', optimizer: { diff --git a/scripts/Deploy.s.sol b/scripts/Deploy.s.sol deleted file mode 100644 index e164f15..0000000 --- a/scripts/Deploy.s.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.27; - -import { Script } from "forge-std/Script.sol"; - - -import { console } from "forge-std/console.sol"; -import { Broadcaster } from "../src/contracts/Broadcaster.sol"; -import { Receiver } from "../src/contracts/Receiver.sol"; - - -contract Deploy is Script { - function run() public { - vm.startBroadcast(); - Broadcaster broadcaster = new Broadcaster(); - Receiver receiver = new Receiver(); - vm.stopBroadcast(); - - console.log("Broadcaster deployed to:", address(broadcaster)); - console.log("Receiver deployed to:", address(receiver)); - } -} \ No newline at end of file diff --git a/scripts/DeployBroadcaster.s.sol b/scripts/DeployBroadcaster.s.sol deleted file mode 100644 index 13cdbea..0000000 --- a/scripts/DeployBroadcaster.s.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.30; - -import { Script } from "forge-std/Script.sol"; - - -import { console } from "forge-std/console.sol"; -import { Broadcaster } from "../src/contracts/Broadcaster.sol"; -import { Receiver } from "../src/contracts/Receiver.sol"; - - -contract DeployBroadcaster is Script { - function run() public { - vm.startBroadcast(); - //Broadcaster broadcaster = new Broadcaster(); - Receiver receiver = new Receiver(); - vm.stopBroadcast(); - - //console.log("Broadcaster deployed to:", address(broadcaster)); - console.log("Receiver deployed to:", address(receiver)); - } -} \ No newline at end of file diff --git a/scripts/DeployZkSyncBroadcaster.s.sol b/scripts/DeployZkSyncBroadcaster.s.sol deleted file mode 100644 index 1ec1de4..0000000 --- a/scripts/DeployZkSyncBroadcaster.s.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.30; - -import { Script } from "forge-std/Script.sol"; - - -import { console } from "forge-std/console.sol"; -import { ZkSyncBroadcaster } from "../src/contracts/ZkSyncBroadcaster.sol"; -import { Receiver } from "../src/contracts/Receiver.sol"; - - -contract DeployBroadcaster is Script { - function run() public { - vm.startBroadcast(); - ZkSyncBroadcaster broadcaster = new ZkSyncBroadcaster(0x0000000000000000000000000000000000008008); - //Receiver receiver = new Receiver(); - vm.stopBroadcast(); - - console.log("ZkSyncBroadcaster deployed to:", address(broadcaster)); - //console.log("Receiver deployed to:", address(receiver)); - } -} \ No newline at end of file diff --git a/scripts/deployment/DeployBase.s.sol b/scripts/deployment/DeployBase.s.sol new file mode 100644 index 0000000..3e76fb7 --- /dev/null +++ b/scripts/deployment/DeployBase.s.sol @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {Script} from "forge-std/Script.sol"; +import {console2} from "forge-std/console2.sol"; +import {LowLevelCall} from "@openzeppelin/contracts/utils/LowLevelCall.sol"; +import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; + +contract DeployBase is Script { + error InvalidChainId(uint256 chainId); + error DeploymentFailed(); + error InvalidPusherAddress(); + error InvalidBufferAddress(); + + // See https://github.com/Arachnid/deterministic-deployment-proxy + // According to this research: https://ethereum-magicians.org/t/eip-7997-deterministic-factory-predeploy/24998/15 + // the Arachnid deployment proxy is the widest proxy available and its adoption suggests that a + // more effect approach to support deterministic addresses is to enshrine it as a predeployed contract + // through proposals like [RIP-7740](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7740.md). + address public constant DEPLOYMENT_PROXY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; + + function _chainName(uint256 chainId) internal view returns (string memory) { + if (chainId == 11155111) return "ethereum-sepolia"; + if (chainId == 421614) return "arbitrum-sepolia"; + if (chainId == 59141) return "linea-sepolia"; + if (chainId == 534351) return "scroll-sepolia"; + if (chainId == 11155420) return "optimism-sepolia"; + if (chainId == 300) return "zksync-sepolia"; + revert InvalidChainId(chainId); + } + + function _deploymentsDir() internal view returns (string memory) { + return string.concat(vm.projectRoot(), "/deployments"); + } + + function _path() internal view returns (string memory) { + return string.concat(_deploymentsDir(), "/", _chainName(block.chainid), ".json"); + } + + function _jsonString(string memory s) internal pure returns (string memory) { + return string.concat('"', s, '"'); + } + + function _ensureDeploymentsDir() internal { + vm.createDir(_deploymentsDir(), true); + } + + function _ensureFile(string memory path) internal { + _ensureDeploymentsDir(); + if (!vm.exists(path)) { + // start as an empty object; we’ll add objects below + vm.writeFile(path, "{}"); + } else { + string memory content = vm.readFile(path); + if (bytes(content).length == 0) vm.writeFile(path, "{}"); + } + } + + /// Ensures that `jsonPath` exists and is an object. If missing, creates `{}` there. + function _ensureObjectAt(string memory path, string memory jsonPath) internal { + string memory content = vm.readFile(path); + try vm.parseJson(content, jsonPath) returns ( + bytes memory + ) { + // exists (and is parseable), do nothing + } + catch { + vm.writeJson("{}", path, jsonPath); + } + } + + function _ensureObjectAtPtr(string memory path, string memory ptr) internal { + // Ensure an object exists at JSON Pointer `ptr` (e.g. "/provers/arbitrum-sepolia") + string memory content = vm.readFile(path); + try vm.parseJson(content, ptr) returns ( + bytes memory + ) { + // exists + } + catch { + vm.writeJson("{}", path, ptr); + } + } + + function _ensureRootScaffold(string memory path) internal { + _ensureFile(path); + _ensureObjectAt(path, ".contracts"); + _ensureObjectAt(path, ".provers"); + _ensureObjectAt(path, ".copies"); + } + + function _getPusherAddress(string memory parentChain, string memory childChain) internal returns (address) { + string memory path = string.concat(_deploymentsDir(), "/", parentChain, ".json"); + string memory json = vm.readFile(path); + if (!vm.keyExistsJson(json, string.concat(".pushers.", childChain))) { + revert InvalidPusherAddress(); + } + return vm.parseJsonAddress(json, string.concat(".pushers.", childChain)); + } + + function _getBufferAddress(string memory childChain) internal returns (address) { + string memory path = string.concat(_deploymentsDir(), "/", childChain, ".json"); + string memory json = vm.readFile(path); + if (!vm.keyExistsJson(json, string.concat(".contracts.", "buffer"))) { + revert InvalidBufferAddress(); + } + return vm.parseJsonAddress(json, string.concat(".contracts.", "buffer")); + } + + // ------------------------- + // Writes + // ------------------------- + + function _isContractDeployed(string memory name) internal returns (bool) { + string memory path = _path(); + _ensureRootScaffold(path); + string memory json = vm.readFile(path); + return vm.keyExistsJson(json, string.concat(".contracts.", name)); + } + + function _isProverDeployed(string memory chainKey) internal returns (bool) { + string memory path = _path(); + _ensureRootScaffold(path); + string memory json = vm.readFile(path); + return vm.keyExistsJson(json, string.concat(".provers.", chainKey)); + } + + function _isCopyDeployed(string memory homeChain, string memory targetChain) internal returns (bool) { + string memory path = _path(); + _ensureRootScaffold(path); + string memory json = vm.readFile(path); + return vm.keyExistsJson(json, string.concat(".copies.", homeChain, ".", targetChain)); + } + + function _isPusherDeployed(string memory chainKey) internal returns (bool) { + string memory path = _path(); + _ensureRootScaffold(path); + string memory json = vm.readFile(path); + return vm.keyExistsJson(json, string.concat(".pushers.", chainKey)); + } + + function _isBufferDeployed(string memory chainKey) internal returns (bool) { + string memory path = _path(); + _ensureRootScaffold(path); + string memory json = vm.readFile(path); + return vm.keyExistsJson(json, string.concat(".buffers.", chainKey)); + } + + function _writeContract(string memory name, address addr) internal { + string memory path = _path(); + _ensureRootScaffold(path); + + vm.writeJson(_jsonString(vm.toString(addr)), path, string.concat(".contracts.", name)); + } + + function _writeContractAtChain(uint256 chainId, string memory name, address addr) internal { + string memory path = string.concat(_deploymentsDir(), "/", _chainName(chainId), ".json"); + _ensureRootScaffold(path); + + vm.writeJson(_jsonString(vm.toString(addr)), path, string.concat(".contracts.", name)); + } + + /// Adds/updates `.provers["chainKey"].pointer` and `.provers["chainKey"].prover` + function _writeProver(string memory chainKey, address pointer, address prover) internal { + string memory path = _path(); + _ensureRootScaffold(path); + + // Ensure `.provers.` exists as an object + string memory objPath = string.concat(".provers.", chainKey); + _ensureObjectAt(path, objPath); + + // Write the pointer and prover addresses + vm.writeJson(_jsonString(vm.toString(pointer)), path, string.concat(objPath, ".pointer")); + vm.writeJson(_jsonString(vm.toString(prover)), path, string.concat(objPath, ".prover")); + } + + /// Adds/updates `.pushers["chainKey"]` + function _writePusher(string memory chainKey, address pusher) internal { + string memory path = _path(); + _ensureRootScaffold(path); + + // Ensure `.pushers.` exists as an object + string memory objPath = string.concat(".pushers.", chainKey); + _ensureObjectAt(path, objPath); + + // Write the pusher address + vm.writeJson(_jsonString(vm.toString(pusher)), path, objPath); + } + + /// Adds/updates `.copies["src"]["dst"] = "0x..."` + function _writeCopy(string memory homeChain, string memory targetChain, address copyAddr) internal { + string memory path = _path(); + _ensureRootScaffold(path); + + // Ensure `.copies.` exists as an object + string memory homeObjPath = string.concat(".copies.", homeChain); + _ensureObjectAt(path, homeObjPath); + + // Set `.copies.. = "0x..."` + string memory leafPath = string.concat(homeObjPath, ".", targetChain); + vm.writeJson(_jsonString(vm.toString(copyAddr)), path, leafPath); + } + + function _deploy(bytes memory creationCode, bytes32 salt) internal returns (address) { + address predictedAddress = Create2.computeAddress(salt, keccak256(creationCode), DEPLOYMENT_PROXY); + + bool success = LowLevelCall.callNoReturn(DEPLOYMENT_PROXY, abi.encodePacked(salt, creationCode)); + + return predictedAddress; + } +} diff --git a/scripts/deployment/DeployProtocol.s.sol b/scripts/deployment/DeployProtocol.s.sol new file mode 100644 index 0000000..c6f47e9 --- /dev/null +++ b/scripts/deployment/DeployProtocol.s.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "./DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {Broadcaster} from "src/contracts/Broadcaster.sol"; +import {ZkSyncBroadcaster} from "src/contracts/ZkSyncBroadcaster.sol"; +import {Receiver} from "src/contracts/Receiver.sol"; +import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; + +contract Deploy is DeployBase { + function run() public { + string memory chainType = vm.envString("CHAIN_TYPE"); + + address broadcasterAddress; + + vm.startBroadcast(); + + if (!_isContractDeployed("broadcaster")) { + if (keccak256(bytes(chainType)) == keccak256(bytes("zksync"))) { + address l1Messenger = 0x0000000000000000000000000000000000008008; + bytes memory creationCode = + abi.encodePacked(type(ZkSyncBroadcaster).creationCode, abi.encode(l1Messenger)); + broadcasterAddress = _deploy(creationCode, bytes32(0)); + } else { + bytes memory creationCode = type(Broadcaster).creationCode; + broadcasterAddress = _deploy(creationCode, bytes32(0)); + } + + if (broadcasterAddress == address(0)) { + console.log("Failed to deploy broadcaster on chain ", _chainName(block.chainid)); + } else { + _writeContract("broadcaster", broadcasterAddress); + } + } + + if (!_isContractDeployed("receiver")) { + bytes memory creationCode = type(Receiver).creationCode; + address receiverAddress = _deploy(creationCode, bytes32(0)); + if (receiverAddress == address(0)) { + console.log("Failed to deploy receiver on chain ", _chainName(block.chainid)); + } else { + _writeContract("receiver", receiverAddress); + } + } + + vm.stopBroadcast(); + } +} diff --git a/scripts/deployment/block-hash-pusher/DeployBuffers.s.sol b/scripts/deployment/block-hash-pusher/DeployBuffers.s.sol new file mode 100644 index 0000000..2301e23 --- /dev/null +++ b/scripts/deployment/block-hash-pusher/DeployBuffers.s.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {LineaBuffer} from "src/contracts/block-hash-pusher/linea/LineaBuffer.sol"; +import {ScrollBuffer} from "src/contracts/block-hash-pusher/scroll/ScrollBuffer.sol"; +import {ZkSyncBuffer} from "src/contracts/block-hash-pusher/zksync/ZkSyncBuffer.sol"; +import {OptimismBuffer} from "src/contracts/block-hash-pusher/optimism/OptimismBuffer.sol"; +import {DeployBase} from "../DeployBase.s.sol"; + +contract DeployBuffers is DeployBase { + function run() public { + string memory chainType = vm.envString("CHAIN_TYPE"); + string memory parentChain = vm.envString("PARENT_CHAIN"); + string memory childChain = vm.envString("CHILD_CHAIN"); + + address pusherAddress = _getPusherAddress(parentChain, childChain); + if (pusherAddress == address(0)) { + revert InvalidPusherAddress(); + } + + address messenger; + address buffer; + + vm.startBroadcast(); + if (_isContractDeployed("buffer")) { + console.log("Buffer already deployed on chain ", _chainName(block.chainid)); + return; + } + + if (keccak256(bytes(chainType)) == keccak256(bytes("zksync"))) { + buffer = address(new ZkSyncBuffer(pusherAddress)); + } else { + messenger = vm.envAddress("MESSENGER"); + + if (keccak256(bytes(chainType)) == keccak256(bytes("linea"))) { + buffer = address(new LineaBuffer(messenger, pusherAddress)); + } else if (keccak256(bytes(chainType)) == keccak256(bytes("scroll"))) { + buffer = address(new ScrollBuffer(messenger, pusherAddress)); + } else if (keccak256(bytes(chainType)) == keccak256(bytes("optimism"))) { + buffer = address(new OptimismBuffer(messenger, pusherAddress)); + } else { + revert("Invalid chain type"); + } + } + vm.stopBroadcast(); + + if (buffer != address(0)) { + _writeContract("buffer", buffer); + } else { + console.log("Failed to deploy buffer on chain ", _chainName(block.chainid)); + } + } +} diff --git a/scripts/deployment/block-hash-pusher/DeployPushers.s.sol b/scripts/deployment/block-hash-pusher/DeployPushers.s.sol new file mode 100644 index 0000000..fe8fc44 --- /dev/null +++ b/scripts/deployment/block-hash-pusher/DeployPushers.s.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {LineaPusher} from "src/contracts/block-hash-pusher/linea/LineaPusher.sol"; +import {ScrollPusher} from "src/contracts/block-hash-pusher/scroll/ScrollPusher.sol"; +import {ZkSyncPusher} from "src/contracts/block-hash-pusher/zksync/ZkSyncPusher.sol"; +import {OptimismPusher} from "src/contracts/block-hash-pusher/optimism/OptimismPusher.sol"; +import {DeployBase} from "../DeployBase.s.sol"; + +contract DeployPushers is DeployBase { + function run() public { + address lineaRollup = vm.envAddress("LINEA_ROLLUP"); + address l1ScrollMessenger = vm.envAddress("L1_SCROLL_MESSENGER"); + address zkSyncDiamond = vm.envAddress("ZKSYNC_DIAMOND"); + address opL1CrossDomainMessengerProxy = vm.envAddress("OPTIMISM_L1_CROSS_DOMAIN_MESSENGER_PROXY"); + + uint256 lineaChainId = vm.envUint("LINEA_CHAIN_ID"); + uint256 scrollChainId = vm.envUint("SCROLL_CHAIN_ID"); + uint256 zksyncChainId = vm.envUint("ZKSYNC_CHAIN_ID"); + uint256 optimismChainId = vm.envUint("OPTIMISM_CHAIN_ID"); + + vm.startBroadcast(); + if (!_isPusherDeployed("linea-sepolia")) { + LineaPusher lineaPusher = new LineaPusher(lineaRollup); + _writePusher("linea-sepolia", address(lineaPusher)); + _writeContractAtChain(lineaChainId, "pusher", address(lineaPusher)); + } + if (!_isPusherDeployed("scroll-sepolia")) { + ScrollPusher scrollPusher = new ScrollPusher(l1ScrollMessenger); + _writePusher("scroll-sepolia", address(scrollPusher)); + _writeContractAtChain(scrollChainId, "pusher", address(scrollPusher)); + } + if (!_isPusherDeployed("zksync-sepolia")) { + ZkSyncPusher zksyncPusher = new ZkSyncPusher(zkSyncDiamond); + _writePusher("zksync-sepolia", address(zksyncPusher)); + _writeContractAtChain(zksyncChainId, "pusher", address(zksyncPusher)); + } + if (!_isPusherDeployed("optimism-sepolia")) { + OptimismPusher optimismPusher = new OptimismPusher(opL1CrossDomainMessengerProxy); + _writePusher("optimism-sepolia", address(optimismPusher)); + _writeContractAtChain(optimismChainId, "pusher", address(optimismPusher)); + } + vm.stopBroadcast(); + } +} diff --git a/scripts/deployment/block-hash-pusher/deploy-buffers.sh b/scripts/deployment/block-hash-pusher/deploy-buffers.sh new file mode 100755 index 0000000..957e6d2 --- /dev/null +++ b/scripts/deployment/block-hash-pusher/deploy-buffers.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +CHAIN_TYPE=$CHAIN_TYPE \ +PARENT_CHAIN=$PARENT_CHAIN \ +CHILD_CHAIN=$CHILD_CHAIN \ +MESSENGER=$MESSENGER \ +forge script scripts/deployment/block-hash-pusher/DeployBuffers.s.sol \ + --rpc-url "$RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + \ No newline at end of file diff --git a/scripts/deployment/block-hash-pusher/deploy-pushers.sh b/scripts/deployment/block-hash-pusher/deploy-pushers.sh new file mode 100755 index 0000000..6530217 --- /dev/null +++ b/scripts/deployment/block-hash-pusher/deploy-pushers.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +forge script scripts/deployment/block-hash-pusher/DeployPushers.s.sol \ + --rpc-url "$RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + \ No newline at end of file diff --git a/scripts/deployment/deploy-protocol.sh b/scripts/deployment/deploy-protocol.sh new file mode 100755 index 0000000..01ae3ef --- /dev/null +++ b/scripts/deployment/deploy-protocol.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +CHAIN_TYPE=$CHAIN_TYPE forge script scripts/deployment/DeployProtocol.s.sol \ + --rpc-url "$RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + \ No newline at end of file diff --git a/scripts/deployment/deploy.sh b/scripts/deployment/deploy.sh new file mode 100644 index 0000000..11fdb4d --- /dev/null +++ b/scripts/deployment/deploy.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash + +set -a +source .env +set +a + + +# ======================================================================================== +# Deploy Broadcaster and Receiver contracts +# ======================================================================================== +chmod +x scripts/deployment/deploy-protocol.sh + +echo "Deploying Broadcaster and Receiver contracts on Ethereum..." +CHAIN_TYPE="ethereum" \ +RPC_URL="$ETHEREUM_RPC_URL" \ +./scripts/deployment/deploy-protocol.sh + +echo "Deploying Broadcaster and Receiver contracts on Arbitrum..." +CHAIN_TYPE="arbitrum" \ +RPC_URL="$ARBITRUM_RPC_URL" \ +./scripts/deployment/deploy-protocol.sh + +echo "Deploying Broadcaster and Receiver contracts on Linea..." +CHAIN_TYPE="linea" \ +RPC_URL="$LINEA_RPC_URL" \ +./scripts/deployment/deploy-protocol.sh + +echo "Deploying Broadcaster and Receiver contracts on Scroll..." +CHAIN_TYPE="scroll" \ +RPC_URL="$SCROLL_RPC_URL" \ +./scripts/deployment/deploy-protocol.sh + +echo "Deploying Broadcaster and Receiver contracts on Optimism..." +CHAIN_TYPE="optimism" \ +RPC_URL="$OPTIMISM_RPC_URL" \ +./scripts/deployment/deploy-protocol.sh + +echo "Deploying Broadcaster and Receiver contracts on ZkSync..." +CHAIN_TYPE="zksync" \ +RPC_URL="$ZKSYNC_RPC_URL" \ +./scripts/deployment/deploy-protocol.sh + + +# ======================================================================================== +# Deploy ParentToChildProver contracts +# ======================================================================================== +chmod +x scripts/deployment/provers/deploy-parent-provers.sh + +# Ethereum +echo "Deploying ParentToChildProver contracts on Ethereum..." +RPC_URL="$ETHEREUM_RPC_URL" ./scripts/deployment/provers/deploy-parent-provers.sh + +# Arbitrum +echo "Deploying ParentToChildProver contracts on Arbitrum..." +RPC_URL="$ARBITRUM_RPC_URL" ./scripts/deployment/provers/deploy-parent-provers.sh + +# Linea +echo "Deploying ParentToChildProver contracts on Linea..." +RPC_URL="$LINEA_RPC_URL" ./scripts/deployment/provers/deploy-parent-provers.sh + +# Scroll +echo "Deploying ParentToChildProver contracts on Scroll..." +RPC_URL="$SCROLL_RPC_URL" ./scripts/deployment/provers/deploy-parent-provers.sh + +# Optimism +echo "Deploying ParentToChildProver contracts on Optimism..." +RPC_URL="$OPTIMISM_RPC_URL" ./scripts/deployment/provers/deploy-parent-provers.sh + +# ZkSync +echo "Deploying ParentToChildProver contracts on ZkSync..." +RPC_URL="$ZKSYNC_RPC_URL" ./scripts/deployment/provers/deploy-parent-provers.sh + + +# ======================================================================================== +# Deploy Pushers contracts +# ======================================================================================== + +# Ethereum +echo "Deploying Pushers contracts on Ethereum..." + +RPC_URL="$ETHEREUM_RPC_URL" ./scripts/deployment/block-hash-pusher/deploy-pushers.sh + +# ======================================================================================== +# Deploy Buffers contracts +# ======================================================================================== +chmod +x scripts/deployment/block-hash-pusher/deploy-buffers.sh + +# Ethereum + +# Linea +echo "Deploying Buffer contract for Linea..." +CHAIN_TYPE="linea" \ +PARENT_CHAIN="ethereum-sepolia" \ +CHILD_CHAIN="linea-sepolia" \ +MESSENGER="$LINEA_L2_MESSAGE_SERVICE" \ +RPC_URL="$LINEA_RPC_URL" ./scripts/deployment/block-hash-pusher/deploy-buffers.sh + +# Scroll +echo "Deploying Buffer contract for Scroll..." +CHAIN_TYPE="scroll" \ +PARENT_CHAIN="ethereum-sepolia" \ +CHILD_CHAIN="scroll-sepolia" \ +MESSENGER="$L2_SCROLL_MESSENGER" \ +RPC_URL="$SCROLL_RPC_URL" ./scripts/deployment/block-hash-pusher/deploy-buffers.sh + +# ZkSync +echo "Deploying Buffer contract for ZkSync..." +CHAIN_TYPE="zksync" \ +PARENT_CHAIN="ethereum-sepolia" \ +CHILD_CHAIN="zksync-sepolia" \ +MESSENGER=0x0000000000000000000000000000000000000000 \ +RPC_URL="$ZKSYNC_RPC_URL" ./scripts/deployment/block-hash-pusher/deploy-buffers.sh + +# Optimism +echo "Deploying Buffer contract for Optimism..." +CHAIN_TYPE="optimism" \ +PARENT_CHAIN="ethereum-sepolia" \ +CHILD_CHAIN="optimism-sepolia" \ +MESSENGER="$OPTIMISM_L2_CROSS_DOMAIN_MESSENGER" \ +RPC_URL="$OPTIMISM_RPC_URL" ./scripts/deployment/block-hash-pusher/deploy-buffers.sh + +# ======================================================================================== +# Deploy ChildToParentProver contracts +# ======================================================================================== +chmod +x scripts/deployment/provers/deploy-child-provers.sh + +# Ethereum +echo "Deploying ChildToParentProver contracts ..." +./scripts/deployment/provers/deploy-child-provers.sh diff --git a/scripts/deployment/provers/DeployArbitrumChildToParent.s.sol b/scripts/deployment/provers/DeployArbitrumChildToParent.s.sol new file mode 100644 index 0000000..4c0f064 --- /dev/null +++ b/scripts/deployment/provers/DeployArbitrumChildToParent.s.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ChildToParentProver} from "src/contracts/provers/arbitrum/ChildToParentProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployArbitrumChildToParent is DeployBase { + function run() public { + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + address owner = vm.envAddress("OWNER"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + + bytes memory proverCreationCode = + abi.encodePacked(type(ChildToParentProver).creationCode, abi.encode(homeChainId)); + prover = _deploy(proverCreationCode, bytes32(0)); + + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + // If the pointer is not deployed, it means that this is a copy of the prover deployed in a different chain. + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), prover); + } else { + _writeProver(_chainName(targetChainId), address(pointer), address(prover)); + } + } +} diff --git a/scripts/deployment/provers/DeployArbitrumParentToChild.s.sol b/scripts/deployment/provers/DeployArbitrumParentToChild.s.sol new file mode 100644 index 0000000..83c9988 --- /dev/null +++ b/scripts/deployment/provers/DeployArbitrumParentToChild.s.sol @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ParentToChildProver} from "src/contracts/provers/arbitrum/ParentToChildProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployArbitrumParentToChild is DeployBase { + function run() public { + address outbox = vm.envAddress("OUTBOX"); + uint256 rootsSlot = vm.envUint("ROOTS_SLOT"); + address owner = vm.envAddress("OWNER"); + + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + + bytes memory proverCreationCode = + abi.encodePacked(type(ParentToChildProver).creationCode, abi.encode(outbox, rootsSlot, homeChainId)); + prover = _deploy(proverCreationCode, bytes32(0)); + + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + // If the pointer is not deployed, it means that this is a copy of the prover deployed in a different chain. + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), prover); + } else { + _writeProver(_chainName(targetChainId), address(pointer), address(prover)); + } + } +} diff --git a/scripts/deployment/provers/DeployLineaChildToParent.s.sol b/scripts/deployment/provers/DeployLineaChildToParent.s.sol new file mode 100644 index 0000000..dfa6087 --- /dev/null +++ b/scripts/deployment/provers/DeployLineaChildToParent.s.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ChildToParentProver} from "src/contracts/provers/linea/ChildToParentProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployLineaChildToParent is DeployBase { + function run() public { + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + address owner = vm.envAddress("OWNER"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + address buffer = _getBufferAddress(_chainName(homeChainId)); + if (buffer == address(0)) { + revert InvalidBufferAddress(); + } + bytes memory proverCreationCode = + abi.encodePacked(type(ChildToParentProver).creationCode, abi.encode(buffer, homeChainId)); + prover = _deploy(proverCreationCode, bytes32(0)); + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), prover); + } else { + _writeProver(_chainName(targetChainId), address(pointer), prover); + } + } +} diff --git a/scripts/deployment/provers/DeployLineaParentToChild.s.sol b/scripts/deployment/provers/DeployLineaParentToChild.s.sol new file mode 100644 index 0000000..397f918 --- /dev/null +++ b/scripts/deployment/provers/DeployLineaParentToChild.s.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ParentToChildProver} from "src/contracts/provers/linea/ParentToChildProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployLineaParentToChild is DeployBase { + function run() public { + address rollup = vm.envAddress("ROLLUP"); + uint256 stateRootHashesSlot = vm.envUint("STATE_ROOT_HASHES_SLOT"); + address owner = vm.envAddress("OWNER"); + + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + bytes memory proverCreationCode = abi.encodePacked( + type(ParentToChildProver).creationCode, abi.encode(rollup, stateRootHashesSlot, homeChainId) + ); + prover = _deploy(proverCreationCode, bytes32(0)); + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), prover); + } else { + _writeProver(_chainName(targetChainId), address(pointer), prover); + } + } +} diff --git a/scripts/deployment/provers/DeployOptimismChildToParent.s.sol b/scripts/deployment/provers/DeployOptimismChildToParent.s.sol new file mode 100644 index 0000000..26a6897 --- /dev/null +++ b/scripts/deployment/provers/DeployOptimismChildToParent.s.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ChildToParentProver} from "src/contracts/provers/optimism/ChildToParentProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployOptimismChildToParent is DeployBase { + function run() public { + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + address owner = vm.envAddress("OWNER"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + address buffer = _getBufferAddress(_chainName(homeChainId)); + if (buffer == address(0)) { + revert InvalidBufferAddress(); + } + bytes memory proverCreationCode = + abi.encodePacked(type(ChildToParentProver).creationCode, abi.encode(buffer, homeChainId)); + prover = _deploy(proverCreationCode, bytes32(0)); + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), prover); + } else { + _writeProver(_chainName(targetChainId), address(pointer), prover); + } + } +} diff --git a/scripts/deployment/provers/DeployOptimismParentToChild.s.sol b/scripts/deployment/provers/DeployOptimismParentToChild.s.sol new file mode 100644 index 0000000..120b507 --- /dev/null +++ b/scripts/deployment/provers/DeployOptimismParentToChild.s.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ParentToChildProver} from "src/contracts/provers/optimism/ParentToChildProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployOptimismParentToChild is DeployBase { + function run() public { + address anchorStateRegistry = vm.envAddress("ANCHOR_STATE_REGISTRY"); + uint256 anchorGameSlot = vm.envUint("ANCHOR_GAME_SLOT"); + address owner = vm.envAddress("OWNER"); + + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + + bytes memory proverCreationCode = abi.encodePacked( + type(ParentToChildProver).creationCode, abi.encode(anchorStateRegistry, anchorGameSlot, homeChainId) + ); + prover = _deploy(proverCreationCode, bytes32(0)); + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + // If the pointer is not deployed, it means that this is a copy of the prover deployed in a different chain. + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), address(prover)); + } else { + _writeProver(_chainName(targetChainId), address(pointer), address(prover)); + } + } +} diff --git a/scripts/deployment/provers/DeployScrollChildToParent.s.sol b/scripts/deployment/provers/DeployScrollChildToParent.s.sol new file mode 100644 index 0000000..0117818 --- /dev/null +++ b/scripts/deployment/provers/DeployScrollChildToParent.s.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ChildToParentProver} from "src/contracts/provers/scroll/ChildToParentProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployScrollChildToParent is DeployBase { + function run() public { + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + address owner = vm.envAddress("OWNER"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + address buffer = _getBufferAddress(_chainName(homeChainId)); + if (buffer == address(0)) { + revert InvalidBufferAddress(); + } + bytes memory proverCreationCode = + abi.encodePacked(type(ChildToParentProver).creationCode, abi.encode(buffer, homeChainId)); + prover = _deploy(proverCreationCode, bytes32(0)); + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), prover); + } else { + _writeProver(_chainName(targetChainId), address(pointer), prover); + } + } +} diff --git a/scripts/deployment/provers/DeployScrollParentToChild.s.sol b/scripts/deployment/provers/DeployScrollParentToChild.s.sol new file mode 100644 index 0000000..56078a4 --- /dev/null +++ b/scripts/deployment/provers/DeployScrollParentToChild.s.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ParentToChildProver} from "src/contracts/provers/scroll/ParentToChildProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployArbitrumParentToChild is DeployBase { + function run() public { + address scrollChain = vm.envAddress("SCROLL_CHAIN"); + uint256 finalizedStateRootsSlot = vm.envUint("FINALIZED_STATE_ROOTS_SLOT"); + address owner = vm.envAddress("OWNER"); + + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + + bytes memory proverCreationCode = abi.encodePacked( + type(ParentToChildProver).creationCode, abi.encode(scrollChain, finalizedStateRootsSlot, homeChainId) + ); + prover = _deploy(proverCreationCode, bytes32(0)); + + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + // If the pointer is not deployed, it means that this is a copy of the prover deployed in a different chain. + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), address(prover)); + } else { + _writeProver(_chainName(targetChainId), address(pointer), address(prover)); + } + } +} diff --git a/scripts/deployment/provers/DeployZkSyncChildToParent.s.sol b/scripts/deployment/provers/DeployZkSyncChildToParent.s.sol new file mode 100644 index 0000000..b109455 --- /dev/null +++ b/scripts/deployment/provers/DeployZkSyncChildToParent.s.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ChildToParentProver} from "src/contracts/provers/zksync/ChildToParentProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployZkSyncChildToParent is DeployBase { + function run() public { + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + address owner = vm.envAddress("OWNER"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + address buffer = _getBufferAddress(_chainName(homeChainId)); + if (buffer == address(0)) { + revert InvalidBufferAddress(); + } + bytes memory proverCreationCode = + abi.encodePacked(type(ChildToParentProver).creationCode, abi.encode(buffer, homeChainId)); + prover = _deploy(proverCreationCode, bytes32(0)); + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), prover); + } else { + _writeProver(_chainName(targetChainId), address(pointer), prover); + } + } +} diff --git a/scripts/deployment/provers/DeployZkSyncParentToChild.s.sol b/scripts/deployment/provers/DeployZkSyncParentToChild.s.sol new file mode 100644 index 0000000..6044a5c --- /dev/null +++ b/scripts/deployment/provers/DeployZkSyncParentToChild.s.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.30; + +import {DeployBase} from "../DeployBase.s.sol"; + +import {console} from "forge-std/console.sol"; +import {ParentToChildProver} from "src/contracts/provers/zksync/ParentToChildProver.sol"; +import {StateProverPointer} from "src/contracts/StateProverPointer.sol"; + +contract DeployZkSyncParentToChild is DeployBase { + function run() public { + address gatewayZkChain = vm.envAddress("GATEWAY_ZK_CHAIN"); + uint256 l2LogsRootHashSlot = vm.envUint("L2_LOGS_ROOT_HASH_SLOT"); + uint256 childChainId = vm.envUint("CHILD_CHAIN_ID"); + uint256 gatewayChainId = vm.envUint("GATEWAY_CHAIN_ID"); + address owner = vm.envAddress("OWNER"); + + uint256 homeChainId = vm.envUint("HOME_CHAIN_ID"); + uint256 targetChainId = vm.envUint("TARGET_CHAIN_ID"); + + address prover; + address pointer; + if (block.chainid == targetChainId) { + return; + } + vm.startBroadcast(); + if ( + (block.chainid == homeChainId && _isProverDeployed(_chainName(targetChainId))) + || (block.chainid != homeChainId && _isCopyDeployed(_chainName(homeChainId), _chainName(targetChainId))) + ) { + vm.stopBroadcast(); + console.log("Prover or copy already deployed on chain ", _chainName(block.chainid)); + return; + } + + bytes memory proverCreationCode = abi.encodePacked( + type(ParentToChildProver).creationCode, + abi.encode(gatewayZkChain, l2LogsRootHashSlot, childChainId, gatewayChainId, homeChainId) + ); + prover = _deploy(proverCreationCode, bytes32(0)); + + if (prover == address(0)) { + console.log("Failed to deploy prover on chain ", _chainName(block.chainid)); + vm.stopBroadcast(); + revert DeploymentFailed(); + } + + // Only deploy the pointer on the "canonical" chain, i.e., the chain where the pointer will be called from the receiver directly. + // The other prover deployments are copies. + if (block.chainid == homeChainId) { + bytes memory pointerCreationCode = + abi.encodePacked(type(StateProverPointer).creationCode, abi.encode(owner)); + pointer = _deploy(pointerCreationCode, bytes32(targetChainId)); + if (pointer != address(0)) { + if (StateProverPointer(pointer).implementationAddress() == address(0)) { + // This will only work if `msg.sender` is the owner of the pointer. + StateProverPointer(pointer).setImplementationAddress(address(prover)); + } + } + } + vm.stopBroadcast(); + + if (pointer == address(0)) { + // If the pointer is not deployed, it means that this is a copy of the prover deployed in a different chain. + _writeCopy(_chainName(homeChainId), _chainName(targetChainId), address(prover)); + } else { + _writeProver(_chainName(targetChainId), address(pointer), address(prover)); + } + } +} diff --git a/scripts/deployment/provers/deploy-child-provers.sh b/scripts/deployment/provers/deploy-child-provers.sh new file mode 100755 index 0000000..2cb11ec --- /dev/null +++ b/scripts/deployment/provers/deploy-child-provers.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +HOME_CHAIN_ID=$ARBITRUM_CHAIN_ID \ +TARGET_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +forge script scripts/deployment/provers/DeployArbitrumChildToParent.s.sol \ + --rpc-url "$ARBITRUM_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + +HOME_CHAIN_ID=$LINEA_CHAIN_ID \ +TARGET_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +forge script scripts/deployment/provers/DeployLineaChildToParent.s.sol \ + --rpc-url "$LINEA_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + +HOME_CHAIN_ID=$SCROLL_CHAIN_ID \ +TARGET_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +forge script scripts/deployment/provers/DeployScrollChildToParent.s.sol \ + --rpc-url "$SCROLL_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + +HOME_CHAIN_ID=$OPTIMISM_CHAIN_ID \ +TARGET_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +forge script scripts/deployment/provers/DeployOptimismChildToParent.s.sol \ + --rpc-url "$OPTIMISM_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + +HOME_CHAIN_ID=$ZKSYNC_CHAIN_ID \ +TARGET_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +forge script scripts/deployment/provers/DeployZkSyncChildToParent.s.sol \ + --rpc-url "$ZKSYNC_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast \ No newline at end of file diff --git a/scripts/deployment/provers/deploy-parent-provers.sh b/scripts/deployment/provers/deploy-parent-provers.sh new file mode 100755 index 0000000..e553ead --- /dev/null +++ b/scripts/deployment/provers/deploy-parent-provers.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +OUTBOX=$ARBITRUM_OUTBOX \ +ROOTS_SLOT=$ARBITRUM_ROOTS_SLOT \ +HOME_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +TARGET_CHAIN_ID=$ARBITRUM_CHAIN_ID \ +forge script scripts/deployment/provers/DeployArbitrumParentToChild.s.sol \ + --rpc-url "$RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + + +ROLLUP=$LINEA_ROLLUP \ +STATE_ROOT_HASHES_SLOT=$LINEA_STATE_ROOT_HASHES_SLOT \ +HOME_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +TARGET_CHAIN_ID=$LINEA_CHAIN_ID \ +forge script scripts/deployment/provers/DeployLineaParentToChild.s.sol \ + --rpc-url "$RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + + +SCROLL_CHAIN=$SCROLL_CHAIN_SEPOLIA \ +FINALIZED_STATE_ROOTS_SLOT=$SCROLL_FINALIZED_STATE_ROOT_SLOT \ +HOME_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +TARGET_CHAIN_ID=$SCROLL_CHAIN_ID \ +forge script scripts/deployment/provers/DeployScrollParentToChild.s.sol \ + --rpc-url "$RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + + +ANCHOR_STATE_REGISTRY=$OPTIMISM_ANCHOR_STATE_REGISTRY \ +ANCHOR_GAME_SLOT=$OPTIMISM_ANCHOR_GAME_SLOT \ +HOME_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +TARGET_CHAIN_ID=$OPTIMISM_CHAIN_ID \ +forge script scripts/deployment/provers/DeployOptimismParentToChild.s.sol \ + --rpc-url "$RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + +GATEWAY_ZK_CHAIN=$ZKSYNC_GATEWAY_ZK_CHAIN \ +L2_LOGS_ROOT_HASH_SLOT=$ZKSYNC_L2_LOGS_ROOT_HASH_SLOT \ +CHILD_CHAIN_ID=$ZKSYNC_CHAIN_ID \ +GATEWAY_CHAIN_ID=$ZKSYNC_GATEWAY_CHAIN_ID \ +HOME_CHAIN_ID=$ETHEREUM_CHAIN_ID \ +TARGET_CHAIN_ID=$ZKSYNC_CHAIN_ID \ +forge script scripts/deployment/provers/DeployZkSyncParentToChild.s.sol \ + --rpc-url "$RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast + + + + + + + + + + diff --git a/scripts/generate-optimism-test-payloads.ts b/scripts/generate-optimism-test-payloads.ts index f94cc25..9518280 100644 --- a/scripts/generate-optimism-test-payloads.ts +++ b/scripts/generate-optimism-test-payloads.ts @@ -16,7 +16,7 @@ import { OptimismChildToParentProverHelper } from '../src/ts/optimism/ChildToPar import fs from 'fs' import path from 'path' -const OPTIMISM_SEPOLIA_RPC = process.env.OPTIMISM_SEPOLIA_RPC_URL || 'https://sepolia.optimism.io' +const OPTIMISM_SEPOLIA_RPC = process.env.OPTIMISM_RPC_URL || 'https://sepolia.optimism.io' const SEPOLIA_RPC = process.env.ETHEREUM_RPC_URL || 'https://ethereum-sepolia-rpc.publicnode.com' async function main() { diff --git a/scripts/taiko/broadcast-l1.s.sol b/scripts/taiko/broadcast-l1.s.sol index e5302df..7e96e4e 100644 --- a/scripts/taiko/broadcast-l1.s.sol +++ b/scripts/taiko/broadcast-l1.s.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import { Script } from "forge-std/Script.sol"; -import { console } from "forge-std/console.sol"; -import { Broadcaster } from "../../src/contracts/Broadcaster.sol"; +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {Broadcaster} from "../../src/contracts/Broadcaster.sol"; /// @notice Broadcast a message on L1 (Taiko Parent Chain) /// @dev This script broadcasts a message using the Broadcaster contract on L1 @@ -11,7 +11,7 @@ contract BroadcastL1Message is Script { function run() public { address broadcasterAddress = vm.envAddress("L1_BROADCASTER"); bytes32 message = keccak256(abi.encodePacked("Message", block.timestamp, msg.sender)); - + vm.startBroadcast(); Broadcaster(broadcasterAddress).broadcastMessage(message); vm.stopBroadcast(); diff --git a/scripts/taiko/broadcast-l2.s.sol b/scripts/taiko/broadcast-l2.s.sol index d847f84..f09edd4 100644 --- a/scripts/taiko/broadcast-l2.s.sol +++ b/scripts/taiko/broadcast-l2.s.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import { Script } from "forge-std/Script.sol"; -import { console } from "forge-std/console.sol"; -import { Broadcaster } from "../../src/contracts/Broadcaster.sol"; +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {Broadcaster} from "../../src/contracts/Broadcaster.sol"; /// @notice Broadcast a message on L2 (Taiko Child Chain) /// @dev This script broadcasts a message using the Broadcaster contract on L2 @@ -11,7 +11,7 @@ contract BroadcastL2Message is Script { function run() public { address broadcasterAddress = vm.envAddress("L2_BROADCASTER"); bytes32 message = keccak256(abi.encodePacked("Message", block.timestamp, msg.sender)); - + vm.startBroadcast(); Broadcaster(broadcasterAddress).broadcastMessage(message); vm.stopBroadcast(); diff --git a/scripts/taiko/deploy-all.s.sol b/scripts/taiko/deploy-all.s.sol index a6d9725..12caea1 100644 --- a/scripts/taiko/deploy-all.s.sol +++ b/scripts/taiko/deploy-all.s.sol @@ -1,22 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import { Script } from "forge-std/Script.sol"; -import { console } from "forge-std/console.sol"; -import { Broadcaster } from "../../src/contracts/Broadcaster.sol"; -import { Receiver } from "../../src/contracts/Receiver.sol"; -import { StateProverPointer } from "../../src/contracts/StateProverPointer.sol"; +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {Broadcaster} from "../../src/contracts/Broadcaster.sol"; +import {Receiver} from "../../src/contracts/Receiver.sol"; +import {StateProverPointer} from "../../src/contracts/StateProverPointer.sol"; contract DeployAll is Script { function run() public { address owner = vm.envAddress("TAIKO_DEPLOYER_ADDRESS"); - + vm.startBroadcast(); - + Broadcaster broadcaster = new Broadcaster(); Receiver receiver = new Receiver(); StateProverPointer pointer = new StateProverPointer(owner); - + vm.stopBroadcast(); console.log("Broadcaster:", address(broadcaster)); diff --git a/scripts/taiko/provers-l2.s.sol b/scripts/taiko/provers-l2.s.sol index d3d54a2..083676a 100644 --- a/scripts/taiko/provers-l2.s.sol +++ b/scripts/taiko/provers-l2.s.sol @@ -1,10 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import { Script } from "forge-std/Script.sol"; -import { console } from "forge-std/console.sol"; -import { ChildToParentProver as TaikoChildToParentProver } from "../../src/contracts/provers/taiko/ChildToParentProver.sol"; -import { StateProverPointer } from "../../src/contracts/StateProverPointer.sol"; +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import { + ChildToParentProver as TaikoChildToParentProver +} from "../../src/contracts/provers/taiko/ChildToParentProver.sol"; +import {StateProverPointer} from "../../src/contracts/StateProverPointer.sol"; /// @notice Deploy ChildToParentProver on L2 (Taiko Child Chain) /// @dev This script deploys the prover that allows reading L1 state from L2 @@ -17,16 +19,13 @@ contract DeployL2Prover is Script { address owner = vm.envAddress("TAIKO_DEPLOYER_ADDRESS"); vm.startBroadcast(); - - TaikoChildToParentProver childToParentProver = new TaikoChildToParentProver( - signalServiceL2, - checkpointsSlot, - homeChainId - ); - + + TaikoChildToParentProver childToParentProver = + new TaikoChildToParentProver(signalServiceL2, checkpointsSlot, homeChainId); + StateProverPointer stateProverPointer = new StateProverPointer(owner); stateProverPointer.setImplementationAddress(address(childToParentProver)); - + vm.stopBroadcast(); console.log("ChildToParentProver:", address(childToParentProver)); diff --git a/scripts/taiko/provers.s.sol b/scripts/taiko/provers.s.sol index 48b8aa3..af4dfa3 100644 --- a/scripts/taiko/provers.s.sol +++ b/scripts/taiko/provers.s.sol @@ -1,10 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import { Script } from "forge-std/Script.sol"; -import { console } from "forge-std/console.sol"; -import { ParentToChildProver as TaikoParentToChildProver } from "../../src/contracts/provers/taiko/ParentToChildProver.sol"; -import { StateProverPointer } from "../../src/contracts/StateProverPointer.sol"; +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import { + ParentToChildProver as TaikoParentToChildProver +} from "../../src/contracts/provers/taiko/ParentToChildProver.sol"; +import {StateProverPointer} from "../../src/contracts/StateProverPointer.sol"; /// @notice Deploy ParentToChildProver on L1 (Ethereum/Taiko Parent Chain) /// @dev This script deploys the prover that allows reading L2 state from L1 @@ -17,19 +19,16 @@ contract DeployL1Prover is Script { address owner = vm.envAddress("TAIKO_DEPLOYER_ADDRESS"); vm.startBroadcast(); - - TaikoParentToChildProver parentToChildProver = new TaikoParentToChildProver( - signalServiceL1, - checkpointsSlot, - homeChainId - ); - + + TaikoParentToChildProver parentToChildProver = + new TaikoParentToChildProver(signalServiceL1, checkpointsSlot, homeChainId); + StateProverPointer stateProverPointer = new StateProverPointer(owner); stateProverPointer.setImplementationAddress(address(parentToChildProver)); - + vm.stopBroadcast(); console.log("ParentToChildProver:", address(parentToChildProver)); console.log("L1ProverPointer:", address(stateProverPointer)); } -} \ No newline at end of file +} diff --git a/scripts/taiko/verify-message.s.sol b/scripts/taiko/verify-message.s.sol index 4fe84af..fbb3dd3 100644 --- a/scripts/taiko/verify-message.s.sol +++ b/scripts/taiko/verify-message.s.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.27; -import { Script } from "forge-std/Script.sol"; -import { console } from "forge-std/console.sol"; -import { stdJson } from "forge-std/StdJson.sol"; -import { Receiver } from "../../src/contracts/Receiver.sol"; -import { IReceiver } from "../../src/contracts/interfaces/IReceiver.sol"; +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {stdJson} from "forge-std/StdJson.sol"; +import {Receiver} from "../../src/contracts/Receiver.sol"; +import {IReceiver} from "../../src/contracts/interfaces/IReceiver.sol"; contract VerifyMessage is Script { using stdJson for string; @@ -13,7 +13,7 @@ contract VerifyMessage is Script { function run() public view { address receiverAddress = vm.envAddress("L1_RECEIVER"); address proverPointerAddress = vm.envAddress("L1_PROVER_POINTER"); - + string memory path = "test/payloads/taiko/taikoProofL2.json"; string memory json = vm.readFile(path); @@ -32,12 +32,9 @@ contract VerifyMessage is Script { bytes[] memory scpInputs = new bytes[](1); scpInputs[0] = abi.encode(uint48(blockNumber)); - IReceiver.RemoteReadArgs memory remoteReadArgs = IReceiver.RemoteReadArgs({ - route: route, - scpInputs: scpInputs, - proof: storageProofInput - }); - + IReceiver.RemoteReadArgs memory remoteReadArgs = + IReceiver.RemoteReadArgs({route: route, scpInputs: scpInputs, proof: storageProofInput}); + bytes32 message = 0xd9222d7d84eefb8570069f30ab4a850423ba57a374c593b67a224c430f9736df; address publisher = 0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec; @@ -50,11 +47,8 @@ contract VerifyMessage is Script { console.logBytes32(message); console.log(""); - (bytes32 broadcasterId, uint256 timestamp) = Receiver(receiverAddress).verifyBroadcastMessage( - remoteReadArgs, - message, - publisher - ); + (bytes32 broadcasterId, uint256 timestamp) = + Receiver(receiverAddress).verifyBroadcastMessage(remoteReadArgs, message, publisher); console.log("=== Verification Success ==="); console.log("Broadcaster ID: ", vm.toString(broadcasterId)); @@ -62,6 +56,3 @@ contract VerifyMessage is Script { } } - - - diff --git a/scripts/taiko/verify-on-chain.s.sol b/scripts/taiko/verify-on-chain.s.sol index 1f26da4..5e57bac 100644 --- a/scripts/taiko/verify-on-chain.s.sol +++ b/scripts/taiko/verify-on-chain.s.sol @@ -60,18 +60,12 @@ contract VerifyOnChain is Script { bytes[] memory scpInputs = new bytes[](1); scpInputs[0] = abi.encode(uint48(blockNumber)); - IReceiver.RemoteReadArgs memory remoteReadArgs = IReceiver.RemoteReadArgs({ - route: route, - scpInputs: scpInputs, - proof: storageProofInput - }); + IReceiver.RemoteReadArgs memory remoteReadArgs = + IReceiver.RemoteReadArgs({route: route, scpInputs: scpInputs, proof: storageProofInput}); // Call the deployed Receiver contract - (bytes32 broadcasterId, uint256 timestamp) = IReceiver(getL2Receiver()).verifyBroadcastMessage( - remoteReadArgs, - message, - publisher - ); + (bytes32 broadcasterId, uint256 timestamp) = + IReceiver(getL2Receiver()).verifyBroadcastMessage(remoteReadArgs, message, publisher); console.log(""); console.log("=== VERIFICATION SUCCESSFUL ==="); @@ -112,18 +106,12 @@ contract VerifyOnChain is Script { bytes[] memory scpInputs = new bytes[](1); scpInputs[0] = abi.encode(uint48(blockNumber)); - IReceiver.RemoteReadArgs memory remoteReadArgs = IReceiver.RemoteReadArgs({ - route: route, - scpInputs: scpInputs, - proof: storageProofInput - }); + IReceiver.RemoteReadArgs memory remoteReadArgs = + IReceiver.RemoteReadArgs({route: route, scpInputs: scpInputs, proof: storageProofInput}); // Call the deployed Receiver contract - (bytes32 broadcasterId, uint256 timestamp) = IReceiver(getL1Receiver()).verifyBroadcastMessage( - remoteReadArgs, - message, - publisher - ); + (bytes32 broadcasterId, uint256 timestamp) = + IReceiver(getL1Receiver()).verifyBroadcastMessage(remoteReadArgs, message, publisher); console.log(""); console.log("=== VERIFICATION SUCCESSFUL ==="); diff --git a/snapshots/verifyBroadcastMessage.json b/snapshots/verifyBroadcastMessage.json index 9082634..4979f65 100644 --- a/snapshots/verifyBroadcastMessage.json +++ b/snapshots/verifyBroadcastMessage.json @@ -1,9 +1,9 @@ { - "EthereumToOptimism": "1642699", - "EthereumToTaikoL2": "1052266", - "LineaL2ToEthereum": "2551828", - "ScrollL2ToEthereum": "1361992", - "ScrollToOptimism": "1352078", - "TaikoL2ToEthereum": "1022329", - "ZkSyncL2ToEthereum": "125715" + "EthereumToOptimism": "541852", + "EthereumToTaikoL2": "334900", + "LineaL2ToEthereum": "2310786", + "ScrollL2ToEthereum": "459836", + "ScrollToOptimism": "453497", + "TaikoL2ToEthereum": "329078", + "ZkSyncL2ToEthereum": "49117" } \ No newline at end of file