diff --git a/.dockerignore b/.dockerignore index 11e5eb817c5ab..816dd7f411fa1 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,13 +1,44 @@ -.github -.vscode +# All the files we depend on. We are using a negative pattern to not include anything by accident. +# node_modules, packages (contains git submodules and node modules etc.), devnet dirs etc. all add up a lot. +* -.env -.envrc -**/.env +# Include contracts +!/packages/contracts-bedrock +# Exclude generated files and node modules from contracts +/packages/contracts-bedrock/forge-artifacts +/packages/contracts-bedrock/artifacts +/packages/contracts-bedrock/cache +/packages/contracts-bedrock/broadcast + +!/cannon +!/devnet-sdk +!/op-batcher +!/op-chain-ops +!/op-deployer +!/op-dripper +!/op-challenger +!/op-dispute-mon +!/op-conductor +!/op-node +!/op-preimage +!/op-program +!/op-proposer +!/op-service +!/op-supervisor +!/op-test-sequencer +!/op-wheel +!/op-alt-da +!/op-faucet +!/op-interop-mon +!/go.mod +!/go.sum +!/justfiles +!/mise.toml +!/op-e2e/e2eutils +!/op-geth +!Makefile -test -**/*_test.go -build/_workspace -build/bin -build/_bin -tests/testdata +**/bin +**/testdata +**/tests +.env diff --git a/.gitignore b/.gitignore index 7f698c034346a..ad9f6a8adfc53 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,5 @@ test/tmp test-apollo/l1-geth test-apollo/config-op test-apollo/data + +test-pp-op/testnet.env diff --git a/.gitmodules b/.gitmodules index 7201ea94539f7..8374b81f69e4c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,4 +35,4 @@ [submodule "op-geth"] path = op-geth url = https://github.com/okx/op-geth - branch = sync/optimism + branch = dev diff --git a/Dockerfile-contracts b/Dockerfile-contracts index 659fc520bfb5b..c8ff77aa3541e 100644 --- a/Dockerfile-contracts +++ b/Dockerfile-contracts @@ -24,7 +24,7 @@ WORKDIR /app/packages/contracts-bedrock RUN git submodule update --init --recursive || echo "No submodules found" RUN --mount=type=cache,target=/root/.foundry \ --mount=type=cache,target=/root/.cache \ - forge build + forge build --skip "/**/test/**" # Build op-deployer WORKDIR /app @@ -42,6 +42,13 @@ RUN --mount=type=cache,target=/root/.cache \ FROM debian:bookworm-slim WORKDIR /app +# Update certificates +RUN apt-get update && apt-get install -y ca-certificates && update-ca-certificates + +# Set environment variables for Go +ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt +ENV SSL_CERT_DIR=/etc/ssl/certs + # Copy foundry tools for runtime use COPY --from=contracts-builder /usr/local/bin/forge /usr/local/bin/cast /usr/local/bin/anvil /usr/local/bin/ diff --git a/Dockerfile-opstack b/Dockerfile-opstack index a545475cb0731..541cd0bbb23b1 100644 --- a/Dockerfile-opstack +++ b/Dockerfile-opstack @@ -40,10 +40,10 @@ COPY . . RUN --mount=type=cache,target=/root/.cache \ --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg/mod \ - make build-go + make build-go-no-submodules # Copy foundry tools and artifacts from contracts image -COPY --from=op-contracts:v1.13.4 /usr/local/bin/forge /usr/local/bin/cast /usr/local/bin/anvil /usr/local/bin/ +COPY --from=op-contracts:latest /usr/local/bin/forge /usr/local/bin/cast /usr/local/bin/anvil /usr/local/bin/ # Verify installations RUN echo "๐Ÿ” Verifying installations:" && \ diff --git a/Makefile b/Makefile index 57c2ebf26684c..e0836e966ba1e 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,9 @@ build: build-go build-contracts ## Builds Go components and contracts-bedrock build-go: submodules op-node op-proposer op-batcher op-challenger op-dispute-mon op-program cannon withdrawal op-conductor ## Builds main Go components .PHONY: build-go +build-go-no-submodules: op-node op-proposer op-batcher op-challenger op-dispute-mon op-program cannon withdrawal op-conductor ## Used in Dockerfile +.PHONY: build-go-no-submodules + build-contracts: (cd packages/contracts-bedrock && just build) .PHONY: build-contracts diff --git a/op-deployer/pkg/deployer/bootstrap/implementations.go b/op-deployer/pkg/deployer/bootstrap/implementations.go index 13e577407302e..f6e6d17e17254 100644 --- a/op-deployer/pkg/deployer/bootstrap/implementations.go +++ b/op-deployer/pkg/deployer/bootstrap/implementations.go @@ -94,7 +94,7 @@ func (c *ImplementationsConfig) Check() error { return errors.New("dispute game finality delay in seconds must be specified") } // Check V2 fault game parameters only if V2 dispute games feature is enabled - deployV2Games := deployer.IsDevFeatureEnabled(c.DevFeatureBitmap, deployer.DeployV2DisputeGames) + deployV2Games := deployer.IsDevFeatureEnabled(c.DevFeatureBitmap, deployer.DeployV2DisputeGamesDevFlag) if deployV2Games { if c.FaultGameMaxGameDepth == 0 { return errors.New("fault game max game depth must be specified when V2 dispute games feature is enabled") diff --git a/op-deployer/pkg/deployer/devfeatures.go b/op-deployer/pkg/deployer/devfeatures.go index 3a9d831428a71..241c9a52d28b2 100644 --- a/op-deployer/pkg/deployer/devfeatures.go +++ b/op-deployer/pkg/deployer/devfeatures.go @@ -15,8 +15,8 @@ var ( // CannonKonaDevFlag enables Kona as the default cannon prover. CannonKonaDevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000010") - // DeployV2DisputeGames enables deployment of V2 dispute game contracts. - DeployV2DisputeGames = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000100") + // DeployV2DisputeGamesDevFlag enables deployment of V2 dispute game contracts. + DeployV2DisputeGamesDevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000100") // CustomGasToken enables the custom gas token. CustomGasToken = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000001000") diff --git a/op-devstack/presets/disputegame_v2.go b/op-devstack/presets/disputegame_v2.go index ab450305f03b0..a47a1cf088b9d 100644 --- a/op-devstack/presets/disputegame_v2.go +++ b/op-devstack/presets/disputegame_v2.go @@ -7,5 +7,5 @@ import ( ) func WithDisputeGameV2() stack.CommonOption { - return stack.MakeCommon(sysgo.WithDeployerOptions(sysgo.WithDevFeatureBitmap(deployer.DeployV2DisputeGames))) + return stack.MakeCommon(sysgo.WithDeployerOptions(sysgo.WithDevFeatureBitmap(deployer.DeployV2DisputeGamesDevFlag))) } diff --git a/op-geth b/op-geth index b23a70873300b..a901f53157345 160000 --- a/op-geth +++ b/op-geth @@ -1 +1 @@ -Subproject commit b23a70873300b57816b783601c2bf0e3c00b94a2 +Subproject commit a901f53157345ffa9c4b97a11696a1edb283092a diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 12d9cb5f206ad..9068e96e130ba 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -63,6 +63,7 @@ fs_permissions = [ { access='read-write', path='./.testdata/' }, { access='read', path='./kout-deployment' }, { access='read', path='./test/fixtures' }, + { access='read', path='../../test/config-op/' }, { access='read', path='./lib/superchain-registry/superchain/configs/' }, { access='read', path='./lib/superchain-registry/validation/standard/' }, ] diff --git a/packages/contracts-bedrock/interfaces/L1/IOKB.sol b/packages/contracts-bedrock/interfaces/L1/IOKB.sol new file mode 100644 index 0000000000000..ab545c22411d7 --- /dev/null +++ b/packages/contracts-bedrock/interfaces/L1/IOKB.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +interface IOKB is IERC20, IERC20Metadata { + function triggerBridge() external; +} diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol index 849249ab269d6..45fcf739ebd65 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol @@ -34,6 +34,8 @@ interface IOptimismPortal2 is IProxyAdminOwnedBase { error OptimismPortal_ProofNotOldEnough(); error OptimismPortal_Unproven(); error OptimismPortal_InvalidLockboxState(); + error OptimismPortal_OnlyCustomGasToken(); + error OptimismPortal_InvalidGasToken(); error OutOfGas(); error UnexpectedList(); error UnexpectedString(); @@ -49,6 +51,15 @@ interface IOptimismPortal2 is IProxyAdminOwnedBase { function anchorStateRegistry() external view returns (IAnchorStateRegistry); function ethLockbox() external view returns (IETHLockbox); function checkWithdrawal(bytes32 _withdrawalHash, address _proofSubmitter) external view; + function depositERC20Transaction( + address _to, + uint256 _mint, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + external; function depositTransaction( address _to, uint256 _value, diff --git a/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol b/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol index bc45b690ff846..132586ffdb3eb 100644 --- a/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol +++ b/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol @@ -99,6 +99,10 @@ interface ISystemConfig is IProxyAdminOwnedBase { function setFeature(bytes32 _feature, bool _enabled) external; function isFeatureEnabled(bytes32) external view returns (bool); function isCustomGasToken() external view returns (bool); + function gasPayingToken() external view returns (address address_, uint8 decimals_); + function gasPayingTokenName() external view returns (string memory name_); + function gasPayingTokenSymbol() external view returns (string memory symbol_); + function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; function __constructor__() external; } diff --git a/packages/contracts-bedrock/scripts/DeployMockOKB.s.sol b/packages/contracts-bedrock/scripts/DeployMockOKB.s.sol new file mode 100644 index 0000000000000..8a5613844005a --- /dev/null +++ b/packages/contracts-bedrock/scripts/DeployMockOKB.s.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Script } from "forge-std/Script.sol"; +import { console2 as console } from "forge-std/console2.sol"; + +// Contracts +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20Burnable } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; + +/// @title MockOKB +/// @notice Mock OKB token for testing custom gas token setup +contract MockOKB is ERC20, ERC20Burnable { + constructor() ERC20("Mock OKB", "OKB") { + _mint(msg.sender, 660000 * 10 ** decimals()); + } + + function decimals() public pure override returns (uint8) { + return 18; + } + + /// @notice Burn all tokens of msg.sender + function triggerBridge() external { + _burn(msg.sender, balanceOf(msg.sender)); + } +} + +/// @title DeployMockOKB +/// @notice Foundry script to deploy MockOKB token for testing +/// @dev This script deploys a mock OKB token with 660,000 initial supply +contract DeployMockOKB is Script { + // Deployed contract + MockOKB okbToken; + address deployerAddress; + + function setUp() public { + // Get deployer address from msg.sender (set by forge script --private-key) + deployerAddress = msg.sender; + console.log("Deployer address:", deployerAddress); + } + + function run() public { + console.log("\n=== Deploying Mock OKB Token ===\n"); + + vm.startBroadcast(msg.sender); + + // Deploy Mock OKB Token + deployMockOKB(); + + vm.stopBroadcast(); + + // Print deployment summary + printDeploymentSummary(); + } + + /// @notice Deploy mock OKB token with 660,000 supply + function deployMockOKB() internal { + okbToken = new MockOKB(); + console.log("MockOKB deployed at:", address(okbToken)); + } + + /// @notice Print deployment summary with token details + function printDeploymentSummary() internal view { + console.log("\n=== Deployment Summary ==="); + console.log("MockOKB Address:", address(okbToken)); + console.log("Token name:", okbToken.name()); + console.log("Token symbol:", okbToken.symbol()); + console.log("Token decimals:", okbToken.decimals()); + console.log("Total supply:", okbToken.totalSupply() / 1e18, "OKB"); + console.log("Deployer balance:", okbToken.balanceOf(deployerAddress) / 1e18, "OKB"); + console.log("\nEnvironment variable to set:"); + console.log("export OKB_TOKEN_ADDRESS=", address(okbToken)); + } +} diff --git a/packages/contracts-bedrock/scripts/SetupCustomGasToken.s.sol b/packages/contracts-bedrock/scripts/SetupCustomGasToken.s.sol new file mode 100644 index 0000000000000..b7f57f9b1aef8 --- /dev/null +++ b/packages/contracts-bedrock/scripts/SetupCustomGasToken.s.sol @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Script } from "forge-std/Script.sol"; +import { console2 as console } from "forge-std/console2.sol"; +import { stdJson } from "forge-std/StdJson.sol"; + +// Contracts + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { DepositedOKBAdapter } from "src/L1/DepositedOKBAdapter.sol"; + +// Interfaces +import { IOKB } from "interfaces/L1/IOKB.sol"; +import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; +import { Constants } from "src/libraries/Constants.sol"; +import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; +import { IL1Block } from "interfaces/L2/IL1Block.sol"; + +// Libraries +import { Features } from "src/libraries/Features.sol"; +import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; +import { LibString } from "@solady/utils/LibString.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; + +/// @title SetupCustomGasToken +/// @notice Foundry script to set up and verify custom gas token configuration +/// @dev This script: +/// 1. Reads OKB token address from environment variable +/// 2. Deploys DepositedOKBAdapter that handles OKB burning internally +/// 3. Adds deployer address to whitelist for deposits +/// 4. Sets gas paying token in SystemConfig storage +/// 5. Verifies all configurations on L1 +contract SetupCustomGasToken is Script { + using stdJson for string; + + // Addresses to be loaded from deployment artifacts + address systemConfigProxy; + address optimismPortalProxy; + address deployerAddress; + address okbTokenAddress; + + // Deployed contracts + IOKB okbToken; + DepositedOKBAdapter adapter; + + function setUp() public { + // Get deployer address from msg.sender (set by forge script --private-key) + deployerAddress = msg.sender; + console.log("Deployer address:", deployerAddress); + + // Parse addresses from environment variables + systemConfigProxy = vm.envAddress("SYSTEM_CONFIG_PROXY_ADDRESS"); + optimismPortalProxy = vm.envAddress("OPTIMISM_PORTAL_PROXY_ADDRESS"); + okbTokenAddress = vm.envAddress("OKB_TOKEN_ADDRESS"); + + console.log("SystemConfig Proxy:", systemConfigProxy); + console.log("OptimismPortal Proxy:", optimismPortalProxy); + console.log("OKB Token Address:", okbTokenAddress); + + // Initialize OKB token interface + okbToken = IOKB(okbTokenAddress); + } + + function run() public { + console.log("\n=== Starting Custom Gas Token Setup ===\n"); + + preCheck(); + + vm.startBroadcast(msg.sender); + + deployAdapter(); + + setupWhitelist(); + + setGasPayingToken(); + + vm.stopBroadcast(); + + postCheck(); + } + + /// @notice Pre-check L1 Configuration + function preCheck() internal view { + console.log("Pre-check L1 Configuration...\n"); + ISystemConfig systemConfig = ISystemConfig(systemConfigProxy); + bool isCustomGasToken = systemConfig.isCustomGasToken(); + require(isCustomGasToken, "FAILED: SystemConfig custom gas token not enabled"); + + (address tokenAddr, uint8 decimals) = systemConfig.gasPayingToken(); + string memory name = systemConfig.gasPayingTokenName(); + string memory symbol = systemConfig.gasPayingTokenSymbol(); + console.log("SystemConfig.gasPayingToken():"); + console.log(" Address:", tokenAddr); + console.log(" Decimals:", decimals); + console.log(" Name:", name); + console.log(" Symbol:", symbol); + require(tokenAddr == Constants.ETHER, "FAILED: GasPayingToken already set"); + } + + /// @notice Set up whitelist for authorized depositors + function setupWhitelist() internal { + console.log(" Adding deployer to whitelist..."); + address[] memory addresses = new address[](1); + addresses[0] = deployerAddress; + adapter.addToWhitelistBatch(addresses); + console.log(" Deployer whitelisted successfully:", deployerAddress); + } + + /// @notice Deploy DepositedOKBAdapter + function deployAdapter() internal { + adapter = new DepositedOKBAdapter(okbTokenAddress, payable(optimismPortalProxy), deployerAddress); + console.log(" DepositedOKBAdapter deployed at:", address(adapter)); + } + + /// @notice Set gas paying token in SystemConfig storage + /// @dev This writes to the GasPayingToken storage slots directly + function setGasPayingToken() internal { + ISystemConfig systemConfig = ISystemConfig(systemConfigProxy); + // adapter is the gas paying token + // Convert string to bytes32 for SystemConfig function + bytes32 nameBytes32 = bytes32(bytes(okbToken.name())); + bytes32 symbolBytes32 = bytes32(bytes(okbToken.symbol())); + systemConfig.setGasPayingToken(address(adapter), okbToken.decimals(), nameBytes32, symbolBytes32); + } + + /// @notice Post-check L1 configuration + function postCheck() internal view { + console.log("\nPost-check L1 Configuration...\n"); + + ISystemConfig systemConfig = ISystemConfig(systemConfigProxy); + // Check SystemConfig gasPayingToken + (address tokenAddr, uint8 decimals) = systemConfig.gasPayingToken(); + string memory name = systemConfig.gasPayingTokenName(); + string memory symbol = systemConfig.gasPayingTokenSymbol(); + console.log("SystemConfig.gasPayingToken():"); + console.log(" Address:", tokenAddr); + console.log(" Decimals:", decimals); + console.log(" Name:", name); + console.log(" Symbol:", symbol); + require(tokenAddr == address(adapter), "FAILED: Token address mismatch"); + require(decimals == okbToken.decimals(), "FAILED: Token decimals mismatch"); + require( + keccak256(abi.encodePacked(name)) == keccak256(abi.encodePacked(okbToken.name())), + "FAILED: Token name mismatch" + ); + require( + keccak256(abi.encodePacked(symbol)) == keccak256(abi.encodePacked(okbToken.symbol())), + "FAILED: Token symbol mismatch" + ); + + // Check DepositedOKBAdapter configuration + require(address(adapter.OKB()) == okbTokenAddress, "FAILED: Adapter OKB mismatch"); + require(address(adapter.PORTAL()) == optimismPortalProxy, "FAILED: Adapter portal mismatch"); + require(adapter.owner() == deployerAddress, "FAILED: Adapter owner mismatch"); + + // Check adapter has preminted total supply + uint256 adapterBalance = adapter.balanceOf(address(adapter)); + uint256 expectedBalance = okbToken.totalSupply(); + console.log(" [CHECK 6] Adapter balance:", adapterBalance); + console.log(" [CHECK 6] Expected balance (OKB total supply):", expectedBalance); + require(adapterBalance == expectedBalance, "FAILED: Adapter balance should equal OKB total supply"); + + // Check whitelist configuration + console.log(" [CHECK 7] Verifying deployer whitelist..."); + require(adapter.whitelist(deployerAddress), "FAILED: Deployer address not whitelisted"); + console.log(" [CHECK 7] Deployer whitelist verified:", deployerAddress); + + // Check Adapter approval to portal (should be zero initially) + uint256 allowance = adapter.allowance(address(adapter), optimismPortalProxy); + console.log(" [CHECK 8] Adapter approval to Portal:", allowance); + require(allowance == 0, "FAILED: Adapter should not pre-approve portal"); + } +} diff --git a/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol index 51b5294019697..6220c7542c817 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol @@ -3,11 +3,8 @@ pragma solidity 0.8.15; import { Script } from "forge-std/Script.sol"; -import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; - import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; import { Solarray } from "scripts/libraries/Solarray.sol"; -import { BaseDeployIO } from "scripts/deploy/BaseDeployIO.sol"; import { ChainAssertions } from "scripts/deploy/ChainAssertions.sol"; import { Constants as ScriptConstants } from "scripts/libraries/Constants.sol"; @@ -21,7 +18,6 @@ import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol" import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol"; -import { Claim, Duration, GameType } from "src/dispute/lib/Types.sol"; import { IOptimismPortal2 as IOptimismPortal } from "interfaces/L1/IOptimismPortal2.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; @@ -31,335 +27,6 @@ import { IL1StandardBridge } from "interfaces/L1/IL1StandardBridge.sol"; import { IOptimismMintableERC20Factory } from "interfaces/universal/IOptimismMintableERC20Factory.sol"; import { IETHLockbox } from "interfaces/L1/IETHLockbox.sol"; -contract DeployOPChainInput is BaseDeployIO { - address internal _opChainProxyAdminOwner; - address internal _systemConfigOwner; - address internal _batcher; - address internal _unsafeBlockSigner; - address internal _proposer; - address internal _challenger; - - // TODO Add fault proofs inputs in a future PR. - uint32 internal _basefeeScalar; - uint32 internal _blobBaseFeeScalar; - uint256 internal _l2ChainId; - IOPContractsManager internal _opcm; - string internal _saltMixer; - uint64 internal _gasLimit; - - // Configurable dispute game inputs - GameType internal _disputeGameType; - Claim internal _disputeAbsolutePrestate; - uint256 internal _disputeMaxGameDepth; - uint256 internal _disputeSplitDepth; - Duration internal _disputeClockExtension; - Duration internal _disputeMaxClockDuration; - bool internal _allowCustomDisputeParameters; - - uint32 internal _operatorFeeScalar; - uint64 internal _operatorFeeConstant; - - function set(bytes4 _sel, address _addr) public { - require(_addr != address(0), "DeployOPChainInput: cannot set zero address"); - if (_sel == this.opChainProxyAdminOwner.selector) _opChainProxyAdminOwner = _addr; - else if (_sel == this.systemConfigOwner.selector) _systemConfigOwner = _addr; - else if (_sel == this.batcher.selector) _batcher = _addr; - else if (_sel == this.unsafeBlockSigner.selector) _unsafeBlockSigner = _addr; - else if (_sel == this.proposer.selector) _proposer = _addr; - else if (_sel == this.challenger.selector) _challenger = _addr; - else if (_sel == this.opcm.selector) _opcm = IOPContractsManager(_addr); - else revert("DeployOPChainInput: unknown selector"); - } - - function set(bytes4 _sel, uint256 _value) public { - if (_sel == this.basefeeScalar.selector) { - _basefeeScalar = SafeCast.toUint32(_value); - } else if (_sel == this.blobBaseFeeScalar.selector) { - _blobBaseFeeScalar = SafeCast.toUint32(_value); - } else if (_sel == this.l2ChainId.selector) { - require(_value != 0 && _value != block.chainid, "DeployOPChainInput: invalid l2ChainId"); - _l2ChainId = _value; - } else if (_sel == this.gasLimit.selector) { - _gasLimit = SafeCast.toUint64(_value); - } else if (_sel == this.disputeGameType.selector) { - _disputeGameType = GameType.wrap(SafeCast.toUint32(_value)); - } else if (_sel == this.disputeMaxGameDepth.selector) { - _disputeMaxGameDepth = SafeCast.toUint64(_value); - } else if (_sel == this.disputeSplitDepth.selector) { - _disputeSplitDepth = SafeCast.toUint64(_value); - } else if (_sel == this.disputeClockExtension.selector) { - _disputeClockExtension = Duration.wrap(SafeCast.toUint64(_value)); - } else if (_sel == this.disputeMaxClockDuration.selector) { - _disputeMaxClockDuration = Duration.wrap(SafeCast.toUint64(_value)); - } else if (_sel == this.operatorFeeScalar.selector) { - _operatorFeeScalar = SafeCast.toUint32(_value); - } else if (_sel == this.operatorFeeConstant.selector) { - _operatorFeeConstant = SafeCast.toUint64(_value); - } else { - revert("DeployOPChainInput: unknown selector"); - } - } - - function set(bytes4 _sel, string memory _value) public { - require((bytes(_value).length != 0), "DeployImplementationsInput: cannot set empty string"); - if (_sel == this.saltMixer.selector) _saltMixer = _value; - else revert("DeployOPChainInput: unknown selector"); - } - - function set(bytes4 _sel, bytes32 _value) public { - if (_sel == this.disputeAbsolutePrestate.selector) { - _disputeAbsolutePrestate = Claim.wrap(_value); - } else { - revert("DeployOPChainInput: unknown selector"); - } - } - - function set(bytes4 _sel, bool _value) public { - if (_sel == this.allowCustomDisputeParameters.selector) { - _allowCustomDisputeParameters = _value; - } else { - revert("DeployOPChainInput: unknown selector"); - } - } - - function opChainProxyAdminOwner() public view returns (address) { - require(_opChainProxyAdminOwner != address(0), "DeployOPChainInput: not set"); - return _opChainProxyAdminOwner; - } - - function systemConfigOwner() public view returns (address) { - require(_systemConfigOwner != address(0), "DeployOPChainInput: not set"); - return _systemConfigOwner; - } - - function batcher() public view returns (address) { - require(_batcher != address(0), "DeployOPChainInput: not set"); - return _batcher; - } - - function unsafeBlockSigner() public view returns (address) { - require(_unsafeBlockSigner != address(0), "DeployOPChainInput: not set"); - return _unsafeBlockSigner; - } - - function proposer() public view returns (address) { - require(_proposer != address(0), "DeployOPChainInput: not set"); - return _proposer; - } - - function challenger() public view returns (address) { - require(_challenger != address(0), "DeployOPChainInput: not set"); - return _challenger; - } - - function basefeeScalar() public view returns (uint32) { - require(_basefeeScalar != 0, "DeployOPChainInput: not set"); - return _basefeeScalar; - } - - function blobBaseFeeScalar() public view returns (uint32) { - require(_blobBaseFeeScalar != 0, "DeployOPChainInput: not set"); - return _blobBaseFeeScalar; - } - - function l2ChainId() public view returns (uint256) { - require(_l2ChainId != 0, "DeployOPChainInput: not set"); - require(_l2ChainId != block.chainid, "DeployOPChainInput: invalid l2ChainId"); - return _l2ChainId; - } - - function startingAnchorRoot() public pure returns (bytes memory) { - // WARNING: For now always hardcode the starting permissioned game anchor root to 0xdead, - // and we do not set anything for the permissioned game. This is because we currently only - // support deploying straight to permissioned games, and the starting root does not - // matter for that, as long as it is non-zero, since no games will be played. We do not - // deploy the permissionless game (and therefore do not set a starting root for it here) - // because to to update to the permissionless game, we will need to update its starting - // anchor root and deploy a new permissioned dispute game contract anyway. - // - // You can `console.logBytes(abi.encode(ScriptConstants.DEFAULT_OUTPUT_ROOT()))` to get the bytes that - // are hardcoded into `op-chain-ops/deployer/opcm/opchain.go` - - return abi.encode(ScriptConstants.DEFAULT_OUTPUT_ROOT()); - } - - function opcm() public view returns (IOPContractsManager) { - require(address(_opcm) != address(0), "DeployOPChainInput: not set"); - DeployUtils.assertValidContractAddress(address(_opcm)); - return _opcm; - } - - function saltMixer() public view returns (string memory) { - return _saltMixer; - } - - function gasLimit() public view returns (uint64) { - return _gasLimit; - } - - function disputeGameType() public view returns (GameType) { - return _disputeGameType; - } - - function disputeAbsolutePrestate() public view returns (Claim) { - return _disputeAbsolutePrestate; - } - - function disputeMaxGameDepth() public view returns (uint256) { - return _disputeMaxGameDepth; - } - - function disputeSplitDepth() public view returns (uint256) { - return _disputeSplitDepth; - } - - function disputeClockExtension() public view returns (Duration) { - return _disputeClockExtension; - } - - function disputeMaxClockDuration() public view returns (Duration) { - return _disputeMaxClockDuration; - } - - function allowCustomDisputeParameters() public view returns (bool) { - return _allowCustomDisputeParameters; - } - - function operatorFeeScalar() public view returns (uint32) { - return _operatorFeeScalar; - } - - function operatorFeeConstant() public view returns (uint64) { - return _operatorFeeConstant; - } -} - -contract DeployOPChainOutput is BaseDeployIO { - IProxyAdmin internal _opChainProxyAdmin; - IAddressManager internal _addressManager; - IL1ERC721Bridge internal _l1ERC721BridgeProxy; - ISystemConfig internal _systemConfigProxy; - IOptimismMintableERC20Factory internal _optimismMintableERC20FactoryProxy; - IL1StandardBridge internal _l1StandardBridgeProxy; - IL1CrossDomainMessenger internal _l1CrossDomainMessengerProxy; - IOptimismPortal internal _optimismPortalProxy; - IETHLockbox internal _ethLockboxProxy; - IDisputeGameFactory internal _disputeGameFactoryProxy; - IAnchorStateRegistry internal _anchorStateRegistryProxy; - IFaultDisputeGame internal _faultDisputeGame; - IPermissionedDisputeGame internal _permissionedDisputeGame; - IDelayedWETH internal _delayedWETHPermissionedGameProxy; - IDelayedWETH internal _delayedWETHPermissionlessGameProxy; - - function set(bytes4 _sel, address _addr) public virtual { - require(_addr != address(0), "DeployOPChainOutput: cannot set zero address"); - // forgefmt: disable-start - if (_sel == this.opChainProxyAdmin.selector) _opChainProxyAdmin = IProxyAdmin(_addr) ; - else if (_sel == this.addressManager.selector) _addressManager = IAddressManager(_addr) ; - else if (_sel == this.l1ERC721BridgeProxy.selector) _l1ERC721BridgeProxy = IL1ERC721Bridge(_addr) ; - else if (_sel == this.systemConfigProxy.selector) _systemConfigProxy = ISystemConfig(_addr) ; - else if (_sel == this.optimismMintableERC20FactoryProxy.selector) _optimismMintableERC20FactoryProxy = IOptimismMintableERC20Factory(_addr) ; - else if (_sel == this.l1StandardBridgeProxy.selector) _l1StandardBridgeProxy = IL1StandardBridge(payable(_addr)) ; - else if (_sel == this.l1CrossDomainMessengerProxy.selector) _l1CrossDomainMessengerProxy = IL1CrossDomainMessenger(_addr) ; - else if (_sel == this.optimismPortalProxy.selector) _optimismPortalProxy = IOptimismPortal(payable(_addr)) ; - else if (_sel == this.ethLockboxProxy.selector) _ethLockboxProxy = IETHLockbox(payable(_addr)) ; - else if (_sel == this.disputeGameFactoryProxy.selector) _disputeGameFactoryProxy = IDisputeGameFactory(_addr) ; - else if (_sel == this.anchorStateRegistryProxy.selector) _anchorStateRegistryProxy = IAnchorStateRegistry(_addr) ; - else if (_sel == this.faultDisputeGame.selector) _faultDisputeGame = IFaultDisputeGame(_addr) ; - else if (_sel == this.permissionedDisputeGame.selector) _permissionedDisputeGame = IPermissionedDisputeGame(_addr) ; - else if (_sel == this.delayedWETHPermissionedGameProxy.selector) _delayedWETHPermissionedGameProxy = IDelayedWETH(payable(_addr)) ; - else if (_sel == this.delayedWETHPermissionlessGameProxy.selector) _delayedWETHPermissionlessGameProxy = IDelayedWETH(payable(_addr)) ; - else revert("DeployOPChainOutput: unknown selector"); - // forgefmt: disable-end - } - - function opChainProxyAdmin() public view returns (IProxyAdmin) { - DeployUtils.assertValidContractAddress(address(_opChainProxyAdmin)); - return _opChainProxyAdmin; - } - - function addressManager() public view returns (IAddressManager) { - DeployUtils.assertValidContractAddress(address(_addressManager)); - return _addressManager; - } - - function l1ERC721BridgeProxy() public returns (IL1ERC721Bridge) { - DeployUtils.assertValidContractAddress(address(_l1ERC721BridgeProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_l1ERC721BridgeProxy)); - return _l1ERC721BridgeProxy; - } - - function systemConfigProxy() public returns (ISystemConfig) { - DeployUtils.assertValidContractAddress(address(_systemConfigProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_systemConfigProxy)); - return _systemConfigProxy; - } - - function optimismMintableERC20FactoryProxy() public returns (IOptimismMintableERC20Factory) { - DeployUtils.assertValidContractAddress(address(_optimismMintableERC20FactoryProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_optimismMintableERC20FactoryProxy)); - return _optimismMintableERC20FactoryProxy; - } - - function l1StandardBridgeProxy() public returns (IL1StandardBridge) { - DeployUtils.assertValidContractAddress(address(_l1StandardBridgeProxy)); - DeployUtils.assertL1ChugSplashImplementationSet(address(_l1StandardBridgeProxy)); - return _l1StandardBridgeProxy; - } - - function l1CrossDomainMessengerProxy() public view returns (IL1CrossDomainMessenger) { - DeployUtils.assertValidContractAddress(address(_l1CrossDomainMessengerProxy)); - DeployUtils.assertResolvedDelegateProxyImplementationSet("OVM_L1CrossDomainMessenger", addressManager()); - return _l1CrossDomainMessengerProxy; - } - - function optimismPortalProxy() public returns (IOptimismPortal) { - DeployUtils.assertValidContractAddress(address(_optimismPortalProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_optimismPortalProxy)); - return _optimismPortalProxy; - } - - function ethLockboxProxy() public returns (IETHLockbox) { - DeployUtils.assertValidContractAddress(address(_ethLockboxProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_ethLockboxProxy)); - return _ethLockboxProxy; - } - - function disputeGameFactoryProxy() public returns (IDisputeGameFactory) { - DeployUtils.assertValidContractAddress(address(_disputeGameFactoryProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_disputeGameFactoryProxy)); - return _disputeGameFactoryProxy; - } - - function anchorStateRegistryProxy() public returns (IAnchorStateRegistry) { - DeployUtils.assertValidContractAddress(address(_anchorStateRegistryProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_anchorStateRegistryProxy)); - return _anchorStateRegistryProxy; - } - - function faultDisputeGame() public view returns (IFaultDisputeGame) { - DeployUtils.assertValidContractAddress(address(_faultDisputeGame)); - return _faultDisputeGame; - } - - function permissionedDisputeGame() public view returns (IPermissionedDisputeGame) { - DeployUtils.assertValidContractAddress(address(_permissionedDisputeGame)); - return _permissionedDisputeGame; - } - - function delayedWETHPermissionedGameProxy() public returns (IDelayedWETH) { - DeployUtils.assertValidContractAddress(address(_delayedWETHPermissionedGameProxy)); - DeployUtils.assertERC1967ImplementationSet(address(_delayedWETHPermissionedGameProxy)); - return _delayedWETHPermissionedGameProxy; - } - - function delayedWETHPermissionlessGameProxy() public view returns (IDelayedWETH) { - // TODO: Eventually switch from Permissioned to Permissionless. Add this check back in. - // DeployUtils.assertValidContractAddress(address(_delayedWETHPermissionlessGameProxy)); - return _delayedWETHPermissionlessGameProxy; - } -} - contract DeployOPChain is Script { struct Output { IProxyAdmin opChainProxyAdmin; diff --git a/packages/contracts-bedrock/scripts/deploy/DeploySimpleSafe.s.sol b/packages/contracts-bedrock/scripts/deploy/DeploySimpleSafe.s.sol new file mode 100644 index 0000000000000..714d28b8007ec --- /dev/null +++ b/packages/contracts-bedrock/scripts/deploy/DeploySimpleSafe.s.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { console2 as console } from "forge-std/console2.sol"; +import { Script } from "forge-std/Script.sol"; +import { GnosisSafe as Safe } from "safe-contracts/GnosisSafe.sol"; +import { GnosisSafeProxyFactory as SafeProxyFactory } from "safe-contracts/proxies/GnosisSafeProxyFactory.sol"; + +/// @title DeploySimpleSafe +/// @notice Simplified Safe deployment script to replace Transactor as l1ProxyAdminOwner +contract DeploySimpleSafe is Script { + /// @notice Deploy a simple Safe as l1ProxyAdminOwner + function run() public { + vm.startBroadcast(); + // Get deployer address from environment variable as the sole owner + address deployer = vm.addr(vm.envUint("DEPLOYER_PRIVATE_KEY")); + + // Configure Safe parameters + address[] memory owners = new address[](1); + owners[0] = deployer; + + uint256 threshold = 1; // Set threshold to 1 for simplified deployment + + // Deploy Safe + address safeAddress = deploySafe("L1ProxyAdminSafe", owners, threshold); + + console.log("L1ProxyAdminSafe deployed at:", safeAddress); + console.log(" Owner:", deployer); + console.log(" Threshold:", threshold); + + vm.stopBroadcast(); + } + + /// @notice Deploy Safe contract + /// @param _name Safe contract name + /// @param _owners Array of owner addresses + /// @param _threshold Signature threshold + /// @return addr_ Deployed Safe contract address + function deploySafe( + string memory _name, + address[] memory _owners, + uint256 _threshold + ) internal returns (address addr_) { + // Get or deploy SafeProxyFactory and Safe Singleton + (SafeProxyFactory safeProxyFactory, Safe safeSingleton) = _getSafeFactory(); + + // Generate salt (using name to ensure deterministic deployment) + bytes32 salt = keccak256(abi.encode(_name, "DeploySimpleSafe")); + console.log("Deploying safe: %s with salt %s", _name, vm.toString(salt)); + + // Prepare initialization data + bytes memory initData = abi.encodeCall( + Safe.setup, + (_owners, _threshold, address(0), hex"", address(0), address(0), 0, payable(address(0))) + ); + + // Create Safe proxy (using createProxyWithNonce to support salt) + addr_ = address(safeProxyFactory.createProxyWithNonce(address(safeSingleton), initData, uint256(salt))); + + console.log("New Safe %s deployed at: %s", _name, addr_); + } + + /// @notice Get Safe factory contracts + /// @return safeProxyFactory_ SafeProxyFactory contract instance + /// @return safeSingleton_ Safe Singleton contract instance + function _getSafeFactory() internal returns (SafeProxyFactory safeProxyFactory_, Safe safeSingleton_) { + // Use standard deployment addresses + address safeProxyFactory = 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2; + address safeSingleton = 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552; + + // Check if already deployed, if not deploy new ones + if (safeProxyFactory.code.length == 0) { + console.log("Deploying new SafeProxyFactory..."); + safeProxyFactory_ = new SafeProxyFactory(); + } else { + console.log("Using existing SafeProxyFactory at:", safeProxyFactory); + safeProxyFactory_ = SafeProxyFactory(safeProxyFactory); + } + + if (safeSingleton.code.length == 0) { + console.log("Deploying new Safe Singleton..."); + safeSingleton_ = new Safe(); + } else { + console.log("Using existing Safe Singleton at:", safeSingleton); + safeSingleton_ = Safe(payable(safeSingleton)); + } + } +} diff --git a/packages/contracts-bedrock/src/L1/DepositedOKBAdapter.sol b/packages/contracts-bedrock/src/L1/DepositedOKBAdapter.sol new file mode 100644 index 0000000000000..674b59c4ed46d --- /dev/null +++ b/packages/contracts-bedrock/src/L1/DepositedOKBAdapter.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +// Contracts +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +// Interfaces +import { IOKB } from "interfaces/L1/IOKB.sol"; +import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; + +/// @title DepositedOKBAdapter +/// @notice This contract is an ERC20 adapter that allows for burning OKB tokens on L1 +/// and depositing them into L2. It enforces the strict 21 million supply cap +/// by burning OKB tokens and minting equivalent deposit tokens (dOKB) that can only +/// be used with the OptimismPortal2 for deposits to L2. +/// +/// Key features: +/// - Burns OKB from user's wallet upon deposit +/// - Mints deposit tokens (dOKB) that are locked to this contract +/// - Only this contract and the OptimismPortal2 have balances of dOKB. +/// - Automatically initiates L2 deposit transaction +/// +/// @dev This token is set as the gasPayingToken on SystemConfig. +contract DepositedOKBAdapter is ERC20, Ownable { + using SafeERC20 for IERC20; + + /// @notice Address of the OptimismPortal2 contract that this adapter works with. + IOptimismPortal2 public immutable PORTAL; + + /// @notice Address of the OKB token contract. + IOKB public immutable OKB; + + /// @notice Default gas limit for L2 deposit transactions. + uint64 public constant DEFAULT_GAS_LIMIT = 100_000; + + /// @notice Mapping of whitelisted addresses allowed to deposit. + mapping(address => bool) public whitelist; + + /// @notice Emitted when a user deposits OKB and initiates an L2 transaction. + /// @param from Address that deposited the OKB. + /// @param to Target address on L2. + /// @param amount Amount of OKB burned and deposited. + event Deposited(address indexed from, address indexed to, uint256 amount); + + /// @notice Emitted when an address is added to the whitelist. + /// @param account Address that was added to the whitelist. + event WhitelistAdded(address indexed account); + + /// @notice Emitted when an address is removed from the whitelist. + /// @param account Address that was removed from the whitelist. + event WhitelistRemoved(address indexed account); + + /// @notice Thrown when transfer is attempted outside of portal operations. + error TransferNotAllowed(); + + /// @notice Thrown when amount is zero. + error AmountMustBeGreaterThanZero(); + + /// @notice Thrown when balance is insufficient. + error InsufficientBalance(); + + /// @notice Thrown when transfer fails. + error TransferFailed(); + + /// @notice Thrown when transfer OKB from user fails. + error TransferFromUserFailed(); + + /// @notice Thrown when OKB balance is not equal to the amount deposited. + error OKBBalanceMismatch(); + + /// @notice Thrown when caller is not whitelisted. + error NotWhitelisted(); + + /// @notice Thrown when address is zero. + error AddressCannotBeZero(); + + /// @notice Thrown when OKB balance is not zero. + error OKBBalanceNotZeroAfterBurn(); + + /// @notice Constructor sets up the adapter with references to OKB, OptimismPortal, rescuer, + /// and premints the maximum supply to the owner. + /// @param _okb Address of the OKB token contract. + /// @param _portal Address of the OptimismPortal2 contract. + /// @param _owner Address of the contract owner. + constructor(address _okb, address payable _portal, address _owner) ERC20("Deposited OKB", "dOKB") { + if (_okb == address(0)) { + revert AddressCannotBeZero(); + } + if (_portal == address(0)) { + revert AddressCannotBeZero(); + } + OKB = IOKB(_okb); + PORTAL = IOptimismPortal2(_portal); + + // Premint total supply of OKB to this contract to enforce hard cap + _mint(address(this), OKB.totalSupply()); + + // Transfer ownership to the owner + transferOwnership(_owner); + } + + /// @notice Adds multiple addresses to the whitelist in a single transaction. + /// @param _accounts Array of addresses to add to the whitelist. + function addToWhitelistBatch(address[] calldata _accounts) external onlyOwner { + for (uint256 i = 0; i < _accounts.length; i++) { + if (_accounts[i] == address(0)) { + revert AddressCannotBeZero(); + } + whitelist[_accounts[i]] = true; + emit WhitelistAdded(_accounts[i]); + } + } + + /// @notice Removes multiple addresses from the whitelist in a single transaction. + /// @param _accounts Array of addresses to remove from the whitelist. + function removeFromWhitelistBatch(address[] calldata _accounts) external onlyOwner { + for (uint256 i = 0; i < _accounts.length; i++) { + if (_accounts[i] == address(0)) { + revert AddressCannotBeZero(); + } + whitelist[_accounts[i]] = false; + emit WhitelistRemoved(_accounts[i]); + } + } + + /// @notice Allows whitelisted users to burn OKB and deposit into L2. + /// This function: + /// 1. Checks if caller is whitelisted + /// 2. Transfers OKB from the user to this contract + /// 3. Creates a minimal proxy burner contract + /// 4. Transfers the exact amount of OKB to the burner + /// 5. Burns the OKB via the burner (which self-destructs) + /// 6. Mints deposit tokens to this contract + /// 7. Initiates an L2 deposit transaction via the portal + /// @param _to Target address on L2 to receive the tokens. + /// @param _amount Amount of OKB to burn and deposit. + function deposit(address _to, uint256 _amount) external { + if (!whitelist[msg.sender]) { + revert NotWhitelisted(); + } + if (_amount == 0) { + revert AmountMustBeGreaterThanZero(); + } + if (OKB.balanceOf(msg.sender) < _amount) { + revert InsufficientBalance(); + } + + // Transfer any remaining OKB to rescuer. + // If someone mistakenly directly transfer OKB to this contract, transfer it to the owner. + if (OKB.balanceOf(address(this)) > 0) { + bool transferSuccess = OKB.transfer(owner(), OKB.balanceOf(address(this))); + if (!transferSuccess) { + revert TransferFailed(); + } + } + + // Transfer OKB from user to this contract first + bool transferFromUserSuccess = OKB.transferFrom(msg.sender, address(this), _amount); + if (!transferFromUserSuccess) { + revert TransferFromUserFailed(); + } + + // Check invariant: the amount of OKB in this contract should be equal to the amount deposited. + if (OKB.balanceOf(address(this)) != _amount) { + revert OKBBalanceMismatch(); + } + + // Burn all OKB from this contract + OKB.triggerBridge(); + + // Check invariant: the amount of OKB in this contract should be zero after burning. + if (OKB.balanceOf(address(this)) > 0) { + revert OKBBalanceNotZeroAfterBurn(); + } + + // Approve the portal to pull the deposit tokens + _approve(address(this), address(PORTAL), _amount); + + // Portal will call transferFrom to pull the deposit tokens + PORTAL.depositERC20Transaction(_to, _amount, _amount, DEFAULT_GAS_LIMIT, false, ""); + + emit Deposited(msg.sender, _to, _amount); + } + + /// @notice Override transfer to disable transfers + /// This ensures that deposit tokens can only be used by the portal + /// and cannot be transferred or traded elsewhere. + /// @return bool Always reverts. + function transfer(address, /* _to */ uint256 /* _amount */ ) public virtual override returns (bool) { + // Do not allow any transfers + revert TransferNotAllowed(); + } + + /// @notice Override transferFrom to disable transfers + /// This ensures that deposit tokens can only be used by the portal + /// and cannot be transferred or traded elsewhere. + /// @param from Sender address. + /// @param to Recipient address. + /// @param amount Amount to transfer. + /// @return bool True if transfer succeeds. + function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { + // Ensure only the portal can pull from this contract, and only to the portal. + if (msg.sender == address(PORTAL) && to == address(PORTAL) && from == address(this)) { + return super.transferFrom(from, to, amount); + } + + revert TransferNotAllowed(); + } + + /// @notice Allows owner to rescue ERC20 tokens sent to this contract. + /// @param _token Address of the ERC20 token to rescue. + /// @param _to Address to send the tokens to. + /// @param _amount Amount of tokens to rescue. + function rescueERC20(address _token, address _to, uint256 _amount) external onlyOwner { + if (_token == address(0)) { + revert AddressCannotBeZero(); + } + if (_to == address(0)) { + revert AddressCannotBeZero(); + } + if (_amount == 0) { + revert AmountMustBeGreaterThanZero(); + } + + IERC20(_token).safeTransfer(_to, _amount); + } +} diff --git a/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol b/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol index 98c557a603c37..cceb56ac55b84 100644 --- a/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/L1/L1ERC721Bridge.sol @@ -94,6 +94,7 @@ contract L1ERC721Bridge is ERC721Bridge, ProxyAdminOwnedBase, ReinitializableBas external onlyOtherBridge { + revert("not allow bridge"); require(paused() == false, "L1ERC721Bridge: paused"); require(_localToken != address(this), "L1ERC721Bridge: local token cannot be self"); @@ -128,6 +129,7 @@ contract L1ERC721Bridge is ERC721Bridge, ProxyAdminOwnedBase, ReinitializableBas internal override { + revert("not allow bridge"); require(_remoteToken != address(0), "L1ERC721Bridge: remote token cannot be address(0)"); // Construct calldata for _l2Token.finalizeBridgeERC721(_to, _tokenId) diff --git a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol index 465ec7f7ed5eb..3e0d6c68cb1ed 100644 --- a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol +++ b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol @@ -142,6 +142,7 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl /// Data supplied here will not be used to execute any code on L2 and is /// only emitted as extra data for the convenience of off-chain tooling. function depositETH(uint32 _minGasLimit, bytes calldata _extraData) external payable onlyEOA { + revert("not allow bridge"); _initiateETHDeposit(msg.sender, msg.sender, _minGasLimit, _extraData); } @@ -157,6 +158,7 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl /// Data supplied here will not be used to execute any code on L2 and is /// only emitted as extra data for the convenience of off-chain tooling. function depositETHTo(address _to, uint32 _minGasLimit, bytes calldata _extraData) external payable { + revert("not allow bridge"); _initiateETHDeposit(msg.sender, _to, _minGasLimit, _extraData); } @@ -180,6 +182,7 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl virtual onlyEOA { + revert("not allow bridge"); _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData); } @@ -204,6 +207,7 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl external virtual { + revert("not allow bridge"); _initiateERC20Deposit(_l1Token, _l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData); } @@ -222,6 +226,7 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl external payable { + revert("not allow bridge"); finalizeBridgeETH(_from, _to, _amount, _extraData); } @@ -243,6 +248,7 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl ) external { + revert("not allow bridge"); finalizeBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _extraData); } @@ -259,6 +265,7 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl /// @param _minGasLimit Minimum gas limit for the deposit message on L2. /// @param _extraData Optional data to forward to L2. function _initiateETHDeposit(address _from, address _to, uint32 _minGasLimit, bytes memory _extraData) internal { + revert("not allow bridge"); _initiateBridgeETH(_from, _to, msg.value, _minGasLimit, _extraData); } @@ -281,6 +288,7 @@ contract L1StandardBridge is StandardBridge, ProxyAdminOwnedBase, Reinitializabl ) internal { + revert("not allow bridge"); _initiateBridgeERC20(_l1Token, _l2Token, _from, _to, _amount, _minGasLimit, _extraData); } diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index 7024fad39c7d8..a16c064e8724c 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -17,6 +17,7 @@ import { SecureMerkleTrie } from "src/libraries/trie/SecureMerkleTrie.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { GameStatus, GameType } from "src/dispute/lib/Types.sol"; import { Features } from "src/libraries/Features.sol"; +import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; // Interfaces import { ISemver } from "interfaces/universal/ISemver.sol"; @@ -27,6 +28,7 @@ import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; import { IETHLockbox } from "interfaces/L1/IETHLockbox.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @custom:proxied true /// @title OptimismPortal2 @@ -207,6 +209,12 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ReinitializableBase /// @notice Thrown when ETHLockbox is set/unset incorrectly depending on the feature flag. error OptimismPortal_InvalidLockboxState(); + /// @notice Thrown when trying to use depositERC20Transaction on a non-CGT chain. + error OptimismPortal_OnlyCustomGasToken(); + + /// @notice Thrown when trying to use depositERC20Transaction but gas token not set. + error OptimismPortal_InvalidGasToken(); + /// @notice Semantic version. /// @custom:semver 5.2.0 function version() public pure virtual returns (string memory) { @@ -551,6 +559,78 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ReinitializableBase } } + /// @notice Accepts deposits of ERC20 (custom gas token) and data, and emits a TransactionDeposited + /// event for use in deriving deposit transactions. This function is specifically for depositing + /// the custom gas token on CGT-enabled chains. Users must approve this contract to spend their + /// tokens before calling this function. + /// @param _to Target address on L2. + /// @param _mint Amount of custom gas token to mint on L2 (transferred from msg.sender). + /// @param _value Amount of custom gas token to send to the recipient on L2. + /// @param _gasLimit Amount of L2 gas to purchase by burning gas on L1. + /// @param _isCreation Whether or not the transaction is a contract creation. + /// @param _data Data to trigger the recipient with. + function depositERC20Transaction( + address _to, + uint256 _mint, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + public + metered(_gasLimit) + { + // Only allow ERC20 deposits if custom gas token mode is enabled + if (!_isUsingCustomGasToken()) { + revert OptimismPortal_OnlyCustomGasToken(); + } + + // Transfer the custom gas token from the caller to this contract + (address token,) = systemConfig.gasPayingToken(); + if (token == Constants.ETHER) { + revert OptimismPortal_InvalidGasToken(); + } + + if (_mint > 0) { + IERC20(token).transferFrom(msg.sender, address(this), _mint); + } + + // Just to be safe, make sure that people specify address(0) as the target when doing + // contract creations. + if (_isCreation && _to != address(0)) { + revert OptimismPortal_BadTarget(); + } + + // Prevent depositing transactions that have too small of a gas limit. Users should pay + // more for more resource usage. + if (_gasLimit < minimumGasLimit(uint64(_data.length))) { + revert OptimismPortal_GasLimitTooLow(); + } + + // Prevent the creation of deposit transactions that have too much calldata. This gives an + // upper limit on the size of unsafe blocks over the p2p network. 120kb is chosen to ensure + // that the transaction can fit into the p2p network policy of 128kb even though deposit + // transactions are not gossipped over the p2p network. + if (_data.length > 120_000) { + revert OptimismPortal_CalldataTooLarge(); + } + + // Transform the from-address to its alias if the caller is a contract. + address from = msg.sender; + if (!EOA.isSenderEOA()) { + from = AddressAliasHelper.applyL1ToL2Alias(msg.sender); + } + + // Compute the opaque data that will be emitted as part of the TransactionDeposited event. + // We use opaque data so that we can update the TransactionDeposited event in the future + // without breaking the current interface. + bytes memory opaqueData = abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data); + + // Emit a TransactionDeposited event so that the rollup node can derive a deposit + // transaction for this deposit. + emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData); + } + /// @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in /// deriving deposit transactions. Note that if a deposit is made by a contract, its /// address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider diff --git a/packages/contracts-bedrock/src/L1/SystemConfig.sol b/packages/contracts-bedrock/src/L1/SystemConfig.sol index 2b6c0f0d77398..0ed197114ecd5 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfig.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfig.sol @@ -9,19 +9,21 @@ import { ProxyAdminOwnedBase } from "src/L1/ProxyAdminOwnedBase.sol"; // Libraries import { Storage } from "src/libraries/Storage.sol"; import { Features } from "src/libraries/Features.sol"; - +import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; +import { Constants } from "src/libraries/Constants.sol"; // Interfaces import { ISemver } from "interfaces/universal/ISemver.sol"; import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; +import { IGasToken } from "src/libraries/GasPayingToken.sol"; /// @custom:proxied true /// @title SystemConfig /// @notice The SystemConfig contract is used to manage configuration of an Optimism network. /// All configuration is stored on L1 and picked up by L2 as part of the derviation of /// the L2 chain. -contract SystemConfig is ProxyAdminOwnedBase, OwnableUpgradeable, ReinitializableBase, ISemver { +contract SystemConfig is ProxyAdminOwnedBase, OwnableUpgradeable, ReinitializableBase, ISemver, IGasToken { /// @notice Enum representing different types of updates. /// @custom:value BATCHER Represents an update to the batcher hash. /// @custom:value FEE_SCALARS Represents an update to l1 data fee scalars. @@ -160,6 +162,9 @@ contract SystemConfig is ProxyAdminOwnedBase, OwnableUpgradeable, Reinitializabl /// respectively. error SystemConfig_InvalidFeatureState(); + /// @notice Thrown when attempting to set a value that has already been set + error SystemConfig_ValueAlreadySet(); + /// @notice Semantic version. /// @custom:semver 3.11.0 function version() public pure virtual returns (string memory) { @@ -572,4 +577,45 @@ contract SystemConfig is ProxyAdminOwnedBase, OwnableUpgradeable, Reinitializabl function isCustomGasToken() public view returns (bool) { return isFeatureEnabled[Features.CUSTOM_GAS_TOKEN]; } + + /// @notice Getter for the ERC20 token address that is used to pay for gas and its decimals. + /// @return address_ Address of the gas paying token. + /// @return decimals_ Decimals of the gas paying token. + function gasPayingToken() public view returns (address address_, uint8 decimals_) { + (address_, decimals_) = GasPayingToken.getToken(); + } + + /// @notice Returns the gas token name. + /// @return name_ Name of the gas paying token. + function gasPayingTokenName() public view returns (string memory name_) { + name_ = GasPayingToken.getName(); + } + + /// @notice Returns the gas token symbol. + /// @return symbol_ Symbol of the gas paying token. + function gasPayingTokenSymbol() public view returns (string memory symbol_) { + symbol_ = GasPayingToken.getSymbol(); + } + + /// @notice Sets the gas paying token and its metadata. Can only be called by the owner. + /// @param _token The address of the gas paying token. + /// @param _decimals The decimals of the gas paying token. + /// @param _name The name of the gas paying token as a bytes32. + /// @param _symbol The symbol of the gas paying token as a bytes32. + function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external onlyOwner { + (address gasToken,) = gasPayingToken(); + if (gasToken != Constants.ETHER) { + revert SystemConfig_ValueAlreadySet(); + } + _setGasPayingToken(_token, _decimals, _name, _symbol); + } + + /// @notice Internal function for setting the gas paying token. + /// @param _token The address of the gas paying token. + /// @param _decimals The decimals of the gas paying token. + /// @param _name The name of the gas paying token as a bytes32. + /// @param _symbol The symbol of the gas paying token as a bytes32. + function _setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) internal { + GasPayingToken.set(_token, _decimals, _name, _symbol); + } } diff --git a/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol b/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol index e080f694751f9..68f2a235e8f25 100644 --- a/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/L2/L2ERC721Bridge.sol @@ -62,6 +62,7 @@ contract L2ERC721Bridge is ERC721Bridge, ISemver { external onlyOtherBridge { + revert("not allow bridge"); require(_localToken != address(this), "L2ERC721Bridge: local token cannot be self"); // Note that supportsInterface makes a callback to the _localToken address which is user @@ -97,6 +98,7 @@ contract L2ERC721Bridge is ERC721Bridge, ISemver { internal override { + revert("not allow bridge"); require(_remoteToken != address(0), "L2ERC721Bridge: remote token cannot be address(0)"); // Check that the withdrawal is being initiated by the NFT owner diff --git a/packages/contracts-bedrock/src/L2/L2StandardBridge.sol b/packages/contracts-bedrock/src/L2/L2StandardBridge.sol index 1e9c2ac15f315..1df6a0d5f91dc 100644 --- a/packages/contracts-bedrock/src/L2/L2StandardBridge.sol +++ b/packages/contracts-bedrock/src/L2/L2StandardBridge.sol @@ -103,6 +103,7 @@ contract L2StandardBridge is StandardBridge, ISemver { virtual onlyEOA { + revert("not allow bridge"); _initiateWithdrawal(_l2Token, msg.sender, msg.sender, _amount, _minGasLimit, _extraData); } @@ -131,6 +132,7 @@ contract L2StandardBridge is StandardBridge, ISemver { payable virtual { + revert("not allow bridge"); _initiateWithdrawal(_l2Token, msg.sender, _to, _amount, _minGasLimit, _extraData); } @@ -159,6 +161,7 @@ contract L2StandardBridge is StandardBridge, ISemver { ) internal { + revert("not allow bridge"); if (_l2Token == Predeploys.LEGACY_ERC20_ETH) { _initiateBridgeETH(_from, _to, _amount, _minGasLimit, _extraData); } else { diff --git a/packages/contracts-bedrock/src/universal/ERC721Bridge.sol b/packages/contracts-bedrock/src/universal/ERC721Bridge.sol index abb9ab1551ef4..33ac2c40fca5a 100644 --- a/packages/contracts-bedrock/src/universal/ERC721Bridge.sol +++ b/packages/contracts-bedrock/src/universal/ERC721Bridge.sol @@ -132,6 +132,7 @@ abstract contract ERC721Bridge is Initializable { ) external { + revert("not allow bridge"); // Modifier requiring sender to be EOA. This prevents against a user error that would occur // if the sender is a smart contract wallet that has a different address on the remote chain // (or doesn't have an address on the remote chain at all). The user would fail to receive @@ -168,6 +169,7 @@ abstract contract ERC721Bridge is Initializable { ) external { + revert("not allow bridge"); require(_to != address(0), "ERC721Bridge: nft recipient cannot be address(0)"); _initiateBridgeERC721(_localToken, _remoteToken, msg.sender, _to, _tokenId, _minGasLimit, _extraData); diff --git a/packages/contracts-bedrock/src/universal/StandardBridge.sol b/packages/contracts-bedrock/src/universal/StandardBridge.sol index 9473b5f321044..d2f7b89bd5b34 100644 --- a/packages/contracts-bedrock/src/universal/StandardBridge.sol +++ b/packages/contracts-bedrock/src/universal/StandardBridge.sol @@ -164,6 +164,7 @@ abstract contract StandardBridge is Initializable { /// not be triggered with this data, but it will be emitted and can be used /// to identify the transaction. function bridgeETH(uint32 _minGasLimit, bytes calldata _extraData) public payable onlyEOA { + revert("not allow bridge"); _initiateBridgeETH(msg.sender, msg.sender, msg.value, _minGasLimit, _extraData); } @@ -180,6 +181,7 @@ abstract contract StandardBridge is Initializable { /// not be triggered with this data, but it will be emitted and can be used /// to identify the transaction. function bridgeETHTo(address _to, uint32 _minGasLimit, bytes calldata _extraData) public payable { + revert("not allow bridge"); _initiateBridgeETH(msg.sender, _to, msg.value, _minGasLimit, _extraData); } @@ -202,6 +204,7 @@ abstract contract StandardBridge is Initializable { virtual onlyEOA { + revert("not allow bridge"); _initiateBridgeERC20(_localToken, _remoteToken, msg.sender, msg.sender, _amount, _minGasLimit, _extraData); } @@ -225,6 +228,7 @@ abstract contract StandardBridge is Initializable { public virtual { + revert("not allow bridge"); _initiateBridgeERC20(_localToken, _remoteToken, msg.sender, _to, _amount, _minGasLimit, _extraData); } @@ -246,6 +250,7 @@ abstract contract StandardBridge is Initializable { payable onlyOtherBridge { + revert("not allow bridge"); require(paused() == false, "StandardBridge: paused"); require(msg.value == _amount, "StandardBridge: amount sent does not match amount required"); require(_to != address(this), "StandardBridge: cannot send to self"); @@ -280,6 +285,7 @@ abstract contract StandardBridge is Initializable { public onlyOtherBridge { + revert("not allow bridge"); require(paused() == false, "StandardBridge: paused"); if (_isOptimismMintableERC20(_localToken)) { require( @@ -315,6 +321,7 @@ abstract contract StandardBridge is Initializable { ) internal { + revert("not allow bridge"); require(msg.value == _amount, "StandardBridge: bridging ETH must include sufficient ETH value"); // Emit the correct events. By default this will be _amount, but child @@ -348,6 +355,7 @@ abstract contract StandardBridge is Initializable { ) internal { + revert("not allow bridge"); require(msg.value == 0, "StandardBridge: cannot send value"); if (_isOptimismMintableERC20(_localToken)) { diff --git a/packages/contracts-bedrock/test/L1/DepositedOKBAdapter.t.sol b/packages/contracts-bedrock/test/L1/DepositedOKBAdapter.t.sol new file mode 100644 index 0000000000000..a23a097884353 --- /dev/null +++ b/packages/contracts-bedrock/test/L1/DepositedOKBAdapter.t.sol @@ -0,0 +1,824 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +// Testing +import { CommonTest } from "test/setup/CommonTest.sol"; +import { Test } from "forge-std/Test.sol"; + +// Contracts +import { DepositedOKBAdapter } from "src/L1/DepositedOKBAdapter.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +// Libraries +import { Types } from "src/libraries/Types.sol"; +import { GameType } from "src/dispute/lib/LibUDT.sol"; + +// Interfaces +import { IOKB } from "interfaces/L1/IOKB.sol"; +import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; +import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; +import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; +import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; +import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; +import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; +import { IProxyAdminOwnedBase } from "interfaces/L1/IProxyAdminOwnedBase.sol"; +import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; +import { IETHLockbox } from "interfaces/L1/IETHLockbox.sol"; + +/// @title MockOKB +/// @notice Mock OKB contract for testing +contract MockOKB is ERC20, IOKB { + bool public burnTriggered = false; + + constructor(uint256 _totalSupply) ERC20("OKX Token", "OKB") { + _mint(address(this), _totalSupply); + } + + function mint(address _to, uint256 _amount) external { + _mint(_to, _amount); + } + + function triggerBridge() external override { + burnTriggered = true; + // Burn all tokens held by the caller + _burn(msg.sender, balanceOf(msg.sender)); + } + + function resetBurnTriggered() external { + burnTriggered = false; + } +} + +/// @title MockOptimismPortal2 +/// @notice Mock OptimismPortal2 contract for testing +contract MockOptimismPortal2 is IOptimismPortal2 { + struct DepositCall { + address to; + uint256 mint; + uint256 value; + uint64 gasLimit; + bool isCreation; + bytes data; + } + + DepositCall[] public depositCalls; + address public depositToken; + bool public shouldRevert = false; + + function setDepositToken(address _token) external { + depositToken = _token; + } + + function setShouldRevert(bool _shouldRevert) external { + shouldRevert = _shouldRevert; + } + + function depositERC20Transaction( + address _to, + uint256 _mint, + uint256 _value, + uint64 _gasLimit, + bool _isCreation, + bytes memory _data + ) + external + override + { + if (shouldRevert) { + revert("MockPortal: forced revert"); + } + + // Simulate portal pulling tokens from the adapter + if (depositToken != address(0)) { + bool success = IERC20(depositToken).transferFrom(msg.sender, address(this), _mint); + require(success, "MockPortal: token transfer failed"); + } + + depositCalls.push( + DepositCall({ + to: _to, + mint: _mint, + value: _value, + gasLimit: _gasLimit, + isCreation: _isCreation, + data: _data + }) + ); + } + + function getDepositCallsLength() external view returns (uint256) { + return depositCalls.length; + } + + function getLastDepositCall() external view returns (DepositCall memory) { + require(depositCalls.length > 0, "No deposit calls"); + return depositCalls[depositCalls.length - 1]; + } + + // Implement other IOptimismPortal2 functions as no-ops for compilation + receive() external payable { } + + function anchorStateRegistry() external pure override returns (IAnchorStateRegistry) { + return IAnchorStateRegistry(address(0)); + } + + function ethLockbox() external pure override returns (IETHLockbox) { + return IETHLockbox(address(0)); + } + + function checkWithdrawal(bytes32, address) external pure override { } + function depositTransaction(address, uint256, uint64, bool, bytes memory) external payable override { } + + function disputeGameBlacklist(IDisputeGame) external pure override returns (bool) { + return false; + } + + function disputeGameFactory() external pure override returns (IDisputeGameFactory) { + return IDisputeGameFactory(address(0)); + } + + function disputeGameFinalityDelaySeconds() external pure override returns (uint256) { + return 0; + } + + function donateETH() external payable override { } + + function superchainConfig() external pure override returns (ISuperchainConfig) { + return ISuperchainConfig(address(0)); + } + + function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory) external pure override { } + function finalizeWithdrawalTransactionExternalProof( + Types.WithdrawalTransaction memory, + address + ) + external + pure + override + { } + + function finalizedWithdrawals(bytes32) external pure override returns (bool) { + return false; + } + + function guardian() external pure override returns (address) { + return address(0); + } + + function initialize(ISystemConfig, IAnchorStateRegistry) external pure override { } + + function initVersion() external pure override returns (uint8) { + return 0; + } + + function l2Sender() external pure override returns (address) { + return address(0); + } + + function minimumGasLimit(uint64) external pure override returns (uint64) { + return 0; + } + + function numProofSubmitters(bytes32) external pure override returns (uint256) { + return 0; + } + + function params() external pure override returns (uint128, uint64, uint64) { + return (0, 0, 0); + } + + function paused() external pure override returns (bool) { + return false; + } + + function proofMaturityDelaySeconds() external pure override returns (uint256) { + return 0; + } + + function proofSubmitters(bytes32, uint256) external pure override returns (address) { + return address(0); + } + + function proveWithdrawalTransaction( + Types.WithdrawalTransaction memory, + uint256, + Types.OutputRootProof memory, + bytes[] memory + ) + external + pure + override + { } + + function provenWithdrawals(bytes32, address) external pure override returns (IDisputeGame, uint64) { + return (IDisputeGame(address(0)), 0); + } + + function respectedGameType() external pure override returns (GameType) { + return GameType.wrap(0); + } + + function respectedGameTypeUpdatedAt() external pure override returns (uint64) { + return 0; + } + + function systemConfig() external pure override returns (ISystemConfig) { + return ISystemConfig(address(0)); + } + + function version() external pure override returns (string memory) { + return "1.0.0"; + } + + function __constructor__(uint256) external pure override { } + + function proxiedInterface() external pure returns (IProxyAdminOwnedBase) { + return IProxyAdminOwnedBase(address(0)); + } + + function proxyAdmin() external pure returns (IProxyAdmin) { + return IProxyAdmin(address(0)); + } + + function proxyAdminOwner() external pure returns (address) { + return address(0); + } +} + +/// @title DepositedOKBAdapter_TestInit +/// @notice Test setup contract for DepositedOKBAdapter tests +contract DepositedOKBAdapter_TestInit is CommonTest { + // Events for testing + event WhitelistAdded(address indexed account); + event WhitelistRemoved(address indexed account); + event Deposited(address indexed from, address indexed to, uint256 amount); + + uint256 constant TOTAL_SUPPLY = 21_000_000e18; // 21 million OKB + uint256 constant TEST_AMOUNT = 1000e18; // 1000 OKB + + MockOKB okb; + MockOptimismPortal2 portal; + DepositedOKBAdapter adapter; + address owner; + address user1; + address user2; + + function setUp() public virtual override { + super.setUp(); + + owner = makeAddr("owner"); + user1 = makeAddr("user1"); + user2 = makeAddr("user2"); + + // Deploy mock contracts + okb = new MockOKB(TOTAL_SUPPLY); + portal = new MockOptimismPortal2(); + + // Deploy the adapter + adapter = new DepositedOKBAdapter(address(okb), payable(address(portal)), owner); + + // Set up the portal to accept the adapter as deposit token + portal.setDepositToken(address(adapter)); + + // Give some OKB to test users + okb.mint(user1, TEST_AMOUNT * 10); + okb.mint(user2, TEST_AMOUNT * 5); + + vm.deal(user1, 10 ether); + vm.deal(user2, 10 ether); + } +} + +/// @title DepositedOKBAdapter_Constructor_Test +/// @notice Test contract for DepositedOKBAdapter constructor +contract DepositedOKBAdapter_Constructor_Test is DepositedOKBAdapter_TestInit { + /// @notice Test successful constructor execution + function test_constructor_succeeds() public view { + // Check that the adapter was deployed correctly + assertEq(address(adapter.OKB()), address(okb)); + assertEq(address(adapter.PORTAL()), address(portal)); + assertEq(adapter.owner(), owner); + assertEq(adapter.name(), "Deposited OKB"); + assertEq(adapter.symbol(), "dOKB"); + assertEq(adapter.totalSupply(), TOTAL_SUPPLY); + assertEq(adapter.balanceOf(address(adapter)), TOTAL_SUPPLY); + assertEq(adapter.DEFAULT_GAS_LIMIT(), 100_000); + } + + /// @notice Test constructor reverts with zero OKB address + function test_constructor_zeroOKBAddress_reverts() public { + vm.expectRevert(DepositedOKBAdapter.AddressCannotBeZero.selector); + new DepositedOKBAdapter(address(0), payable(address(portal)), owner); + } + + /// @notice Test constructor reverts with zero portal address + function test_constructor_zeroPortalAddress_reverts() public { + vm.expectRevert(DepositedOKBAdapter.AddressCannotBeZero.selector); + new DepositedOKBAdapter(address(okb), payable(address(0)), owner); + } +} + +/// @title DepositedOKBAdapter_WhitelistManagement_Test +/// @notice Test contract for whitelist management functions +contract DepositedOKBAdapter_WhitelistManagement_Test is DepositedOKBAdapter_TestInit { + /// @notice Test adding single address to whitelist + function test_addToWhitelistBatch_single_succeeds() public { + address[] memory accounts = new address[](1); + accounts[0] = user1; + + vm.expectEmit(true, false, false, false); + emit WhitelistAdded(user1); + + vm.prank(owner); + adapter.addToWhitelistBatch(accounts); + + assertTrue(adapter.whitelist(user1)); + } + + /// @notice Test adding multiple addresses to whitelist + function test_addToWhitelistBatch_multiple_succeeds() public { + address[] memory accounts = new address[](2); + accounts[0] = user1; + accounts[1] = user2; + + vm.expectEmit(true, false, false, false); + emit WhitelistAdded(user1); + vm.expectEmit(true, false, false, false); + emit WhitelistAdded(user2); + + vm.prank(owner); + adapter.addToWhitelistBatch(accounts); + + assertTrue(adapter.whitelist(user1)); + assertTrue(adapter.whitelist(user2)); + } + + /// @notice Test adding zero address to whitelist reverts + function test_addToWhitelistBatch_zeroAddress_reverts() public { + address[] memory accounts = new address[](1); + accounts[0] = address(0); + + vm.expectRevert(DepositedOKBAdapter.AddressCannotBeZero.selector); + vm.prank(owner); + adapter.addToWhitelistBatch(accounts); + } + + /// @notice Test non-owner cannot add to whitelist + function test_addToWhitelistBatch_nonOwner_reverts() public { + address[] memory accounts = new address[](1); + accounts[0] = user1; + + vm.expectRevert("Ownable: caller is not the owner"); + vm.prank(user1); + adapter.addToWhitelistBatch(accounts); + } + + /// @notice Test removing address from whitelist + function test_removeFromWhitelistBatch_succeeds() public { + // First add to whitelist + address[] memory accounts = new address[](1); + accounts[0] = user1; + vm.prank(owner); + adapter.addToWhitelistBatch(accounts); + + // Then remove + vm.expectEmit(true, false, false, false); + emit WhitelistRemoved(user1); + + vm.prank(owner); + adapter.removeFromWhitelistBatch(accounts); + + assertFalse(adapter.whitelist(user1)); + } + + /// @notice Test removing zero address from whitelist reverts + function test_removeFromWhitelistBatch_zeroAddress_reverts() public { + address[] memory accounts = new address[](1); + accounts[0] = address(0); + + vm.expectRevert(DepositedOKBAdapter.AddressCannotBeZero.selector); + vm.prank(owner); + adapter.removeFromWhitelistBatch(accounts); + } +} + +/// @title DepositedOKBAdapter_Deposit_Test +/// @notice Test contract for deposit functionality +contract DepositedOKBAdapter_Deposit_Test is DepositedOKBAdapter_TestInit { + function setUp() public override { + super.setUp(); + + // Add user1 to whitelist + address[] memory accounts = new address[](1); + accounts[0] = user1; + vm.prank(owner); + adapter.addToWhitelistBatch(accounts); + + // Approve adapter to spend user1's OKB + vm.prank(user1); + okb.approve(address(adapter), type(uint256).max); + } + + /// @notice Test successful deposit + function test_deposit_succeeds() public { + uint256 depositAmount = TEST_AMOUNT; + address target = makeAddr("target"); + + uint256 userBalanceBefore = okb.balanceOf(user1); + uint256 adapterBalanceBefore = adapter.balanceOf(address(adapter)); + + vm.expectEmit(true, true, false, true); + emit Deposited(user1, target, depositAmount); + + vm.prank(user1); + adapter.deposit(target, depositAmount); + + // Check that OKB was burned + assertTrue(okb.burnTriggered()); + assertEq(okb.balanceOf(user1), userBalanceBefore - depositAmount); + assertEq(okb.balanceOf(address(adapter)), 0); // Should be burned + + // Check that portal was called + MockOptimismPortal2.DepositCall memory lastCall = portal.getLastDepositCall(); + assertEq(lastCall.to, target); + assertEq(lastCall.mint, depositAmount); + assertEq(lastCall.value, depositAmount); + assertEq(lastCall.gasLimit, adapter.DEFAULT_GAS_LIMIT()); + assertFalse(lastCall.isCreation); + assertEq(lastCall.data, ""); + + // Check adapter token balance decreased (tokens were transferred to portal) + assertEq(adapter.balanceOf(address(adapter)), adapterBalanceBefore - depositAmount); + } + + /// @notice Test deposit with non-whitelisted user reverts + function test_deposit_notWhitelisted_reverts() public { + vm.expectRevert(DepositedOKBAdapter.NotWhitelisted.selector); + vm.prank(user2); + adapter.deposit(makeAddr("target"), TEST_AMOUNT); + } + + /// @notice Test deposit with zero amount reverts + function test_deposit_zeroAmount_reverts() public { + vm.expectRevert(DepositedOKBAdapter.AmountMustBeGreaterThanZero.selector); + vm.prank(user1); + adapter.deposit(makeAddr("target"), 0); + } + + /// @notice Test deposit with insufficient balance reverts + function test_deposit_insufficientBalance_reverts() public { + uint256 userBalance = okb.balanceOf(user1); + + vm.expectRevert(DepositedOKBAdapter.InsufficientBalance.selector); + vm.prank(user1); + adapter.deposit(makeAddr("target"), userBalance + 1); + } + + /// @notice Test deposit handles existing OKB balance in contract + function test_deposit_handlesExistingOKBBalance_succeeds() public { + uint256 depositAmount = TEST_AMOUNT; + address target = makeAddr("target"); + + // Send some OKB directly to the adapter (simulating mistaken transfer) + vm.prank(user1); + okb.transfer(address(adapter), 100e18); + + uint256 ownerBalanceBefore = okb.balanceOf(owner); + uint256 adapterOKBBefore = okb.balanceOf(address(adapter)); + + vm.prank(user1); + adapter.deposit(target, depositAmount); + + // Check that the existing OKB was transferred to owner + assertEq(okb.balanceOf(owner), ownerBalanceBefore + adapterOKBBefore); + + // Check that the burn was triggered + assertTrue(okb.burnTriggered()); + } +} + +/// @title DepositedOKBAdapter_Transfer_Test +/// @notice Test contract for transfer restrictions +contract DepositedOKBAdapter_Transfer_Test is DepositedOKBAdapter_TestInit { + /// @notice Test regular transfer is not allowed + function test_transfer_notAllowed_reverts() public { + vm.expectRevert(DepositedOKBAdapter.TransferNotAllowed.selector); + vm.prank(user1); + adapter.transfer(user2, 1000); + } + + /// @notice Test transferFrom is not allowed except from adapter to portal + function test_transferFrom_notAllowed_reverts() public { + vm.expectRevert(DepositedOKBAdapter.TransferNotAllowed.selector); + vm.prank(user1); + adapter.transferFrom(user1, user2, 1000); + } + + /// @notice Test transferFrom from adapter to portal is allowed + function test_transferFrom_adapterToPortal_succeeds() public { + uint256 amount = 1000e18; + + // First approve the portal to spend from the adapter + vm.prank(address(adapter)); + adapter.approve(address(portal), amount); + + // This should succeed (simulating portal pulling tokens) + vm.prank(address(portal)); + bool success = adapter.transferFrom(address(adapter), address(portal), amount); + assertTrue(success); + + assertEq(adapter.balanceOf(address(portal)), amount); + assertEq(adapter.balanceOf(address(adapter)), TOTAL_SUPPLY - amount); + } + + /// @notice Test portal calling transferFrom from adapter to user1 reverts + function test_transferFrom_portalCallerAdapterToUser1_reverts() public { + uint256 amount = 1000e18; + + // First approve the portal to spend from the adapter + vm.prank(address(adapter)); + adapter.approve(address(portal), amount); + + // Portal calling transferFrom(adapter, user1, amount) should revert + // because 'to' is not the portal address + vm.expectRevert(DepositedOKBAdapter.TransferNotAllowed.selector); + vm.prank(address(portal)); + adapter.transferFrom(address(adapter), user1, amount); + } + + /// @notice Test portal calling transferFrom from portal to adapter reverts + function test_transferFrom_portalCallerPortalToAdapter_reverts() public { + uint256 amount = 1000e18; + + // First approve the portal to spend from the portal (though this wouldn't make sense in practice) + vm.prank(address(portal)); + adapter.approve(address(portal), amount); + + // Portal calling transferFrom(portal, adapter, amount) should revert + // because 'from' is not the adapter address + vm.expectRevert(DepositedOKBAdapter.TransferNotAllowed.selector); + vm.prank(address(portal)); + adapter.transferFrom(address(portal), address(adapter), amount); + } + + /// @notice Test portal calling transferFrom from portal to user1 reverts + function test_transferFrom_portalCallerPortalToUser1_reverts() public { + uint256 amount = 1000e18; + + // First approve the portal to spend from the portal + vm.prank(address(portal)); + adapter.approve(address(portal), amount); + + // Portal calling transferFrom(portal, user1, amount) should revert + // because 'from' is not the adapter address and 'to' is not the portal + vm.expectRevert(DepositedOKBAdapter.TransferNotAllowed.selector); + vm.prank(address(portal)); + adapter.transferFrom(address(portal), user1, amount); + } +} + +/// @title MockUSDT +/// @notice Mock USDT contract that mimics real USDT behavior (no return value for transfer) +contract MockUSDT { + mapping(address => uint256) private _balances; + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + string public name = "Tether USD"; + string public symbol = "USDT"; + uint8 public decimals = 6; + + bool public shouldRevert = false; + + constructor(uint256 _supply) { + _totalSupply = _supply; + _balances[msg.sender] = _supply; + } + + function totalSupply() public view returns (uint256) { + return _totalSupply; + } + + function balanceOf(address account) public view returns (uint256) { + return _balances[account]; + } + + function allowance(address owner, address spender) public view returns (uint256) { + return _allowances[owner][spender]; + } + + /// @notice USDT-style transfer that doesn't return bool and reverts on failure + function transfer(address to, uint256 amount) public { + if (shouldRevert) { + revert("USDT: transfer failed"); + } + require(to != address(0), "USDT: transfer to zero address"); + require(_balances[msg.sender] >= amount, "USDT: insufficient balance"); + + _balances[msg.sender] -= amount; + _balances[to] += amount; + } + + /// @notice USDT-style transferFrom that doesn't return bool and reverts on failure + function transferFrom(address from, address to, uint256 amount) public { + if (shouldRevert) { + revert("USDT: transfer failed"); + } + require(to != address(0), "USDT: transfer to zero address"); + require(_balances[from] >= amount, "USDT: insufficient balance"); + require(_allowances[from][msg.sender] >= amount, "USDT: insufficient allowance"); + + _balances[from] -= amount; + _balances[to] += amount; + _allowances[from][msg.sender] -= amount; + } + + function approve(address spender, uint256 amount) public returns (bool) { + _allowances[msg.sender][spender] = amount; + return true; + } + + function setShouldRevert(bool _shouldRevert) external { + shouldRevert = _shouldRevert; + } + + /// @notice Mint tokens for testing + function mint(address to, uint256 amount) external { + _balances[to] += amount; + _totalSupply += amount; + } +} + +/// @title DepositedOKBAdapter_Rescue_Test +/// @notice Test contract for ERC20 rescue functionality +contract DepositedOKBAdapter_Rescue_Test is DepositedOKBAdapter_TestInit { + ERC20 testToken; + MockUSDT mockUSDT; + + function setUp() public override { + super.setUp(); + testToken = new ERC20("Test Token", "TEST"); + // Mint some tokens to the adapter (simulating accidental transfer) + deal(address(testToken), address(adapter), 1000e18); + + // Create mock USDT with 6 decimals (1M USDT) + mockUSDT = new MockUSDT(1_000_000e6); + // Transfer some USDT to the adapter (simulating accidental transfer) + mockUSDT.mint(address(adapter), 10_000e6); // 10,000 USDT + } + + /// @notice Test successful ERC20 rescue + function test_rescueERC20_succeeds() public { + uint256 rescueAmount = 500e18; + address rescueTo = makeAddr("rescueTo"); + + uint256 balanceBefore = testToken.balanceOf(rescueTo); + + vm.prank(owner); + adapter.rescueERC20(address(testToken), rescueTo, rescueAmount); + + assertEq(testToken.balanceOf(rescueTo), balanceBefore + rescueAmount); + assertEq(testToken.balanceOf(address(adapter)), 1000e18 - rescueAmount); + } + + /// @notice Test rescue with zero token address reverts + function test_rescueERC20_zeroTokenAddress_reverts() public { + vm.expectRevert(DepositedOKBAdapter.AddressCannotBeZero.selector); + vm.prank(owner); + adapter.rescueERC20(address(0), makeAddr("rescueTo"), 100); + } + + /// @notice Test rescue with zero recipient address reverts + function test_rescueERC20_zeroRecipientAddress_reverts() public { + vm.expectRevert(DepositedOKBAdapter.AddressCannotBeZero.selector); + vm.prank(owner); + adapter.rescueERC20(address(testToken), address(0), 100); + } + + /// @notice Test rescue with zero amount reverts + function test_rescueERC20_zeroAmount_reverts() public { + vm.expectRevert(DepositedOKBAdapter.AmountMustBeGreaterThanZero.selector); + vm.prank(owner); + adapter.rescueERC20(address(testToken), makeAddr("rescueTo"), 0); + } + + /// @notice Test non-owner cannot rescue + function test_rescueERC20_nonOwner_reverts() public { + vm.expectRevert("Ownable: caller is not the owner"); + vm.prank(user1); + adapter.rescueERC20(address(testToken), makeAddr("rescueTo"), 100); + } + + /// @notice Test successful USDT rescue (USDT doesn't return bool from transfer) + function test_rescueUSDT_succeeds() public { + uint256 rescueAmount = 5000e6; // 5,000 USDT (6 decimals) + address rescueTo = makeAddr("rescueTo"); + + uint256 balanceBefore = mockUSDT.balanceOf(rescueTo); + uint256 adapterBalanceBefore = mockUSDT.balanceOf(address(adapter)); + + vm.prank(owner); + adapter.rescueERC20(address(mockUSDT), rescueTo, rescueAmount); + + assertEq(mockUSDT.balanceOf(rescueTo), balanceBefore + rescueAmount); + assertEq(mockUSDT.balanceOf(address(adapter)), adapterBalanceBefore - rescueAmount); + } + + /// @notice Test USDT rescue handles revert case properly + function test_rescueUSDT_transferReverts_fails() public { + uint256 rescueAmount = 5000e6; // 5,000 USDT (6 decimals) + address rescueTo = makeAddr("rescueTo"); + + // Make USDT transfers revert + mockUSDT.setShouldRevert(true); + + // The rescue should revert when USDT transfer fails + vm.expectRevert("USDT: transfer failed"); + vm.prank(owner); + adapter.rescueERC20(address(mockUSDT), rescueTo, rescueAmount); + } +} + +/// @title DepositedOKBAdapter_Integration_Test +/// @notice Integration tests combining multiple functionalities +contract DepositedOKBAdapter_Integration_Test is DepositedOKBAdapter_TestInit { + function setUp() public override { + super.setUp(); + + // Add users to whitelist + address[] memory accounts = new address[](2); + accounts[0] = user1; + accounts[1] = user2; + vm.prank(owner); + adapter.addToWhitelistBatch(accounts); + + // Approve adapter to spend users' OKB + vm.prank(user1); + okb.approve(address(adapter), type(uint256).max); + vm.prank(user2); + okb.approve(address(adapter), type(uint256).max); + } + + /// @notice Test multiple deposits from different users + function test_multipleDeposits_succeeds() public { + address target1 = makeAddr("target1"); + address target2 = makeAddr("target2"); + uint256 amount1 = TEST_AMOUNT; + uint256 amount2 = TEST_AMOUNT / 2; + + // First deposit + vm.prank(user1); + adapter.deposit(target1, amount1); + + // Reset burn trigger for second deposit + okb.resetBurnTriggered(); + + // Second deposit + vm.prank(user2); + adapter.deposit(target2, amount2); + + // Check both deposits were recorded + assertEq(portal.getDepositCallsLength(), 2); + + // Check that both deposits were recorded + assertTrue(portal.getDepositCallsLength() >= 2); + + // We can't easily access individual array elements, so we'll just verify the last call + MockOptimismPortal2.DepositCall memory lastCall = portal.getLastDepositCall(); + assertEq(lastCall.to, target2); + assertEq(lastCall.mint, amount2); + } + + /// @notice Test whitelist management followed by deposits + function test_whitelistManagementThenDeposit_succeeds() public { + address user3 = makeAddr("user3"); + okb.mint(user3, TEST_AMOUNT); + vm.prank(user3); + okb.approve(address(adapter), type(uint256).max); + + // Initially user3 is not whitelisted + vm.expectRevert(DepositedOKBAdapter.NotWhitelisted.selector); + vm.prank(user3); + adapter.deposit(makeAddr("target"), TEST_AMOUNT); + + // Add user3 to whitelist + address[] memory accounts = new address[](1); + accounts[0] = user3; + vm.prank(owner); + adapter.addToWhitelistBatch(accounts); + + // Now deposit should succeed + vm.prank(user3); + adapter.deposit(makeAddr("target"), TEST_AMOUNT); + + // Remove user3 from whitelist + vm.prank(owner); + adapter.removeFromWhitelistBatch(accounts); + + // Deposit should fail again + vm.expectRevert(DepositedOKBAdapter.NotWhitelisted.selector); + vm.prank(user3); + adapter.deposit(makeAddr("target"), TEST_AMOUNT); + } +} diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index 754a459f5707c..d9d89b7fbd02d 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -33,6 +33,8 @@ import { IProxy } from "interfaces/universal/IProxy.sol"; import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol"; import { IETHLockbox } from "interfaces/L1/IETHLockbox.sol"; import { IProxyAdminOwnedBase } from "interfaces/L1/IProxyAdminOwnedBase.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract OptimismPortal2_TestInit is DisputeGameFactory_TestInit { address depositor; @@ -2754,6 +2756,343 @@ contract OptimismPortal2_DepositTransaction_Test is OptimismPortal2_TestInit { } } +/// @title OptimismPortal2_DepositERC20Transaction_Test +/// @notice Test contract for OptimismPortal2 `depositERC20Transaction` function. +contract OptimismPortal2_DepositERC20Transaction_Test is CommonTest { + address depositor; + ERC20 customGasToken; + + function setUp() public override { + super.setUp(); + depositor = makeAddr("depositor"); + + // Set up custom gas token if the feature is enabled + if (isDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN)) { + // Deploy a mock ERC20 token to use as custom gas token + customGasToken = new ERC20("Custom Gas Token", "CGT"); + + // Set the custom gas token in SystemConfig + // Convert strings to bytes32 for SystemConfig function + bytes32 nameBytes32 = bytes32(bytes("Custom Gas Token")); + bytes32 symbolBytes32 = bytes32(bytes("CGT")); + + vm.prank(systemConfig.owner()); + systemConfig.setGasPayingToken(address(customGasToken), 18, nameBytes32, symbolBytes32); + } + } + /// @notice Tests that `depositERC20Transaction` reverts when custom gas token is not enabled. + + function test_depositERC20Transaction_notCustomGasToken_reverts() external { + skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + + vm.expectRevert(IOptimismPortal.OptimismPortal_OnlyCustomGasToken.selector); + optimismPortal2.depositERC20Transaction({ + _to: address(0x40), + _mint: 100, + _value: 100, + _gasLimit: 21000, + _isCreation: false, + _data: hex"" + }); + } + + /// @notice Tests that `depositERC20Transaction` reverts when gas token is invalid (ETH). + function test_depositERC20Transaction_invalidGasToken_reverts() external { + skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfForkTest( + "OptimismPortal2_DepositERC20Transaction_Test: custom gas token not available on forked networks" + ); + + // Mock the gasPayingToken to return Constants.ETHER to test the invalid token error + // We can't actually call setGasPayingToken again since it can only be set once + vm.mockCall( + address(systemConfig), + abi.encodeCall(systemConfig.gasPayingToken, ()), + abi.encode(Constants.ETHER, uint8(18)) + ); + + vm.expectRevert(IOptimismPortal.OptimismPortal_InvalidGasToken.selector); + optimismPortal2.depositERC20Transaction({ + _to: address(0x40), + _mint: 100, + _value: 100, + _gasLimit: 21000, + _isCreation: false, + _data: hex"" + }); + + // Clear the mock for other tests + vm.clearMockedCalls(); + } + + /// @notice Tests that `depositERC20Transaction` reverts when destination address is non-zero + /// for a contract creation deposit. + function test_depositERC20Transaction_contractCreation_reverts() external { + skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfForkTest( + "OptimismPortal2_DepositERC20Transaction_Test: custom gas token not available on forked networks" + ); + + // Set up tokens and approval so we don't fail on ERC20 transfer first + uint256 mintAmount = 100; + deal(address(customGasToken), address(this), mintAmount); + customGasToken.approve(address(optimismPortal2), mintAmount); + + vm.expectRevert(IOptimismPortal.OptimismPortal_BadTarget.selector); + optimismPortal2.depositERC20Transaction({ + _to: address(1), + _mint: mintAmount, + _value: 100, + _gasLimit: 21000, + _isCreation: true, + _data: hex"" + }); + } + + /// @notice Tests that `depositERC20Transaction` reverts when the gas limit is too small. + function test_depositERC20Transaction_smallGasLimit_reverts() external { + skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfForkTest( + "OptimismPortal2_DepositERC20Transaction_Test: custom gas token not available on forked networks" + ); + + // Set up tokens and approval so we don't fail on ERC20 transfer first + uint256 mintAmount = 100; + deal(address(customGasToken), address(this), mintAmount); + customGasToken.approve(address(optimismPortal2), mintAmount); + + vm.expectRevert(IOptimismPortal.OptimismPortal_GasLimitTooLow.selector); + optimismPortal2.depositERC20Transaction({ + _to: address(0x40), + _mint: mintAmount, + _value: 100, + _gasLimit: 0, + _isCreation: false, + _data: hex"" + }); + } + + /// @notice Tests that `depositERC20Transaction` reverts when the data is too large. + function test_depositERC20Transaction_largeData_reverts() external { + skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfForkTest( + "OptimismPortal2_DepositERC20Transaction_Test: custom gas token not available on forked networks" + ); + + uint256 size = 120_001; + uint64 gasLimit = optimismPortal2.minimumGasLimit(uint64(size)); + + // Set up tokens and approval so we don't fail on ERC20 transfer first + uint256 mintAmount = 100; + deal(address(customGasToken), address(this), mintAmount); + customGasToken.approve(address(optimismPortal2), mintAmount); + + vm.expectRevert(IOptimismPortal.OptimismPortal_CalldataTooLarge.selector); + optimismPortal2.depositERC20Transaction({ + _to: address(0x40), + _mint: mintAmount, + _value: 100, + _gasLimit: gasLimit, + _isCreation: false, + _data: new bytes(size) + }); + } + + /// @notice Tests that `depositERC20Transaction` succeeds for small, but sufficient, gas limits. + function testFuzz_depositERC20Transaction_smallGasLimit_succeeds(bytes memory _data, bool _shouldFail) external { + skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfForkTest( + "OptimismPortal2_DepositERC20Transaction_Test: custom gas token not available on forked networks" + ); + + uint64 gasLimit = optimismPortal2.minimumGasLimit(uint64(_data.length)); + if (_shouldFail) { + gasLimit = uint64(bound(gasLimit, 0, gasLimit - 1)); + vm.expectRevert(IOptimismPortal.OptimismPortal_GasLimitTooLow.selector); + } + + // No ERC20 transfer needed since _mint is 0 + vm.prank(depositor); + optimismPortal2.depositERC20Transaction({ + _to: address(0x40), + _mint: 0, + _value: 0, + _gasLimit: gasLimit, + _isCreation: false, + _data: _data + }); + } + + /// @notice Tests that `depositERC20Transaction` succeeds for an EOA. + function testFuzz_depositERC20Transaction_eoa_succeeds( + address _to, + uint64 _gasLimit, + uint256 _mint, + uint256 _value, + bool _isCreation, + bytes memory _data + ) + external + { + skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfForkTest( + "OptimismPortal2_DepositERC20Transaction_Test: custom gas token not available on forked networks" + ); + + _gasLimit = uint64( + bound( + _gasLimit, + optimismPortal2.minimumGasLimit(uint64(_data.length)), + systemConfig.resourceConfig().maxResourceLimit + ) + ); + if (_isCreation) _to = address(0); + + // Set up ERC20 token balance and approval for real transfers + if (_mint > 0) { + // Give the depositor some tokens and approve the portal + deal(address(customGasToken), depositor, _mint); + vm.prank(depositor); + customGasToken.approve(address(optimismPortal2), _mint); + } + + // EOA emulation + vm.expectEmit(address(optimismPortal2)); + emitTransactionDeposited({ + _from: depositor, + _to: _to, + _value: _value, + _mint: _mint, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + + vm.prank(depositor, depositor); + optimismPortal2.depositERC20Transaction({ + _to: _to, + _mint: _mint, + _value: _value, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + } + + /// @notice Tests that `depositERC20Transaction` succeeds for a contract. + function testFuzz_depositERC20Transaction_contract_succeeds( + address _to, + uint64 _gasLimit, + uint256 _mint, + uint256 _value, + bool _isCreation, + bytes memory _data + ) + external + { + skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfForkTest( + "OptimismPortal2_DepositERC20Transaction_Test: custom gas token not available on forked networks" + ); + + _gasLimit = uint64( + bound( + _gasLimit, + optimismPortal2.minimumGasLimit(uint64(_data.length)), + systemConfig.resourceConfig().maxResourceLimit + ) + ); + if (_isCreation) _to = address(0); + + // Set up ERC20 token balance and approval for real transfers + if (_mint > 0) { + // Give the test contract some tokens and approve the portal + deal(address(customGasToken), address(this), _mint); + customGasToken.approve(address(optimismPortal2), _mint); + } + + vm.expectEmit(address(optimismPortal2)); + emitTransactionDeposited({ + _from: AddressAliasHelper.applyL1ToL2Alias(address(this)), + _to: _to, + _value: _value, + _mint: _mint, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + + vm.prank(address(this)); + optimismPortal2.depositERC20Transaction({ + _to: _to, + _mint: _mint, + _value: _value, + _gasLimit: _gasLimit, + _isCreation: _isCreation, + _data: _data + }); + } + + /// @notice Tests that `depositERC20Transaction` correctly transfers tokens when mint is non-zero. + function test_depositERC20Transaction_transfersTokens_succeeds() external { + skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfForkTest( + "OptimismPortal2_DepositERC20Transaction_Test: custom gas token not available on forked networks" + ); + + uint256 mintAmount = 1000; + + // Set up the depositor with tokens and approval + deal(address(customGasToken), depositor, mintAmount); + vm.prank(depositor); + customGasToken.approve(address(optimismPortal2), mintAmount); + + // Check initial balances + uint256 depositorBalanceBefore = customGasToken.balanceOf(depositor); + uint256 portalBalanceBefore = customGasToken.balanceOf(address(optimismPortal2)); + + vm.prank(depositor, depositor); + optimismPortal2.depositERC20Transaction({ + _to: address(0x40), + _mint: mintAmount, + _value: mintAmount, + _gasLimit: 50000, + _isCreation: false, + _data: hex"" + }); + + // Verify the tokens were transferred + assertEq(customGasToken.balanceOf(depositor), depositorBalanceBefore - mintAmount); + assertEq(customGasToken.balanceOf(address(optimismPortal2)), portalBalanceBefore + mintAmount); + } + + /// @notice Tests that `depositERC20Transaction` does not transfer tokens when mint is zero. + function test_depositERC20Transaction_zeroMint_succeeds() external { + skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfForkTest( + "OptimismPortal2_DepositERC20Transaction_Test: custom gas token not available on forked networks" + ); + + // Check initial balances - should remain unchanged + uint256 depositorBalanceBefore = customGasToken.balanceOf(depositor); + uint256 portalBalanceBefore = customGasToken.balanceOf(address(optimismPortal2)); + + vm.prank(depositor, depositor); + optimismPortal2.depositERC20Transaction({ + _to: address(0x40), + _mint: 0, + _value: 100, + _gasLimit: 50000, + _isCreation: false, + _data: hex"" + }); + + // Verify no tokens were transferred when mint is 0 + assertEq(customGasToken.balanceOf(depositor), depositorBalanceBefore); + assertEq(customGasToken.balanceOf(address(optimismPortal2)), portalBalanceBefore); + } +} + /// @title OptimismPortal2_Params_Test /// @notice Test various values of the resource metering config to ensure that deposits cannot be /// broken by changing the config. diff --git a/packages/contracts-bedrock/test/bridgeRevert/L1Bridge.t.sol b/packages/contracts-bedrock/test/bridgeRevert/L1Bridge.t.sol new file mode 100644 index 0000000000000..1be83be74551c --- /dev/null +++ b/packages/contracts-bedrock/test/bridgeRevert/L1Bridge.t.sol @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.10; + +import { IL1CrossDomainMessenger } from "../../interfaces/L1/IL1CrossDomainMessenger.sol"; +import { IL1StandardBridge } from "../../interfaces/L1/IL1StandardBridge.sol"; +import { CommonBase } from "../../lib/forge-std/src/Base.sol"; +import { StdAssertions } from "../../lib/forge-std/src/StdAssertions.sol"; +import { StdChains } from "../../lib/forge-std/src/StdChains.sol"; +import { StdCheats, StdCheatsSafe } from "../../lib/forge-std/src/StdCheats.sol"; +import { StdUtils } from "../../lib/forge-std/src/StdUtils.sol"; +import { Test } from "../../lib/forge-std/src/Test.sol"; +import { TestERC20 } from "../mocks/TestERC20.sol"; +import { TestERC721 } from "../mocks/TestERC721.sol"; +import { IL1ERC721Bridge } from "../../interfaces/L1/IL1ERC721Bridge.sol"; + +contract L1Bridge_Test is Test { + TestERC20 token; + TestERC721 token721; + uint256 l1Fork; + address testAlice; + address testBob; + IL1StandardBridge internal l1StandardBridge; + IL1CrossDomainMessenger internal l1CrossDomainMessenger; + IL1ERC721Bridge internal l1ERC721Bridge; + + function setUp() public { + testAlice = makeAddr("testAlice"); + testBob = makeAddr("testBob"); + l1Fork = vm.createSelectFork("http://localhost:8545"); + token = new TestERC20(); + token721 = new TestERC721(); + token.mint(testAlice, 1000); + token721.mint(testAlice, 1); + vm.deal(testAlice, 1000 ether); + vm.deal(testBob, 1000 ether); + vm.label(testAlice, "testAlice"); + vm.label(testBob, "testBob"); + string memory stateJson = vm.readFile("../../test/config-op/state.json"); + + address l1StandardBridgeProxy = vm.parseJsonAddress(stateJson, ".opChainDeployments[0].L1StandardBridgeProxy"); + address l1CrossDomainMessengerProxy = + vm.parseJsonAddress(stateJson, ".opChainDeployments[0].L1CrossDomainMessengerProxy"); + address l1ERC721BridgeProxy = vm.parseJsonAddress(stateJson, ".opChainDeployments[0].L1Erc721BridgeProxy"); + l1StandardBridge = IL1StandardBridge(payable(l1StandardBridgeProxy)); + l1CrossDomainMessenger = IL1CrossDomainMessenger(l1CrossDomainMessengerProxy); + l1ERC721Bridge = IL1ERC721Bridge(l1ERC721BridgeProxy); + } + + function test_sendETH_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + address(l1StandardBridge).call{ value: 1 ether }(""); + } + + function test_depositETH_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1StandardBridge.depositETH(100000, hex""); + } + + function test_depositETHTo_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1StandardBridge.depositETHTo(testBob, 100000, hex""); + } + + function test_depositERC20_reverts() public { + vm.prank(testAlice, testAlice); + token.approve(address(l1StandardBridge), 1); + + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1StandardBridge.depositERC20(address(token), address(token), 1000, 100000, hex""); + } + + function test_depositERC20To_reverts() public { + // Approve bridge to spend tokens + vm.prank(testAlice, testAlice); + token.approve(address(l1StandardBridge), 1); + + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1StandardBridge.depositERC20To( + address(token), + address(token), + testBob, + 1, + 200000, // minGasLimit + "" // extraData + ); + } + + function test_finalizeETHWithdrawal_reverts() public { + vm.expectRevert("not allow bridge"); + l1StandardBridge.finalizeETHWithdrawal{ value: 1 ether }(testAlice, testBob, 1 ether, ""); + } + + function test_finalizeERC20Withdrawal_reverts() public { + vm.expectRevert("not allow bridge"); + l1StandardBridge.finalizeERC20Withdrawal(address(token), address(token), testAlice, testBob, 1, ""); + } + + function test_bridgeETH_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1StandardBridge.bridgeETH{ value: 1 ether }( + 200000, // minGasLimit + "" // extraData + ); + } + + function test_bridgeETHTo_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1StandardBridge.bridgeETHTo(testBob, 100000, hex""); + } + + function test_bridgeERC20_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1StandardBridge.bridgeERC20(address(token), address(token), 1, 200000, hex""); + } + + function test_bridgeERC20To_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1StandardBridge.bridgeERC20To(address(token), address(token), testBob, 1, 200000, hex""); + } + + function test_bridgeERC721_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1ERC721Bridge.bridgeERC721(address(token721), address(token721), 1, 200000, hex""); + } + + function test_bridgeERC721To_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l1ERC721Bridge.bridgeERC721To(address(token721), address(token721), testBob, 1, 200000, hex""); + } + + function test_finalizeBridgeERC20_reverts() public { + address messenger = address(l1StandardBridge.messenger()); + + // Mock + vm.mockCall( + messenger, + abi.encodeCall(l1CrossDomainMessenger.xDomainMessageSender, ()), + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) + ); + vm.expectRevert("not allow bridge"); + vm.prank(messenger, messenger); + l1StandardBridge.finalizeBridgeERC20(address(token), address(token), testAlice, testBob, 1, hex""); + } + + function test_finalizeBridgeETH_reverts() public { + address messenger = address(l1StandardBridge.messenger()); + + vm.mockCall( + messenger, + abi.encodeCall(l1CrossDomainMessenger.xDomainMessageSender, ()), + abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) + ); + + vm.startPrank(messenger); + vm.expectRevert("not allow bridge"); + l1StandardBridge.finalizeBridgeETH(testAlice, testBob, 1 ether, hex""); + vm.stopPrank(); + } +} diff --git a/packages/contracts-bedrock/test/bridgeRevert/L2Bridge.t.sol b/packages/contracts-bedrock/test/bridgeRevert/L2Bridge.t.sol new file mode 100644 index 0000000000000..68e691d86a65d --- /dev/null +++ b/packages/contracts-bedrock/test/bridgeRevert/L2Bridge.t.sol @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.10; + +import { CommonBase } from "../../lib/forge-std/src/Base.sol"; +import { StdAssertions } from "../../lib/forge-std/src/StdAssertions.sol"; +import { StdChains } from "../../lib/forge-std/src/StdChains.sol"; +import { StdCheats, StdCheatsSafe } from "../../lib/forge-std/src/StdCheats.sol"; +import { StdUtils } from "../../lib/forge-std/src/StdUtils.sol"; +import { Test } from "../../lib/forge-std/src/Test.sol"; +import { TestERC20 } from "../mocks/TestERC20.sol"; +import { TestERC721 } from "../mocks/TestERC721.sol"; +import { IL2ERC721Bridge } from "../../interfaces/L2/IL2ERC721Bridge.sol"; +import { IL2StandardBridge } from "../../interfaces/L2/IL2StandardBridge.sol"; +import { IL2CrossDomainMessenger } from "../../interfaces/L2/IL2CrossDomainMessenger.sol"; + +contract L2Bridge_Test is Test { + TestERC20 token; + TestERC721 token721; + uint256 l2Fork; + address testAlice; + address testBob; + IL2StandardBridge internal l2StandardBridge; + IL2ERC721Bridge internal l2ERC721Bridge; + IL2CrossDomainMessenger internal l2CrossDomainMessenger; + + function setUp() public { + testAlice = makeAddr("testAlice"); + testBob = makeAddr("testBob"); + l2Fork = vm.createSelectFork("http://localhost:8123"); + token = new TestERC20(); + token721 = new TestERC721(); + token.mint(testAlice, 1000); + token721.mint(testAlice, 1); + vm.deal(testAlice, 1000 ether); + vm.deal(testBob, 1000 ether); + vm.label(testAlice, "testAlice"); + vm.label(testBob, "testBob"); + + address l2StandardBridgeProxy = 0x4200000000000000000000000000000000000010; + address l2CrossDomainMessengerProxy = 0x4200000000000000000000000000000000000007; + address l2ERC721BridgeProxy = 0x4200000000000000000000000000000000000014; + l2StandardBridge = IL2StandardBridge(payable(l2StandardBridgeProxy)); + l2CrossDomainMessenger = IL2CrossDomainMessenger(l2CrossDomainMessengerProxy); + l2ERC721Bridge = IL2ERC721Bridge(l2ERC721BridgeProxy); + } + + function test_sendETH_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + address(l2StandardBridge).call{ value: 1 ether }(""); + } + + function test_withdraw_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l2StandardBridge.withdraw(address(token), 1, 100000, hex""); + } + + function test_withdrawTo_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l2StandardBridge.withdrawTo(address(token), testBob, 1, 100000, hex""); + } + + function test_bridgeETH_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l2StandardBridge.bridgeETH{ value: 1 ether }(100000, hex""); + } + + function test_bridgeETHTo_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l2StandardBridge.bridgeETHTo(testBob, 100000, hex""); + } + + function test_bridgeERC20_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l2StandardBridge.bridgeERC20(address(token), address(token), 1, 100000, hex""); + } + + function test_bridgeERC20To_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l2StandardBridge.bridgeERC20To(address(token), address(token), testBob, 1, 100000, hex""); + } + + function test_bridgeERC721_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l2ERC721Bridge.bridgeERC721(address(token721), address(token721), 1, 100000, hex""); + } + + function test_bridgeERC721To_reverts() public { + vm.prank(testAlice, testAlice); + vm.expectRevert("not allow bridge"); + l2ERC721Bridge.bridgeERC721To(address(token721), address(token721), testBob, 1, 100000, hex""); + } + + function test_finalizeBridgeERC20_reverts() public { + address messenger = address(l2StandardBridge.messenger()); + + // Mock + vm.mockCall( + messenger, + abi.encodeCall(l2CrossDomainMessenger.xDomainMessageSender, ()), + abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) + ); + vm.expectRevert("not allow bridge"); + vm.prank(messenger, messenger); + l2StandardBridge.finalizeBridgeERC20(address(token), address(token), testAlice, testBob, 1, hex""); + } + + function test_finalizeBridgeETH_reverts() public { + address messenger = address(l2StandardBridge.messenger()); + + vm.mockCall( + messenger, + abi.encodeCall(l2CrossDomainMessenger.xDomainMessageSender, ()), + abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) + ); + + vm.startPrank(messenger); + vm.expectRevert("not allow bridge"); + l2StandardBridge.finalizeBridgeETH(testAlice, testBob, 1 ether, hex""); + vm.stopPrank(); + } +} diff --git a/test-pp-op/0-all-local.sh b/test-pp-op/0-all-local.sh new file mode 100755 index 0000000000000..efa8aad44a6ea --- /dev/null +++ b/test-pp-op/0-all-local.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -e + +# ./build_images.sh --all # build all images. add --force if want to force rebuild +make clean +cp local.env .env +./1-start-erigon.sh +./2-deploy-op-contracts.sh +./3-stop-erigon.sh +./4-migrate-op.sh +./5-start-op.sh +./6-build-op-program.sh +./7-setup-fraud-proof.sh diff --git a/test-pp-op/1-start-erigon.sh b/test-pp-op/1-start-erigon.sh new file mode 100755 index 0000000000000..00e95fd74e9b1 --- /dev/null +++ b/test-pp-op/1-start-erigon.sh @@ -0,0 +1,60 @@ +#!/bin/bash +set -e +set -x + +if ! [ -f .env ]; then + echo "need to provide .env file" +fi + +source .env +source tools.sh + +if [ "$ENV" = "local" ]; then + COMPOSE_FILE="docker-compose-local.yml" +else + COMPOSE_FILE="docker-compose.yml" +fi + +DOCKER_COMPOSE=$(shell docker compose version >/dev/null 2>&1 && echo "docker compose" || echo "docker-compose") +DOCKER_COMPOSE_CMD="${DOCKER_COMPOSE} -f ${COMPOSE_FILE}" +echo ${DOCKER_COMPOSE_CMD} + +# 1. setup l1 +# 2. run & init erigon pp +start_local_xlayer_erigon() { + export ENV=local + make run_erigon + sleep 3 + # Calculate addresses for all actors + OP_BATCHER_ADDR=$(cast wallet a $OP_BATCHER_PRIVATE_KEY) + OP_PROPOSER_ADDR=$(cast wallet a $OP_PROPOSER_PRIVATE_KEY) + OP_CHALLENGER_ADDR=$(cast wallet a $OP_CHALLENGER_PRIVATE_KEY) + + # Wait for L1 node to finish syncing + while [[ "$(cast rpc eth_syncing --rpc-url $L1_RPC_URL)" != "false" ]]; do + echo "Waiting for node to finish syncing..." + sleep 1 + done + + # Fund all actor addresses + for addr in $OP_BATCHER_ADDR $OP_PROPOSER_ADDR $OP_CHALLENGER_ADDR; do + cast send --private-key $RICH_PRIVATE_KEY --value 100ether $addr --legacy --rpc-url $L1_RPC_URL + done +} + +setup_xlayer_erigon() { + if [ "$ENV" = "local" ]; then + echo "Starting local environment setup..." + start_local_xlayer_erigon + elif [ "$ENV" = "testnet" ]; then + echo "Starting ${ENV} environment setup..." + echo "not implemented" + exit 1 + else + echo "Starting ${ENV} environment setup..." + echo "not implemented" + exit 1 + fi +} + +setup_xlayer_erigon diff --git a/test-pp-op/2-deploy-op-contracts.sh b/test-pp-op/2-deploy-op-contracts.sh new file mode 100755 index 0000000000000..bdd7ad90d1cf7 --- /dev/null +++ b/test-pp-op/2-deploy-op-contracts.sh @@ -0,0 +1,322 @@ +#!/bin/bash +set -e +set -x + +source .env +source tools.sh +source utils.sh + +ROOT_DIR=$(git rev-parse --show-toplevel) + +# Set global OP_CONTRACTS_IMAGE_TAG based on environment +if [ "$ENV" = "local" ]; then + # Use local image tag for local environment + DOCKER_NETWORK_ARG="$DOCKER_NETWORK" +else + # Use cert image tag for non-local environments + DOCKER_NETWORK_ARG="host" +fi + +if [ -z "$CHAIN_ID" ]; then + echo "โŒ ERROR: CHAIN_ID is not set. Set it explicitly or derive it from intent.toml before proceeding." + exit 1 +fi +if ! [[ "$CHAIN_ID" =~ ^[0-9]+$ ]]; then + echo "โŒ ERROR: CHAIN_ID must be a numeric value, got: '$CHAIN_ID'" + exit 1 +fi + +cd $PWD_DIR + +deploy_safe() { + echo "=== Deploying Gnosis Safe ===" + + # Use deployer as single owner with threshold 1 + echo "Using deployer as single owner with threshold 1" + + # Execute Safe deployment + SAFE_DEPLOY_OUTPUT=$(docker run --rm \ + --network "$DOCKER_NETWORK" \ + -v "$(pwd)/$CONFIG_DIR:/deployments" \ + -e DEPLOYER_PRIVATE_KEY="$DEPLOYER_PRIVATE_KEY" \ + -w /app/packages/contracts-bedrock \ + "${OP_CONTRACTS_IMAGE_TAG}" \ + forge script --json --broadcast \ + --rpc-url $L1_RPC_URL_IN_DOCKER \ + --private-key $DEPLOYER_PRIVATE_KEY \ + scripts/deploy/DeploySimpleSafe.s.sol:DeploySimpleSafe) + + # Extract Safe address + SAFE_ADDRESS=$(echo "$SAFE_DEPLOY_OUTPUT" | jq -r '.logs[] | select(contains("New Safe L1ProxyAdminSafe deployed at:")) | split(": ")[1]' 2>/dev/null | head -1) + + if [ -z "$SAFE_ADDRESS" ] || [ "$SAFE_ADDRESS" = "null" ]; then + echo "โŒ Failed to deploy Safe" + exit 1 + fi + + echo "โœ… Safe deployed at: $SAFE_ADDRESS" + echo " Owner: $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY)" + echo " Threshold: 1" + + # Update .env file + sed_inplace "s/SAFE_ADDRESS=.*/SAFE_ADDRESS=$SAFE_ADDRESS/" .env + source .env + echo " โœ… Updated SAFE_ADDRESS in .env: $SAFE_ADDRESS" +} + +deploy_transactor() { + # Deploy Transactor contract first + echo "๐Ÿ”ง Deploying Transactor contract..." + + # Debug: Show environment variables + echo "ENV: $ENV" + echo "CHAIN_ID: $CHAIN_ID" + echo "DOCKER_NETWORK: $DOCKER_NETWORK" + echo "L1_RPC_URL_IN_DOCKER: $L1_RPC_URL_IN_DOCKER" + echo "DEPLOYER_PRIVATE_KEY: ${DEPLOYER_PRIVATE_KEY:0:10}..." + echo "ADMIN_OWNER_ADDRESS: $ADMIN_OWNER_ADDRESS" + echo "OP_CONTRACTS_IMAGE_TAG: $OP_CONTRACTS_IMAGE_TAG" + + # Build docker run command with conditional network flag + DOCKER_ARGS=() + DOCKER_ARGS+=("--rm") + DOCKER_ARGS+=("-v" "$(pwd)/$CONFIG_DIR:/deployments") + DOCKER_ARGS+=("-w" "/app/packages/contracts-bedrock") + + if [ "$ENV" = "local" ]; then + DOCKER_ARGS+=("--network" "$DOCKER_NETWORK") + echo "โœ… Using Docker network: $DOCKER_NETWORK" + else + DOCKER_ARGS+=("--network" "host") + echo "โœ… Skipping Docker network (ENV=$ENV)" + fi + + DOCKER_ARGS+=("$OP_CONTRACTS_IMAGE_TAG") + + # Create the forge create command + FORGE_CMD="forge create --json --broadcast --legacy \ + --rpc-url $L1_RPC_URL_IN_DOCKER \ + --private-key $DEPLOYER_PRIVATE_KEY \ + src/periphery/Transactor.sol:Transactor \ + --constructor-args $ADMIN_OWNER_ADDRESS" + + echo "๐Ÿ”ง Executing Docker command..." + echo "Command: docker run ${DOCKER_ARGS[*]} $FORGE_CMD" + + TRANSACTOR_DEPLOY_OUTPUT=$(docker run "${DOCKER_ARGS[@]}" $FORGE_CMD) + + echo "Raw deployment output:" + echo "$TRANSACTOR_DEPLOY_OUTPUT" + echo "--- End of raw output ---" + + # Extract contract address from deployment output + TRANSACTOR_ADDRESS=$(echo "$TRANSACTOR_DEPLOY_OUTPUT" | jq -r '.deployedTo // empty' 2>/dev/null || echo "") + if [ -z "$TRANSACTOR_ADDRESS" ] || [ "$TRANSACTOR_ADDRESS" = "null" ]; then + echo "โŒ Failed to extract Transactor contract address from deployment output" + echo "Deployment output: $TRANSACTOR_DEPLOY_OUTPUT" + echo "Trying to extract address manually..." + + # Try alternative extraction methods for forge output + TRANSACTOR_ADDRESS=$(echo "$TRANSACTOR_DEPLOY_OUTPUT" | jq -r '.deployedTo' 2>/dev/null || echo "") + if [ -z "$TRANSACTOR_ADDRESS" ]; then + TRANSACTOR_ADDRESS=$(echo "$TRANSACTOR_DEPLOY_OUTPUT" | grep -o '"deployedTo":"[^"]*"' | cut -d'"' -f4 || echo "") + fi + if [ -z "$TRANSACTOR_ADDRESS" ]; then + TRANSACTOR_ADDRESS=$(echo "$TRANSACTOR_DEPLOY_OUTPUT" | grep -o '0x[a-fA-F0-9]\{40\}' | head -1 || echo "") + fi + + if [ -z "$TRANSACTOR_ADDRESS" ]; then + echo "โŒ Still failed to extract contract address" + exit 1 + else + echo "โœ… Extracted address manually: $TRANSACTOR_ADDRESS" + fi + fi + + echo "โœ… Transactor contract deployed at: $TRANSACTOR_ADDRESS" + + # Update .env file with Transactor address + sed_inplace "s/TRANSACTOR=.*/TRANSACTOR=$TRANSACTOR_ADDRESS/" .env + source .env + echo "โœ… Updated TRANSACTOR address in .env: $TRANSACTOR_ADDRESS" +} + +# Bootstrapping superchain with op-deployer +# Output: after deploy, it will output `superchain.json` under config-op +# e.g. { +# "protocolVersionsImplAddress": "0x37e15e4d6dffa9e5e320ee1ec036922e563cb76c", +# "protocolVersionsProxyAddress": "0xfb5a7622e23e0f807b97a8ed608d50d56d202688", +# "superchainConfigImplAddress": "0xce28685eb204186b557133766eca00334eb441e4", +# "superchainConfigProxyAddress": "0x8c15b9d397b5bf29e114aebff0663fdd34976756", +# "proxyAdminAddress": "0x210879bec4c74c7e4e6df5e919f9525d75e15183" +# } +deploy_op_stack_bootstrap_superchain() { + source .env + echo "๐Ÿ”ง Bootstrapping superchain with op-deployer..." + + # Build docker run command with conditional network flag + DOCKER_ARGS=() + DOCKER_ARGS+=("-v" "$(pwd)/$CONFIG_DIR:/deployments") + DOCKER_ARGS+=("-w" "/app") + DOCKER_ARGS+=("-e" "CURL_CA_BUNDLE=") + DOCKER_ARGS+=("-e" "GIT_SSL_NO_VERIFY=true") + DOCKER_ARGS+=("-e" "NODE_TLS_REJECT_UNAUTHORIZED=0") + DOCKER_ARGS+=("-e" "GODEBUG=x509ignoreCN=1,x509ignoreUnknownCA=1,x509ignoreSystemRoots=1") + DOCKER_ARGS+=("--network" "$DOCKER_NETWORK_ARG") + + DOCKER_ARGS+=("$OP_CONTRACTS_IMAGE_TAG") + + BASH_CMD="set -e && /app/op-deployer/bin/op-deployer bootstrap superchain --l1-rpc-url $L1_RPC_URL_IN_DOCKER --private-key $DEPLOYER_PRIVATE_KEY --artifacts-locator file:///app/packages/contracts-bedrock/forge-artifacts --superchain-proxy-admin-owner $L1_PROXY_ADMIN_OWNER --protocol-versions-owner $ADMIN_OWNER_ADDRESS --guardian $ADMIN_OWNER_ADDRESS --outfile /deployments/superchain.json" + + docker run "${DOCKER_ARGS[@]}" bash -c "$BASH_CMD" +} + +deploy_op_stack_bootstrap_implementations() { + source .env + echo "๐Ÿ”ง Bootstrapping implementations with op-deployer..." + SUPERCHAIN_JSON="$CONFIG_DIR/superchain.json" + PROTOCOL_VERSIONS_PROXY=$(jq -r '.protocolVersionsProxyAddress' "$SUPERCHAIN_JSON") + SUPERCHAIN_CONFIG_PROXY=$(jq -r '.superchainConfigProxyAddress' "$SUPERCHAIN_JSON") + PROXY_ADMIN=$(jq -r '.proxyAdminAddress' "$SUPERCHAIN_JSON") + # Build docker run command with conditional network flag + DOCKER_ARGS=() + DOCKER_ARGS+=("-v" "$(pwd)/$CONFIG_DIR:/deployments") + DOCKER_ARGS+=("-w" "/app") + DOCKER_ARGS+=("-e" "CURL_CA_BUNDLE=") + DOCKER_ARGS+=("-e" "GIT_SSL_NO_VERIFY=true") + DOCKER_ARGS+=("-e" "NODE_TLS_REJECT_UNAUTHORIZED=0") + DOCKER_ARGS+=("--network" "$DOCKER_NETWORK_ARG") + + DOCKER_ARGS+=("$OP_CONTRACTS_IMAGE_TAG") + + # Build the base command + BASH_CMD="set -e && export CURL_CA_BUNDLE= && export GIT_SSL_NO_VERIFY=true && /app/op-deployer/bin/op-deployer bootstrap implementations --artifacts-locator file:///app/packages/contracts-bedrock/forge-artifacts --l1-rpc-url $L1_RPC_URL_IN_DOCKER --outfile /deployments/implementations.json --mips-version \"7\" --private-key $DEPLOYER_PRIVATE_KEY --protocol-versions-proxy $PROTOCOL_VERSIONS_PROXY --superchain-config-proxy $SUPERCHAIN_CONFIG_PROXY --superchain-proxy-admin $PROXY_ADMIN --upgrade-controller $ADMIN_OWNER_ADDRESS --challenger $CHALLENGER_ADDRESS --challenge-period-seconds $CHALLENGE_PERIOD_SECONDS --withdrawal-delay-seconds $WITHDRAWAL_DELAY_SECONDS --proof-maturity-delay-seconds $PROOF_MATURITY_DELAY_SECONDS --dispute-game-finality-delay-seconds $DISPUTE_GAME_FINALITY_DELAY_SECONDS" + + # Add dev-feature-bitmap only when CGT_ENABLED=true + if [ "$CGT_ENABLED" = "true" ]; then + BASH_CMD="$BASH_CMD --dev-feature-bitmap 0x0000000000000000000000000000000000000000000000000000000000001000" + fi + + docker run "${DOCKER_ARGS[@]}" bash -c "$BASH_CMD" + + # Update intent.toml + sed_inplace "s/l1ProxyAdminOwner = .*/l1ProxyAdminOwner = \"$L1_PROXY_ADMIN_OWNER\"/" "$CONFIG_DIR/intent.toml" + echo " โœ… Updated intent.toml with $OWNER_TYPE owner: $L1_PROXY_ADMIN_OWNER" + + # Read opcmAddress from implementations.json and write it into intent.toml + OPCM_ADDRESS=$(jq -r '.opcmAddress' ./config-op/implementations.json) + if [ -z "$OPCM_ADDRESS" ] || [ "$OPCM_ADDRESS" = "null" ]; then + echo "โŒ Failed to read opcmAddress from implementations.json" + exit 1 + fi + + # Replace the opcmAddress field in intent.toml with the new value + sed_inplace "s/^opcmAddress = \".*\"/opcmAddress = \"$OPCM_ADDRESS\"/" ./config-op/intent.toml + echo "โœ… Updated opcmAddress ($OPCM_ADDRESS) in intent.toml" +} + +deploy_op_stack_contracts() { + # Deploy contracts, TODO: should we need to modify source code to deploy contracts? + # Build docker run command with conditional network flag + DOCKER_ARGS=() + DOCKER_ARGS+=("-v" "$(pwd)/$CONFIG_DIR:/deployments") + DOCKER_ARGS+=("-w" "/app") + DOCKER_ARGS+=("-e" "CURL_CA_BUNDLE=") + DOCKER_ARGS+=("-e" "GIT_SSL_NO_VERIFY=true") + DOCKER_ARGS+=("-e" "NODE_TLS_REJECT_UNAUTHORIZED=0") + DOCKER_ARGS+=("--network" "$DOCKER_NETWORK_ARG") + + DOCKER_ARGS+=("$OP_CONTRACTS_IMAGE_TAG") + + BASH_CMD="set -e && export CURL_CA_BUNDLE= && export GIT_SSL_NO_VERIFY=true && echo '๐Ÿ”ง Starting contract deployment with op-deployer...' && echo '' && echo 'Deploy using op-deployer, wait for completion before proceeding' && /app/op-deployer/bin/op-deployer apply --workdir /deployments --private-key $DEPLOYER_PRIVATE_KEY --l1-rpc-url $L1_RPC_URL_IN_DOCKER && echo '' && echo '๐Ÿ“„ Generating L2 genesis and rollup config...' && echo '' && echo 'Generate L2 genesis using op-deployer' && /app/op-deployer/bin/op-deployer inspect genesis --workdir /deployments $CHAIN_ID > /deployments/genesis.json && echo '' && echo 'Generate L2 rollup using op-node' && /app/op-deployer/bin/op-deployer inspect rollup --workdir /deployments $CHAIN_ID > /deployments/rollup.json && echo '' && echo 'โœ… Contract deployment completed successfully'" + + docker run "${DOCKER_ARGS[@]}" bash -c "$BASH_CMD" + + echo "genesis.json and rollup.json are generated in deployments folder" + echo "๐ŸŽ‰ OP Stack deployment preparation completed!" +} + +deploy_custom_gas_token() { + echo "๐Ÿ”ง Setting up Custom Gas Token (CGT) configuration..." + echo "" + + SYSTEM_CONFIG_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].SystemConfigProxy' "$CONFIG_DIR/state.json") + OPTIMISM_PORTAL_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].OptimismPortalProxy' "$CONFIG_DIR/state.json") + + if [ -z "$SYSTEM_CONFIG_PROXY_ADDRESS" ] || [ "$SYSTEM_CONFIG_PROXY_ADDRESS" = "null" ]; then + echo "โŒ Failed to read systemConfigProxyAddress from state.json" + exit 1 + fi + if [ -z "$OPTIMISM_PORTAL_PROXY_ADDRESS" ] || [ "$OPTIMISM_PORTAL_PROXY_ADDRESS" = "null" ]; then + echo "โŒ Failed to read optimismPortalProxyAddress from state.json" + exit 1 + fi + echo "๐Ÿ“ Running Foundry setup script for Custom Gas Token..." + + cd $ROOT_DIR/packages/contracts-bedrock + export SYSTEM_CONFIG_PROXY_ADDRESS=$SYSTEM_CONFIG_PROXY_ADDRESS + export OPTIMISM_PORTAL_PROXY_ADDRESS=$OPTIMISM_PORTAL_PROXY_ADDRESS + + FORGE_OUTPUT=$(forge script scripts/SetupCustomGasToken.s.sol:SetupCustomGasToken \ + --rpc-url "$L1_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast 2>&1) + + echo "$FORGE_OUTPUT" + + # Extract contract addresses from forge output + OKB_TOKEN=$(echo "$FORGE_OUTPUT" | grep "MockOKB deployed at:" | awk '{print $NF}') + ADAPTER_ADDRESS=$(echo "$FORGE_OUTPUT" | grep "DepositedOKBAdapter deployed at:" | awk '{print $NF}') + + # Query initial OKB total supply + INIT_TOTAL_SUPPLY=$(cast call "$OKB_TOKEN" "totalSupply()(uint256)" --rpc-url "$L1_RPC_URL") + echo "" + echo "๐Ÿ“Š Initial OKB Total Supply: $INIT_TOTAL_SUPPLY" + + echo "" + echo "โœ… L1 Custom Gas Token setup complete!" + echo "" + echo "๐Ÿ“‹ Deployed Contract Addresses:" + echo " OKB Token: $OKB_TOKEN" + echo " Adapter: $ADAPTER_ADDRESS" + echo "" + +} + +echo "CGT_ENABLED: ${CGT_ENABLED}" + +cp ./config-op/intent.${ENV}.toml.bak ./config-op/intent.toml +cp ./config-op/state.json.bak ./config-op/state.json + +CHAIN_ID_UINT256=$(cast to-uint256 $CHAIN_ID) +sed_inplace 's/id = .*/id = "'"$CHAIN_ID_UINT256"'"/' ./config-op/intent.toml +echo " โœ… Updated chain id in intent.toml: $CHAIN_ID_UINT256" + +# Validate OWNER_TYPE configuration +if [ "$OWNER_TYPE" != "transactor" ] && [ "$OWNER_TYPE" != "safe" ]; then + echo "โŒ Error: Invalid OWNER_TYPE '$OWNER_TYPE'. Must be 'transactor' or 'safe'" + exit 1 +fi + +echo "=== Deploying with OWNER_TYPE: $OWNER_TYPE ===" + +# Deploy owner contract based on OWNER_TYPE +if [ "$OWNER_TYPE" = "safe" ]; then + echo "๐Ÿ”ง Deploying Gnosis Safe for l1ProxyAdminOwner..." + deploy_safe + L1_PROXY_ADMIN_OWNER=$SAFE_ADDRESS +elif [ "$OWNER_TYPE" = "transactor" ]; then + echo "๐Ÿ”ง Deploying Transactor for l1ProxyAdminOwner..." + deploy_transactor + L1_PROXY_ADMIN_OWNER=$TRANSACTOR_ADDRESS +fi + +echo "Using $OWNER_TYPE as l1ProxyAdminOwner: $L1_PROXY_ADMIN_OWNER" + +deploy_op_stack_bootstrap_superchain +deploy_op_stack_bootstrap_implementations +deploy_op_stack_contracts + +if [ "$CGT_ENABLED" = "true" ]; then + deploy_custom_gas_token +fi diff --git a/test-pp-op/3-stop-erigon.sh b/test-pp-op/3-stop-erigon.sh new file mode 100755 index 0000000000000..5a6b2845f2b53 --- /dev/null +++ b/test-pp-op/3-stop-erigon.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -x +set -e +source .env +source tools.sh +source utils.sh + +cd $PWD_DIR + +## Stop X Layer services +echo "DOCKER_COMPOSE_CMD: ${DOCKER_COMPOSE_CMD}" +${DOCKER_COMPOSE_CMD} stop xlayer-seq +#${DOCKER_COMPOSE_CMD} stop xlayer-rpc +${DOCKER_COMPOSE_CMD} stop xlayer-bridge-service +${DOCKER_COMPOSE_CMD} stop xlayer-bridge-ui +${DOCKER_COMPOSE_CMD} stop xlayer-agg-sender + +# Get fork block number and parent hash +LOG_OUTPUT=$(docker logs xlayer-seq 2>&1) +FORK_BLOCK=$(echo "$LOG_OUTPUT" | grep "Finish block" | tail -1 | sed -n 's/.*Finish block \([0-9]*\) with.*/\1/p') + +echo "FORK_BLOCK=$FORK_BLOCK" + +sed_inplace "s/FORK_BLOCK=.*/FORK_BLOCK=$((FORK_BLOCK+1))/" .env +PARENT_HASH=$(echo "$LOG_OUTPUT" | grep "RPC Daemon notified of new headers" | tail -1 | sed -n 's/.*hash=\([0-9a-fx]*\) .*/\1/p') +echo "PARENT_HASH=$PARENT_HASH" +sed_inplace "s/PARENT_HASH=.*/PARENT_HASH=$PARENT_HASH/" .env diff --git a/test-pp-op/4-migrate-op.sh b/test-pp-op/4-migrate-op.sh new file mode 100755 index 0000000000000..fe9ab58525946 --- /dev/null +++ b/test-pp-op/4-migrate-op.sh @@ -0,0 +1,177 @@ +#!/bin/bash +set -x +set -e +source .env +source tools.sh +source utils.sh + + +prepare() { + # Check if FORK_BLOCK is set + if [ -z "$FORK_BLOCK" ]; then + echo " โŒ FORK_BLOCK environment variable is not set" + echo "Please set FORK_BLOCK in your .env file" + exit 1 + fi + + # Check required files exist + if [ ! -f "./config-op/genesis.json" ]; then + echo "โŒ ERROR: ./config-op/genesis.json not found!" + exit 1 + fi + + if [ ! -f "./config-op/rollup.json" ]; then + echo "โŒ ERROR: ./config-op/rollup.json not found!" + exit 1 + fi + + cp ./config-op/genesis.json ./config-op/genesis-op-raw.json + cp ./config-op/genesis.json ./config-op/genesis-op-before-number.json + + jq '.config.legacyXLayerBlock = '"$FORK_BLOCK" ./config-op/genesis.json > temp_genesis.json && mv temp_genesis.json ./config-op/genesis.json + sed_inplace 's/"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"/"parentHash": "'"$PARENT_HASH"'"/' ./config-op/genesis.json + jq '.genesis.l2.number = '"$FORK_BLOCK" ./config-op/rollup.json > temp_rollup.json && mv temp_rollup.json ./config-op/rollup.json + + cp ./config-op/genesis.json ./config-op/genesis-op-after-number.json + + # Extract contract addresses from state.json and update .env file + echo "๐Ÿ”ง Extracting contract addresses from state.json..." + STATE_JSON="$PWD_DIR/config-op/state.json" + + if [ -f "$STATE_JSON" ]; then + # Extract contract addresses from state.json + DEPLOYMENTS_TYPE=$(jq -r 'type' "$STATE_JSON") + if [ "$DEPLOYMENTS_TYPE" = "object" ]; then + OPCD_TYPE=$(jq -r '.opChainDeployments | type' "$STATE_JSON" 2>/dev/null) + if [ "$OPCD_TYPE" = "object" ]; then + DISPUTE_GAME_FACTORY_ADDRESS=$(jq -r '.opChainDeployments.DisputeGameFactoryProxy // empty' "$STATE_JSON") + L2OO_ADDRESS=$(jq -r '.opChainDeployments.L2OutputOracleProxy // empty' "$STATE_JSON") + OPCM_IMPL_ADDRESS=$(jq -r '.appliedIntent.opcmAddress // empty' "$STATE_JSON") + SYSTEM_CONFIG_PROXY_ADDRESS=$(jq -r '.opChainDeployments.SystemConfigProxy // empty' "$STATE_JSON") + PROXY_ADMIN=$(jq -r '.superchainContracts.SuperchainProxyAdminImpl // empty' "$STATE_JSON") + OPTIMISM_PORTAL_PROXY_ADDRESS=$(jq -r '.opChainDeployments.OptimismPortalProxy // empty' "$STATE_JSON") + elif [ "$OPCD_TYPE" = "array" ]; then + DISPUTE_GAME_FACTORY_ADDRESS=$(jq -r '.opChainDeployments[0].DisputeGameFactoryProxy // empty' "$STATE_JSON") + L2OO_ADDRESS=$(jq -r '.opChainDeployments[0].L2OutputOracleProxy // empty' "$STATE_JSON") + OPCM_IMPL_ADDRESS=$(jq -r '.appliedIntent.opcmAddress // empty' "$STATE_JSON") + SYSTEM_CONFIG_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].SystemConfigProxy // empty' "$STATE_JSON") + PROXY_ADMIN=$(jq -r '.superchainContracts.SuperchainProxyAdminImpl // empty' "$STATE_JSON") + OPTIMISM_PORTAL_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].OptimismPortalProxy // empty' "$STATE_JSON") + else + DISPUTE_GAME_FACTORY_ADDRESS="" + L2OO_ADDRESS="" + OPCM_IMPL_ADDRESS="" + SYSTEM_CONFIG_PROXY_ADDRESS="" + PROXY_ADMIN="" + OPTIMISM_PORTAL_PROXY_ADDRESS="" + fi + + # Update .env if found + if [ -n "$DISPUTE_GAME_FACTORY_ADDRESS" ]; then + echo "โœ… Found DisputeGameFactoryProxy address: $DISPUTE_GAME_FACTORY_ADDRESS" + sed_inplace "s/DISPUTE_GAME_FACTORY_ADDRESS=.*/DISPUTE_GAME_FACTORY_ADDRESS=$DISPUTE_GAME_FACTORY_ADDRESS/" .env + else + echo "โš ๏ธ DisputeGameFactoryProxy address not found in opChainDeployments" + fi + + if [ -n "$L2OO_ADDRESS" ]; then + echo "โœ… Found L2OutputOracleProxy address: $L2OO_ADDRESS" + sed_inplace "s/L2OO_ADDRESS=.*/L2OO_ADDRESS=$L2OO_ADDRESS/" .env + else + echo "โš ๏ธ L2OutputOracleProxy address not found in opChainDeployments" + fi + + if [ -n "$OPCM_IMPL_ADDRESS" ]; then + echo "โœ… Found opcmAddress address: $OPCM_IMPL_ADDRESS" + sed_inplace "s/OPCM_IMPL_ADDRESS=.*/OPCM_IMPL_ADDRESS=$OPCM_IMPL_ADDRESS/" .env + else + echo "โš ๏ธ opcmAddress address not found in opChainDeployments" + fi + + if [ -n "$SYSTEM_CONFIG_PROXY_ADDRESS" ]; then + echo "โœ… Found SystemConfigProxy address: $SYSTEM_CONFIG_PROXY_ADDRESS" + sed_inplace "s/SYSTEM_CONFIG_PROXY_ADDRESS=.*/SYSTEM_CONFIG_PROXY_ADDRESS=$SYSTEM_CONFIG_PROXY_ADDRESS/" .env + else + echo "โš ๏ธ SystemConfigProxy address not found in opChainDeployments" + fi + + if [ -n "$OPTIMISM_PORTAL_PROXY_ADDRESS" ]; then + echo " โœ… Found OptimismPortalProxy address: $OPTIMISM_PORTAL_PROXY_ADDRESS" + sed_inplace "s/OPTIMISM_PORTAL_PROXY_ADDRESS=.*/OPTIMISM_PORTAL_PROXY_ADDRESS=$OPTIMISM_PORTAL_PROXY_ADDRESS/" .env + else + echo " โš ๏ธ OptimismPortalProxy address not found in opChainDeployments" + fi + + if [ -n "$PROXY_ADMIN" ]; then + echo "โœ… Found ProxyAdmin address: $PROXY_ADMIN" + sed_inplace "s/PROXY_ADMIN=.*/PROXY_ADMIN=$PROXY_ADMIN/" .env + else + echo "โš ๏ธ ProxyAdmin address not found in opChainDeployments" + fi + + # Show summary + echo "๐Ÿ“„ Contract addresses updated in .env:" + echo " DISPUTE_GAME_FACTORY_ADDRESS=$DISPUTE_GAME_FACTORY_ADDRESS" + echo " L2OO_ADDRESS=$L2OO_ADDRESS" + echo " OPCM_IMPL_ADDRESS=$OPCM_IMPL_ADDRESS" + echo " SYSTEM_CONFIG_PROXY_ADDRESS=$SYSTEM_CONFIG_PROXY_ADDRESS" + echo " OPTIMISM_PORTAL_PROXY_ADDRESS=$OPTIMISM_PORTAL_PROXY_ADDRESS" + echo " PROXY_ADMIN=$PROXY_ADMIN" + else + echo "โŒ $STATE_JSON is not a valid JSON object" + fi + else + echo "โŒ state.json not found at $STATE_JSON" + fi +} + + +migrate() { + export OP_DATA_DIR=./data/op-geth-seq + export OP_GENESIS_PATH=${PWD_DIR}/config-op/genesis-op-after-number.json + + if [ "$ENV" = "local" ]; then + ERIGON_CHAINDATA_DIR=${PWD_DIR}/data/rpc/chaindata/ + ERIGON_SMTDATA_DIR=${PWD_DIR}/data/rpc/smt/ + else + ERIGON_CHAINDATA_DIR=/data/erigon-data/chaindata/ + ERIGON_SMTDATA_DIR=/data/erigon-data/smt/ + fi + + if [[ "$OSTYPE" == "darwin"* ]]; then + export GETH_CMD=$(go env GOPATH)/bin/geth + + if [ ! -f ${GETH_CMD} ]; then + cd ./tmp/op-geth + make geth + sudo cp ./build/bin/geth /usr/local/bin/geth + cd $PWD_DIR + else + echo "โœ… geth found at optimism/op-geth/build/bin" + fi + else + export GETH_CMD=geth + echo "โœ… Using Linux geth path: $GETH_CMD" + fi + + echo "GETH_CMD: $GETH_CMD" + ${GETH_CMD} --datadir=${OP_DATA_DIR} --gcmode=archive migrate --state.scheme=hash --ignore-addresses=0x000000000000000000000000000000005ca1ab1e --chaindata=${ERIGON_CHAINDATA_DIR} --smt-db-path=${ERIGON_SMTDATA_DIR} --no-verify --output merged.genesis.json ${OP_GENESIS_PATH} 2>&1 | tee migrate.log + + sleep 5 + + LOG_BLOCK=$(grep -A 5 "Update rollup.json file with the following information l2" migrate.log | tail -n 5) + L2_NUMBER=$(echo "$LOG_BLOCK" | grep '"number"' | sed 's/[^0-9]*\([0-9]*\).*/\1/') + L2_HASH=$(echo "$LOG_BLOCK" | grep '"hash"' | sed 's/.*"\(0x[0-9a-fA-F]*\)".*/\1/') + echo "L2_NUMBER: $L2_NUMBER" + echo "L2_HASH: $L2_HASH" + + jq --argjson num "$L2_NUMBER" --arg hash "$L2_HASH" \ + '.genesis.l2.number = $num | .genesis.l2.hash = $hash' \ + config-op/rollup.json > config-op/rollup.json.tmp && mv config-op/rollup.json.tmp config-op/rollup.json + + echo "finished migrate op-geth" +} + +cd $PWD_DIR +prepare +migrate diff --git a/test-pp-op/5-start-op.sh b/test-pp-op/5-start-op.sh new file mode 100755 index 0000000000000..62ff8b6c8c18f --- /dev/null +++ b/test-pp-op/5-start-op.sh @@ -0,0 +1,168 @@ +set -e +set -x +source .env +source utils.sh +source tools.sh + +PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(dirname "$PWD_DIR")" +SCRIPTS_DIR=$ROOT_DIR/test/scripts + +start_sequencer() { + rm -rf "$OP_GETH_DATADIR2" + cp -r "$OP_GETH_DATADIR" "$OP_GETH_DATADIR2" + + rm -rf "$OP_GETH_DATADIR3" + cp -r "$OP_GETH_DATADIR" "$OP_GETH_DATADIR3" + + if [ "$ENV" = "testnet" ];then + L1_RPC_URL="https://fullnode-inner.okg.com/sepolia/fork/okbc/rpc" + L1_BEACON_URL_IN_DOCKER="https://fullnode-inner.okg.com/ethsepoliabeacon/native/layer1/rpc" + sed_inplace "s|L1_RPC_URL=.*|L1_RPC_URL=$L1_RPC_URL|" .env + sed_inplace "s|L1_RPC_URL_IN_DOCKER=.*|L1_RPC_URL_IN_DOCKER=$L1_RPC_URL|" .env + sed_inplace "s|L1_BEACON_URL_IN_DOCKER=.*|L1_BEACON_URL_IN_DOCKER=$L1_BEACON_URL_IN_DOCKER|" .env + fi + + if [ "$CONDUCTOR_ENABLED" = "true" ]; then + ${DOCKER_COMPOSE_CMD} up -d op-conductor + ${DOCKER_COMPOSE_CMD} up -d op-conductor2 + ${DOCKER_COMPOSE_CMD} up -d op-conductor3 + sleep 3 + $SCRIPTS_DIR/active-sequencer.sh + else + ${DOCKER_COMPOSE_CMD} up -d op-seq + fi + + # Check for L2 genesis hash mismatch + LOG_OUTPUT=$(${DOCKER_COMPOSE_CMD} logs op-seq 2>&1 | tail -20) + if echo "$LOG_OUTPUT" | grep -q "expected L2 genesis hash to match L2 block at genesis block number"; then + echo "โŒ L2 genesis hash mismatch detected!" + echo "Error details:" + echo "$LOG_OUTPUT" | grep "expected L2 genesis hash to match L2 block at genesis block number" + exit 1 + fi +} + +start_rpc() { + rm -rf "$OP_GETH_RPC_DATADIR" + cp -r "$OP_GETH_DATADIR" "$OP_GETH_RPC_DATADIR" + ${DOCKER_COMPOSE_CMD} up -d op-rpc +} + +connect_static_peers() { + + # Setup P2P static connections between op-geth nodes + echo "๐Ÿ”— Setting up P2P static connections between op-geth nodes..." + + # Get enodes for all op-geth containers + echo "๐Ÿ“ก Getting enode addresses..." + + # Get enodes + OP_GETH_SEQ_ENODE=$(get_enode "op-geth-seq" "8545") + OP_GETH_RPC_ENODE=$(get_enode "op-geth-rpc" "8545") + + if [ "$CONDUCTOR_ENABLED" = "true" ]; then + OP_GETH_SEQ2_ENODE=$(get_enode "op-geth-seq2" "8545") + OP_GETH_SEQ3_ENODE=$(get_enode "op-geth-seq3" "8545") + fi + + # Replace 127.0.0.1 with container names + OP_GETH_SEQ_ENODE=$(replace_enode_ip "$OP_GETH_SEQ_ENODE" "op-geth-seq") + OP_GETH_RPC_ENODE=$(replace_enode_ip "$OP_GETH_RPC_ENODE" "op-geth-rpc") + + if [ "$CONDUCTOR_ENABLED" = "true" ]; then + OP_GETH_SEQ2_ENODE=$(replace_enode_ip "$OP_GETH_SEQ2_ENODE" "op-geth-seq2") + OP_GETH_SEQ3_ENODE=$(replace_enode_ip "$OP_GETH_SEQ3_ENODE" "op-geth-seq3") + fi + + echo "โœ… Enode addresses:" + echo " op-geth-seq: $OP_GETH_SEQ_ENODE" + echo " op-geth-rpc: $OP_GETH_RPC_ENODE" + if [ "$CONDUCTOR_ENABLED" = "true" ]; then + echo " op-geth-seq2: $OP_GETH_SEQ2_ENODE" + echo " op-geth-seq3: $OP_GETH_SEQ3_ENODE" + fi + + + # Setup static connections between sequencer nodes + echo "๐Ÿ”— Setting up static connections between sequencer nodes..." + + # Add peers to op-geth-seq (connect to other sequencers) + echo "๐Ÿ”— Setting up peers for op-geth-seq..." + if [ "$CONDUCTOR_ENABLED" = "true" ]; then + add_peer "op-geth-seq" "$OP_GETH_SEQ2_ENODE" + add_peer "op-geth-seq" "$OP_GETH_SEQ3_ENODE" + fi + + if [ "$CONDUCTOR_ENABLED" = "true" ]; then + # Add peers to op-geth-seq2 (connect to other sequencers) + echo "๐Ÿ”— Setting up peers for op-geth-seq2..." + add_peer "op-geth-seq2" "$OP_GETH_SEQ_ENODE" + add_peer "op-geth-seq2" "$OP_GETH_SEQ3_ENODE" + + # Add peers to op-geth-seq3 (connect to other sequencers) + echo "๐Ÿ”— Setting up peers for op-geth-seq3..." + add_peer "op-geth-seq3" "$OP_GETH_SEQ_ENODE" + add_peer "op-geth-seq3" "$OP_GETH_SEQ2_ENODE" + fi + + # Setup RPC node to connect to all sequencer nodes + echo "๐Ÿ”— Setting up RPC node to connect to all sequencer nodes..." + add_peer "op-geth-rpc" "$OP_GETH_SEQ_ENODE" + if [ "$CONDUCTOR_ENABLED" = "true" ]; then + add_peer "op-geth-rpc" "$OP_GETH_SEQ2_ENODE" + add_peer "op-geth-rpc" "$OP_GETH_SEQ3_ENODE" + fi + + echo "โœ… P2P static connections established:" + echo " - Sequencer nodes (op-geth-seq, op-geth-seq2, op-geth-seq3) are connected to each other" + echo " - RPC node (op-geth-rpc) is connected to all sequencer nodes" + +} + +# Function to get enode from a geth container +get_enode() { + local container_name=$1 + local rpc_port=$2 + local enode=$(docker exec $container_name geth attach --exec "admin.nodeInfo.enode" --datadir /datadir 2>/dev/null | tr -d '"') + echo "$enode" +} + +# Function to replace 127.0.0.1 with container name in enode +replace_enode_ip() { + local enode=$1 + local container_name=$2 + echo "$enode" | sed "s/@127.0.0.1:/@$container_name:/" +} + +# Function to add peer to a geth container +add_peer() { + local container_name=$1 + local peer_enode=$2 + echo "๐Ÿ”— Adding peer to $container_name: $peer_enode" + docker exec $container_name geth attach --exec "admin.addPeer('$peer_enode')" --datadir /datadir 2>/dev/null +} + +start_batcher() { + # Configure op-batcher endpoints based on conductor mode + if [ "$CONDUCTOR_ENABLED" = "true" ]; then + echo "๐Ÿ”ง Configuring op-batcher for conductor mode with conductor RPC endpoints..." + # Set conductor mode endpoints + export OP_BATCHER_L2_ETH_RPC="http://op-conductor:8547,http://op-conductor2:8547,http://op-conductor3:8547" + export OP_BATCHER_ROLLUP_RPC="http://op-conductor:8547,http://op-conductor2:8547,http://op-conductor3:8547" + echo "โœ… op-batcher configured for conductor mode (connecting to conductor RPC endpoints)" + else + echo "๐Ÿ”ง Configuring op-batcher for single sequencer mode..." + # Set single sequencer mode endpoints + export OP_BATCHER_L2_ETH_RPC="http://op-geth-seq:8545" + export OP_BATCHER_ROLLUP_RPC="http://op-seq:9545" + echo "โœ… op-batcher configured for single sequencer mode" + fi + + ${DOCKER_COMPOSE_CMD} up -d op-batcher +} + +start_sequencer +start_rpc +connect_static_peers +start_batcher diff --git a/test-pp-op/6-build-op-program.sh b/test-pp-op/6-build-op-program.sh new file mode 100755 index 0000000000000..867ec1be3d168 --- /dev/null +++ b/test-pp-op/6-build-op-program.sh @@ -0,0 +1,174 @@ +#!/bin/bash +set -x +set -e +source .env +source tools.sh + +PWD_DIR=$(pwd) + +if [ -z "$CHAIN_ID" ]; then + echo "โŒ ERROR: CHAIN_ID is not set. Set it explicitly or derive it from intent.toml before proceeding." + exit 1 +fi +if ! [[ "$CHAIN_ID" =~ ^[0-9]+$ ]]; then + echo "โŒ ERROR: CHAIN_ID must be a numeric value, got: '$CHAIN_ID'" + exit 1 +fi +# Function to show usage +show_usage() { + echo "Usage: $0 [OPTIONS]" + echo "Options:" + echo " -a, --arch ARCH Target architecture (x86|arm|amd64|arm64)" + echo " Default: auto-detect from OSTYPE" + echo " -h, --help Show this help message" + echo "" + echo "Architecture mapping:" + echo " x86/amd64 -> linux/amd64" + echo " arm/arm64 -> linux/arm64" + echo "" + echo "Current OSTYPE: $OSTYPE" +} + +# Default architecture detection based on OSTYPE +detect_arch() { + case "$OSTYPE" in + *darwin*) + if [[ $(uname -m) == "arm64" ]]; then + echo "linux/arm64" + else + echo "linux/amd64" + fi + ;; + *linux*) + if [[ $(uname -m) == "aarch64" ]] || [[ $(uname -m) == "arm64" ]]; then + echo "linux/arm64" + else + echo "linux/amd64" + fi + ;; + *) + echo "linux/amd64" # Default fallback + ;; + esac +} + +# Parse command line arguments +DOCKER_PLATFORM="" +while [[ $# -gt 0 ]]; do + case $1 in + -a|--arch) + case "$2" in + x86|amd64) + DOCKER_PLATFORM="linux/amd64" + ;; + arm|arm64) + DOCKER_PLATFORM="linux/arm64" + ;; + *) + echo "Error: Invalid architecture '$2'" + echo "Valid options: x86, amd64, arm, arm64" + exit 1 + ;; + esac + shift 2 + ;; + -h|--help) + show_usage + exit 0 + ;; + *) + echo "Error: Unknown option '$1'" + show_usage + exit 1 + ;; + esac +done + +# Set default platform if not specified +if [ -z "$DOCKER_PLATFORM" ]; then + DOCKER_PLATFORM=$(detect_arch) + echo "Auto-detected platform: $DOCKER_PLATFORM" +else + echo "Using specified platform: $DOCKER_PLATFORM" +fi + +post_migrate() { + # Check if genesis.json exists, panic if it doesn't + if [ ! -f "merged.genesis.json" ]; then + echo "ERROR: merged.genesis.json does not exist!" + echo "Please ensure the genesis.json file is present before running this script." + exit 1 + fi + + $MD5SUM_CMD merged.genesis.json + # genesis.json is too large to embed in go, so we compress it now and decompress it in go code + gzip -c merged.genesis.json > config-op/merged.genesis.gz.json + + # Ensure prestate files exist and devnetL1.json is consistent before deploying contracts + EXPORT_DIR="$PWD_DIR/data/cannon-data" + rm -rf $EXPORT_DIR + mkdir -p $EXPORT_DIR + + # Set network based on ENV + if [ "$ENV" = "local" ]; then + DOCKER_NETWORK_ARG="--network ${DOCKER_NETWORK}" + else + DOCKER_NETWORK_ARG="--network host" + fi + + ROOTLESS_DOCKER=$(docker info -f "{{println .SecurityOptions}}" | grep rootless || true) + + if ! [ -z "$ROOTLESS_DOCKER" ]; then + docker run -it --privileged \ + --platform $DOCKER_PLATFORM \ + -v "$(pwd)/scripts:/scripts" \ + -v "$(pwd)/config-op/rollup.json:/app/op-program/chainconfig/configs/${CHAIN_ID}-rollup.json" \ + -v "$(pwd)/config-op/merged.genesis.gz.json:/app/op-program/chainconfig/configs/${CHAIN_ID}-genesis-l2.json" \ + -v "$(pwd)/l1-geth/execution/genesis.json:/app/op-program/chainconfig/configs/1337-genesis-l1.json" \ + -v "$EXPORT_DIR:/app/op-program/bin" \ + --name op-program \ + -w /app \ + ${DOCKER_NETWORK_ARG} \ + "${OP_STACK_IMAGE_TAG}" \ + bash -c " + echo '๐Ÿ“Š Verifying Docker connection:' + /scripts/dind-install-start.sh + docker --version + docker ps --format 'table {{.Names}}\t{{.Status}}' | head -3 + + echo '๐Ÿš€ Running make reproducible-prestate...' + make reproducible-prestate + + echo '๐Ÿ“ Checking contents of op-program/bin:' + ls -la /app/op-program/bin/ || echo 'Directory is empty or does not exist' + " + else + docker run -it \ + --platform $DOCKER_PLATFORM \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v "$(pwd)/config-op/rollup.json:/app/op-program/chainconfig/configs/${CHAIN_ID}-rollup.json" \ + -v "$(pwd)/config-op/merged.genesis.gz.json:/app/op-program/chainconfig/configs/${CHAIN_ID}-genesis-l2.json" \ + -v "$(pwd)/l1-geth/execution/genesis.json:/app/op-program/chainconfig/configs/1337-genesis-l1.json" \ + -v "$EXPORT_DIR:/app/op-program/bin" \ + --name op-program \ + -w /app \ + ${DOCKER_NETWORK_ARG} \ + -e DOCKER_HOST=unix:///var/run/docker.sock \ + "${OP_STACK_IMAGE_TAG}" \ + bash -c " + echo '๐Ÿ“Š Verifying Docker connection:' + apt-get update + apt-get install docker.io -y + docker --version + docker ps --format 'table {{.Names}}\t{{.Status}}' | head -3 + + echo '๐Ÿš€ Running make reproducible-prestate...' + make reproducible-prestate + + echo '๐Ÿ“ Checking contents of op-program/bin:' + ls -la /app/op-program/bin/ || echo 'Directory is empty or does not exist' + " + fi +} + +post_migrate diff --git a/test-pp-op/7-setup-fraud-proof.sh b/test-pp-op/7-setup-fraud-proof.sh new file mode 100755 index 0000000000000..2dad87ecf5731 --- /dev/null +++ b/test-pp-op/7-setup-fraud-proof.sh @@ -0,0 +1,505 @@ +#!/bin/bash +set -e +set -x + +source .env +source tools.sh + +if [ "$ENV" = "testnet" ];then + shopt -s expand_aliases + alias cast='docker run --rm --network host op-migrate:amd64 cast' +fi + +PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd $PWD_DIR +EXPORT_DIR="$PWD_DIR/data/cannon-data" + +# Get prestate value from prestate-proof-mt64.json +ABSOLUTE_PRESTATE=$(jq -r '.pre' "$EXPORT_DIR/prestate-proof-mt64.json") + +# Validate OWNER_TYPE configuration +if [ "$OWNER_TYPE" != "transactor" ] && [ "$OWNER_TYPE" != "safe" ]; then + echo "โŒ Error: Invalid OWNER_TYPE '$OWNER_TYPE'. Must be 'transactor' or 'safe'" + exit 1 +fi + +echo "=== Using OWNER_TYPE: $OWNER_TYPE ===" + +# Function to add game type via Safe +add_game_type_via_safe() { + # Check parameter count + if [ $# -ne 5 ]; then + echo "Error: add_game_type_via_safe requires exactly 5 parameters" + echo "Usage: add_game_type_via_safe " + echo "Example: add_game_type_via_safe 2 true 600 1800 0x..." + return 1 + fi + + local GAME_TYPE=$1 + local IS_PERMISSIONED=$2 + local CLOCK_EXTENSION_VAL=$3 + local MAX_CLOCK_DURATION_VAL=$4 + local ABSOLUTE_PRESTATE_VAL=$5 + + echo "=== Adding Game Type $GAME_TYPE via Safe ===" + echo " Game Type: $GAME_TYPE" + echo " Is Permissioned: $IS_PERMISSIONED" + echo " Clock Extension: $CLOCK_EXTENSION_VAL" + echo " Max Clock Duration: $MAX_CLOCK_DURATION_VAL" + echo "" + + # Get dispute game factory address + DISPUTE_GAME_FACTORY=$(cast call --rpc-url $L1_RPC_URL $SYSTEM_CONFIG_PROXY_ADDRESS 'disputeGameFactory()(address)') + + echo "Debug Info:" + echo " State JSON: $STATE_JSON_PATH" + echo " Dispute Game Factory: $DISPUTE_GAME_FACTORY" + echo " System Config: $SYSTEM_CONFIG_PROXY_ADDRESS" + echo " Proxy Admin: $PROXY_ADMIN" + echo " OPCM: $OPCM_IMPL_ADDRESS" + echo " Safe: $SAFE_ADDRESS" + echo " RPC URL: $L1_RPC_URL" + echo " Sender: $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY)" + echo "" + + # Retrieve existing permissioned game implementation for parameters + echo "Retrieving permissioned game parameters..." + PERMISSIONED_GAME=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY 'gameImpls(uint32)(address)' 1) + echo "Permissioned Game Implementation: $PERMISSIONED_GAME" + + if [ "$PERMISSIONED_GAME" == "0x0000000000000000000000000000000000000000" ]; then + echo "Error: No permissioned game found. Cannot retrieve parameters." + exit 1 + fi + + # Retrieve parameters from existing permissioned game + ABSOLUTE_PRESTATE="$ABSOLUTE_PRESTATE_VAL" + MAX_GAME_DEPTH=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME 'maxGameDepth()') + SPLIT_DEPTH=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME 'splitDepth()') + VM=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME 'vm()(address)') + + echo "Retrieved parameters:" + echo " Absolute Prestate: $ABSOLUTE_PRESTATE" + echo " Max Game Depth: $MAX_GAME_DEPTH" + echo " Split Depth: $SPLIT_DEPTH" + echo " Clock Extension: $CLOCK_EXTENSION_VAL" + echo " Max Clock Duration: $MAX_CLOCK_DURATION_VAL" + echo " VM: $VM" + echo "" + + # Set constants + INITIAL_BOND='80000000000000000' # 0.08 ETH in wei + SALT_MIXER='123' # Unique salt for game type + + echo "Creating addGameType calldata..." + + # Build game type parameters array (simplified) + GAME_PARAMS="[(\"$SALT_MIXER\",$SYSTEM_CONFIG_PROXY_ADDRESS,$PROXY_ADMIN,0x0000000000000000000000000000000000000000,$GAME_TYPE,$ABSOLUTE_PRESTATE,$MAX_GAME_DEPTH,$SPLIT_DEPTH,$CLOCK_EXTENSION_VAL,$MAX_CLOCK_DURATION_VAL,$INITIAL_BOND,$VM,$IS_PERMISSIONED)]" + + echo "Parameters prepared for addGameType" + + # Execute the transaction through Safe + echo "Executing transaction via Safe..." + echo "Target: $SAFE_ADDRESS" + echo "From: $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY)" + + # Simplified DELEGATECALL - build calldata first, then call + ADDGAMETYPE_CALLDATA=$(cast calldata 'addGameType((string,address,address,address,uint32,bytes32,uint256,uint256,uint64,uint64,uint256,address,bool)[])' "$GAME_PARAMS") + + + # Execute transaction via Safe's execTransaction with proper signature + echo "Executing transaction via Safe with signature..." + DEPLOYER_ADDRESS=$(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY) + + # Use the calldata we built earlier + echo "Using calldata: $ADDGAMETYPE_CALLDATA" + + # Get Safe nonce + SAFE_NONCE=$(cast call --rpc-url $L1_RPC_URL $SAFE_ADDRESS 'nonce()(uint256)') + echo "Safe nonce: $SAFE_NONCE" + + # Build signature exactly like DeployOwnership.s.sol _callViaSafe method + # abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1)) + echo "Building signature like DeployOwnership.s.sol _callViaSafe..." + + # Convert deployer address to uint256(uint160(address)) format + # This is equivalent to: uint256(uint160(msg.sender)) + DEPLOYER_ADDRESS_NO_PREFIX=${DEPLOYER_ADDRESS#0x} + DEPLOYER_ADDRESS_PADDED=$(printf "%064s" $DEPLOYER_ADDRESS_NO_PREFIX) + + # Build signature: uint256(uint160(msg.sender)) + bytes32(0) + uint8(1) + # This is exactly what abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1)) produces + PACKED_SIGNATURE="0x${DEPLOYER_ADDRESS_PADDED}000000000000000000000000000000000000000000000000000000000000000001" + + echo "Deployer address: $DEPLOYER_ADDRESS" + echo "Signature (abi.encodePacked format): $PACKED_SIGNATURE" + echo "Signature length: $((${#PACKED_SIGNATURE} - 2)) hex chars = $(((${#PACKED_SIGNATURE} - 2) / 2)) bytes" + + # Execute transaction via Safe's execTransaction + echo "Executing execTransaction on Safe..." + TX_OUTPUT=$(cast send \ + --json \ + --legacy \ + --rpc-url $L1_RPC_URL \ + --private-key $DEPLOYER_PRIVATE_KEY \ + --from $DEPLOYER_ADDRESS \ + $SAFE_ADDRESS \ + 'execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)' \ + $OPCM_IMPL_ADDRESS \ + 0 \ + $ADDGAMETYPE_CALLDATA \ + 1 \ + 0 \ + 0 \ + 0 \ + 0x0000000000000000000000000000000000000000 \ + 0x0000000000000000000000000000000000000000 \ + $PACKED_SIGNATURE) + + # Extract transaction hash and status + TX_HASH=$(echo "$TX_OUTPUT" | jq -r '.transactionHash // empty') + TX_STATUS=$(echo "$TX_OUTPUT" | jq -r '.status // empty') + + echo "" + echo "Transaction sent, TX_HASH: $TX_HASH" + + # Check if transaction was successful + if [ "$TX_STATUS" = "0x1" ] || [ "$TX_STATUS" = "1" ]; then + echo " โœ… Transaction successful!" + else + echo " โŒ Transaction failed with status: $TX_STATUS" + echo "Full output: $TX_OUTPUT" + exit 1 + fi + echo "" + + # Verify the new game type was added + echo "Verifying new game type was added..." + NEW_GAME_IMPL=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY 'gameImpls(uint32)(address)' $GAME_TYPE) + + if [ "$NEW_GAME_IMPL" != "0x0000000000000000000000000000000000000000" ] && [ "$NEW_GAME_IMPL" != "$PERMISSIONED_GAME" ]; then + echo " โœ… Success! New game type $GAME_TYPE added." + echo "Game Type $GAME_TYPE Implementation: $NEW_GAME_IMPL" + else + echo " โŒ Warning: Could not verify game type was added. Check transaction status." + fi + + echo " โœ… AddGameType operations completed successfully" + + # Set the newly added game type as respected + echo "" + set_respected_game_type "$GAME_TYPE" +} + +# Function to add game type via Transactor +add_game_type_via_transactor() { + local GAME_TYPE=$1 + local IS_PERMISSIONED=$2 + local CLOCK_EXTENSION_VAL=$3 + local MAX_CLOCK_DURATION_VAL=$4 + local ABSOLUTE_PRESTATE_VAL=$5 + + echo "=== Adding Game Type $GAME_TYPE via Transactor ===" + echo "Game Type: $GAME_TYPE" + echo "Is Permissioned: $IS_PERMISSIONED" + echo "Clock Extension: $CLOCK_EXTENSION_VAL" + echo "Max Clock Duration: $MAX_CLOCK_DURATION_VAL" + echo "" + + docker run --rm \ + --network "$DOCKER_NETWORK" \ + -v "$(pwd)/$CONFIG_DIR:/deployments" \ + -w /app \ + "${OP_CONTRACTS_IMAGE_TAG}" \ + bash -c " + set -e + + # Get addresses from environment + RPC_URL=$L1_RPC_URL_IN_DOCKER + TRANSACTOR_ADDRESS=$TRANSACTOR + SENDER_ADDRESS=\$(cast wallet address --private-key $ADMIN_OWNER_PRIVATE_KEY) + PRIVATE_KEY=$ADMIN_OWNER_PRIVATE_KEY + + # Get addresses from environment variables + SYSTEM_CONFIG=$SYSTEM_CONFIG_PROXY_ADDRESS + PROXY_ADMIN=$PROXY_ADMIN + OPCM=$OPCM_IMPL_ADDRESS + DISPUTE_GAME_FACTORY=\$(cast call --rpc-url \$RPC_URL \$SYSTEM_CONFIG 'disputeGameFactory()(address)') + + echo 'State JSON Path: '\$STATE_JSON_PATH + echo 'Dispute Game Factory: '\$DISPUTE_GAME_FACTORY + echo 'System Config: '\$SYSTEM_CONFIG + echo 'Proxy Admin: '\$PROXY_ADMIN + echo 'OPCM: '\$OPCM + echo 'Transactor Address: '\$TRANSACTOR_ADDRESS + echo 'RPC URL: '\$RPC_URL + echo 'Sender Address: '\$SENDER_ADDRESS + echo '' + + # Retrieve existing permissioned game implementation for parameters + echo 'Retrieving permissioned game parameters...' + PERMISSIONED_GAME=\$(cast call --rpc-url \$RPC_URL \$DISPUTE_GAME_FACTORY 'gameImpls(uint32)(address)' 1) + echo 'Permissioned Game Implementation: '\$PERMISSIONED_GAME + + if [ \"\$PERMISSIONED_GAME\" == \"0x0000000000000000000000000000000000000000\" ]; then + echo 'Error: No permissioned game found. Cannot retrieve parameters.' + exit 1 + fi + + # Retrieve parameters from existing permissioned game + ABSOLUTE_PRESTATE='$ABSOLUTE_PRESTATE_VAL' + MAX_GAME_DEPTH=\$(cast call --rpc-url \$RPC_URL \$PERMISSIONED_GAME 'maxGameDepth()') + SPLIT_DEPTH=\$(cast call --rpc-url \$RPC_URL \$PERMISSIONED_GAME 'splitDepth()') + VM=\$(cast call --rpc-url \$RPC_URL \$PERMISSIONED_GAME 'vm()(address)') + + echo 'Retrieved parameters:' + echo ' Absolute Prestate: '\$ABSOLUTE_PRESTATE + echo ' Max Game Depth: '\$MAX_GAME_DEPTH + echo ' Split Depth: '\$SPLIT_DEPTH + echo ' Clock Extension: '$CLOCK_EXTENSION_VAL' + echo ' Max Clock Duration: '$MAX_CLOCK_DURATION_VAL' + echo ' VM: '\$VM + echo '' + + # Set initial bond + INITIAL_BOND='80000000000000000' # 0.08 ETH in wei + + # Create unique salt mixer + SALT_MIXER='123' + + echo 'Creating addGameType calldata...' + + # Create calldata for addGameType function + ADDGAMETYPE_CALLDATA=\$(cast calldata 'addGameType((string,address,address,address,uint32,bytes32,uint256,uint256,uint64,uint64,uint256,address,bool)[])' \ + \"[(\ + \\\"\$SALT_MIXER\\\",\ + \$SYSTEM_CONFIG,\ + \$PROXY_ADMIN,\ + 0x0000000000000000000000000000000000000000,\ + $GAME_TYPE,\ + \$ABSOLUTE_PRESTATE,\ + \$MAX_GAME_DEPTH,\ + \$SPLIT_DEPTH,\ + $CLOCK_EXTENSION_VAL,\ + $MAX_CLOCK_DURATION_VAL,\ + \$INITIAL_BOND,\ + \$VM,\ + $IS_PERMISSIONED\ + )]\") + echo 'AddGameType calldata: '\$ADDGAMETYPE_CALLDATA + echo '' + + # Create calldata for Transactor's DELEGATECALL function + echo 'Creating Transactor DELEGATECALL calldata...' + TRANSACTOR_CALLDATA=\$(cast calldata 'DELEGATECALL(address,bytes)' \$OPCM \$ADDGAMETYPE_CALLDATA) + + echo 'Transactor calldata: '\$TRANSACTOR_CALLDATA + echo '' + + # Execute the transaction through Transactor + echo 'Executing transaction via Transactor...' + echo 'Target: '\$TRANSACTOR_ADDRESS + echo 'RPC_URL: '\$RPC_URL + + cast send \\ + --rpc-url \$RPC_URL \\ + --private-key \$PRIVATE_KEY \\ + --from \$SENDER_ADDRESS \\ + \$TRANSACTOR_ADDRESS \\ + \$TRANSACTOR_CALLDATA + + echo '' + echo 'Transaction sent! Check the transaction hash above for confirmation.' + echo '' + + # Verify the new game type was added + echo 'Verifying new game type was added...' + NEW_GAME_IMPL=\$(cast call --rpc-url \$RPC_URL \$DISPUTE_GAME_FACTORY 'gameImpls(uint32)(address)' $GAME_TYPE) + + if [ \"\$NEW_GAME_IMPL\" != \"0x0000000000000000000000000000000000000000\" ] && [ \"\$NEW_GAME_IMPL\" != \"\$PERMISSIONED_GAME\" ]; then + echo 'โœ… Success! New game type $GAME_TYPE added.' + echo 'Game Type $GAME_TYPE Implementation: '\$NEW_GAME_IMPL + else + echo 'โŒ Warning: Could not verify game type was added. Check transaction status.' + fi + + echo 'โœ… AddGameType operations completed successfully' + " +} + +add_permissioned_game_type() { + echo "Adding game type to DisputeGameFactory via op-deployer..." + + # Retrieve existing values from chain for reference + # Get permissioned game implementation + PERMISSIONED_GAME_RAW=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY_ADDRESS "gameImpls(uint32)" 1) + # Convert 32-byte hex to 20-byte address (last 40 hex chars, with 0x prefix) + PERMISSIONED_GAME="0x${PERMISSIONED_GAME_RAW: -40}" + + MAX_GAME_DEPTH=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "maxGameDepth()") + SPLIT_DEPTH=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "splitDepth()") + VM_RAW=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "vm()") + VM="0x${VM_RAW: -40}" + ANCHOR_STATE_REGISTRY=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "anchorStateRegistry()") + L2_CHAIN_ID=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "l2ChainId()") + + # Call the function to add game type 1 (permissioned) via Transactor + add_game_type_via_transactor 1 true $TEMP_CLOCK_EXTENSION $TEMP_MAX_CLOCK_DURATION $ABSOLUTE_PRESTATE + export GAME_TYPE=1 +} + +wait_op_proposer_create_game() { + + echo "Waiting for op-proposer to create a game..." + ${DOCKER_COMPOSE_CMD} up -d op-proposer + + GAME_CREATED=false + MAX_WAIT_TIME=600 # 10 minutes timeout + WAIT_COUNT=0 + + while [ "$GAME_CREATED" = false ] && [ $WAIT_COUNT -lt $MAX_WAIT_TIME ]; do + # Check if a game was created by op-proposer + GAME_COUNT=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY_ADDRESS "gameCount()(uint256)") + if [ "$GAME_COUNT" -gt 0 ]; then + echo "โœ… Game created! Game count: $GAME_COUNT" + GAME_CREATED=true + else + echo "โณ Waiting for game creation... ($WAIT_COUNT/$MAX_WAIT_TIME seconds)" + sleep 1 + WAIT_COUNT=$((WAIT_COUNT + 1)) + fi + done + + if [ "$GAME_CREATED" = false ]; then + echo "โŒ Timeout waiting for game creation" + exit 1 + fi + + echo "๐Ÿ›‘ Stopping op-proposer..." + ${DOCKER_COMPOSE_CMD} stop op-proposer + +} + +fetch_and_set_latest_game_address() { + echo "get game address" +# echo "๐Ÿ”ง Executing dispute resolution sequence using op-challenger..." + GAME_COUNT=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY_ADDRESS "gameCount()(uint256)") + # Get the latest game address + LATEST_GAME_INDEX=$((GAME_COUNT - 1)) + GAME_INFO=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY_ADDRESS "gameAtIndex(uint256)(uint256,uint256,address)" $LATEST_GAME_INDEX) + # Extract the third value (address) from the returned tuple - address is the last 40 hex chars + GAME_ADDRESS="0x${GAME_INFO: -40}" + echo "Latest game address: $GAME_ADDRESS" +} + +resolve_claim() { + # Execute the dispute resolution sequence using op-challenger commands + echo "1. Resolving claim (0,0) using op-challenger..." + docker run --rm \ + --network "$DOCKER_NETWORK" \ + -v "$(pwd)/data/cannon-data:/data" \ + -v "$(pwd)/config-op/rollup.json:/rollup.json" \ + -v "$(pwd)/config-op/genesis.json:/l2-genesis.json" \ + "${OP_STACK_IMAGE_TAG}" \ + /app/op-challenger/bin/op-challenger resolve-claim \ + --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} \ + --private-key=${OP_CHALLENGER_PRIVATE_KEY} \ + --game-address=$GAME_ADDRESS \ + --claim=0 +} + +resolve_game() { + echo "2. Resolving game using op-challenger..." + docker run --rm \ + --network "$DOCKER_NETWORK" \ + -v "$(pwd)/data/cannon-data:/data" \ + -v "$(pwd)/config-op/rollup.json:/rollup.json" \ + -v "$(pwd)/config-op/genesis.json:/l2-genesis.json" \ + "${OP_STACK_IMAGE_TAG}" \ + /app/op-challenger/bin/op-challenger resolve \ + --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} \ + --private-key=${OP_CHALLENGER_PRIVATE_KEY} \ + --game-address=$GAME_ADDRESS +} + +claim_credit() { + echo "3. Claiming credit for proposer using cast command..." + docker run --rm \ + --network "$DOCKER_NETWORK" \ + "${OP_STACK_IMAGE_TAG}" \ + cast send \ + --rpc-url ${L1_RPC_URL_IN_DOCKER} \ + --private-key ${OP_CHALLENGER_PRIVATE_KEY} \ + $GAME_ADDRESS \ + "claimCredit(address)" \ + $PROPOSER_ADDRESS + echo "โœ… Dispute resolution sequence completed using op-challenger commands!" +} + +set_game_type_permissionless() { + # Retrieve existing values from chain for reference + # Get permissioned game implementation + PERMISSIONED_GAME_RAW=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY_ADDRESS "gameImpls(uint32)" 1) + # Convert 32-byte hex to 20-byte address (last 40 hex chars, with 0x prefix) + PERMISSIONED_GAME="0x${PERMISSIONED_GAME_RAW: -40}" + # + ABSOLUTE_PRESTATE=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "absolutePrestate()") + ANCHOR_STATE_REGISTRY=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "anchorStateRegistry()") + + # Call the function to add game type 0 (permissionless) via Transactor or Safe + # Script is being executed directly - choose function based on OWNER_TYPE + if [ "$OWNER_TYPE" = "safe" ]; then + add_game_type_via_safe 0 false $CLOCK_EXTENSION $MAX_CLOCK_DURATION $ABSOLUTE_PRESTATE + elif [ "$OWNER_TYPE" = "transactor" ]; then + add_game_type_via_transactor 0 false $CLOCK_EXTENSION $MAX_CLOCK_DURATION $ABSOLUTE_PRESTATE + else + echo "Error: Invalid OWNER_TYPE '$OWNER_TYPE'" + exit 1 + fi + + docker run --rm \ + --network "$DOCKER_NETWORK" \ + -v "$(pwd)/$CONFIG_DIR:/deployments" \ + -w /app \ + "${OP_CONTRACTS_IMAGE_TAG}" \ + bash -c " + set -e + + echo '๐Ÿ“‹ Gathering contract addresses and generating calldata...' + DISPUTE_GAME_FACTORY_ADDR=\$(cast call --rpc-url $L1_RPC_URL_IN_DOCKER $SYSTEM_CONFIG_PROXY_ADDRESS 'disputeGameFactory()(address)') + OPTIMISM_PORTAL_ADDR=\$(cast call --rpc-url $L1_RPC_URL_IN_DOCKER $SYSTEM_CONFIG_PROXY_ADDRESS 'optimismPortal()(address)') + echo 'disputeGameFactory: '\$DISPUTE_GAME_FACTORY_ADDR + echo 'optimismPortal: '\$OPTIMISM_PORTAL_ADDR + + # Get anchorStateRegistry address with proper return type specification + ANCHOR_STATE_REGISTRY_ADDR=\$(cast call --rpc-url $L1_RPC_URL_IN_DOCKER \$OPTIMISM_PORTAL_ADDR 'anchorStateRegistry()(address)') + echo 'anchorStateRegistry: '\$ANCHOR_STATE_REGISTRY_ADDR + + GAME_ADDR=\$(cast call --rpc-url $L1_RPC_URL_IN_DOCKER \$DISPUTE_GAME_FACTORY_ADDR 'gameImpls(uint32)(address)' 0) + echo 'gameImpls(0): '\$GAME_ADDR + + cast send \$ANCHOR_STATE_REGISTRY_ADDR 'setRespectedGameType(uint32)' 0 --rpc-url $L1_RPC_URL_IN_DOCKER --private-key $ADMIN_OWNER_PRIVATE_KEY + + echo 'โœ… setRespectedGameType completed successfully' + " + + export GAME_TYPE=0 +} + +add_permissioned_game_type +wait_op_proposer_create_game +# +#echo "โฐ Sleeping for ($TEMP_MAX_CLOCK_DURATION seconds)..." +#sleep $TEMP_MAX_CLOCK_DURATION +# +#fetch_and_set_latest_game_address +#resolve_claim +#resolve_game +# +#sleep $DISPUTE_GAME_FINALITY_DELAY_SECONDS +#claim_credit +# +#set_game_type_permissionless +# +sleep $TEMP_GAME_WINDOW +${DOCKER_COMPOSE_CMD} up -d op-proposer op-challenger op-dispute-mon diff --git a/test-pp-op/8-prepare-tests.sh b/test-pp-op/8-prepare-tests.sh new file mode 100755 index 0000000000000..8f3dd154bc382 --- /dev/null +++ b/test-pp-op/8-prepare-tests.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +set -e + +source .env + + +echo "=== Preparing test; Funding L1 Admin Address===" +L1_ADMIN_ADDRESS="0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534" +L1_ADMIN_PRIVATE_KEY="0x815405dddb0e2a99b12af775fd2929e526704e1d1aea6a0b4e74dc33e2f7fcd2" +cast send --rpc-url $L1_RPC_URL $L1_ADMIN_ADDRESS --private-key $RICH_L1_PRIVATE_KEY --value 1000ether + +echo "=== Bridging ETH from L1 to L2 ===" + +# Bridge contract addresses +OPTIMISM_PORTAL=$(cast call --rpc-url $L1_RPC_URL $SYSTEM_CONFIG_PROXY_ADDRESS 'optimismPortal()(address)') +RECIPIENT="0x14dC79964da2C08b23698B3D3cc7Ca32193d9955" # Default Rich Address +PRIVATE_KEY="0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356" # Default Rich Private Key + +echo "OPTIMISM PORTAL Address: $OPTIMISM_PORTAL" +echo "Recipient: $RECIPIENT" +cast balance $RECIPIENT --rpc-url $L2_RPC_URL +echo "Bridging 1 ETH from L1 to L2..." + +# Bridge 1 ETH to L2 +cast send $OPTIMISM_PORTAL \ + --rpc-url $L1_RPC_URL \ + --private-key $PRIVATE_KEY \ + --value 100ether + +cast send $OPTIMISM_PORTAL \ + --rpc-url $L1_RPC_URL \ + --private-key $L1_ADMIN_PRIVATE_KEY \ + --value 100ether + + + +echo -e "\nWaiting for bridging to complete..." + +echo "Checking L2 balance for $RECIPIENT:" +BALANCE=$(cast balance $RECIPIENT --rpc-url $L2_RPC_URL) +ADMIN_BALANCE=$(cast balance $L1_ADMIN_ADDRESS --rpc-url $L2_RPC_URL) + +WAIT_COUNT=0 +while [ $BALANCE == 0 ] || [ $ADMIN_BALANCE == 0 ]; do + WAIT_COUNT=$((WAIT_COUNT + 1)) + echo " โณ Waiting for bridge transactions to finalize... (${WAIT_COUNT})" + echo " Current L2 balance: $(cast --to-unit $BALANCE ether) ETH" + echo " Current Admin balance: $(cast --to-unit $ADMIN_BALANCE ether) ETH" + sleep 5 + BALANCE=$(cast balance $RECIPIENT --rpc-url $L2_RPC_URL) + ADMIN_BALANCE=$(cast balance $L1_ADMIN_ADDRESS --rpc-url $L2_RPC_URL) +done + +echo " โœ… Bridging complete!" +echo " Final L2 balance: $(cast --to-unit $BALANCE ether) ETH" +echo " Final Admin balance: $(cast --to-unit $ADMIN_BALANCE ether) ETH" diff --git a/test-pp-op/Makefile b/test-pp-op/Makefile new file mode 100644 index 0000000000000..e3bcf091c2529 --- /dev/null +++ b/test-pp-op/Makefile @@ -0,0 +1,204 @@ +-include .env +export + +ifeq ($(ENV),local) + COMPOSE_FILE := docker-compose-local.yml + include local.env +else + COMPOSE_FILE := docker-compose.yml + include testnet.env +endif + +DOCKER_COMPOSE := $(shell docker compose version >/dev/null 2>&1 && echo "docker compose" || echo "docker-compose") -f ${COMPOSE_FILE} + +RUN_DOCKER_MOCK_L1_NETWORK := $(DOCKER_COMPOSE) up -d xlayer-mock-l1-network + +PAUSE := $(DOCKER_COMPOSE) down --remove-orphans; \ + sleep 3; \ + rm -Rf ./l1-geth/consensus/beacondata; \ + rm -Rf ./l1-geth/consensus/validatordata; \ + rm -Rf ./l1-geth/consensus/genesis.ssz; \ + rm -Rf ./l1-geth/execution/geth; \ + rm -Rf ./config-op/artifact.json; \ + rm -Rf ./config-op/31337-deploy.json; \ + rm -Rf ./config-op/genesis.json; \ + rm -Rf ./config-op/rollup.json; \ + rm -Rf ./config-op/state_dump.json; \ + rm -Rf ./l1-geth/execution/genesis.json; \ + rm -Rf ./config-op/genesis-op-raw.json; \ + rm -Rf ./config-op/superchain.json; \ + rm -Rf ./config-op/implementations.json; \ + + +DEPLOY_ERC20_L1 := cd contracts && forge create OKBToken.sol:StandardERC20 --private-key $(SEQUENCER_PRIVATE_KEY) --rpc-url $(L1_RPC_URL) --legacy --broadcast --constructor-args "OKBToken" "OKB" 1000000000 +INIT_ACCOUNT_1 := cast send -f $(SEQUENCER_ADDRESS) --private-key $(SEQUENCER_PRIVATE_KEY) --value 1000ether $(DEPLOYER_ADDRESS) --legacy --rpc-url $(L1_RPC_URL) +INIT_ACCOUNT_2 := cast send -f $(SEQUENCER_ADDRESS) --private-key $(SEQUENCER_PRIVATE_KEY) --value 1000ether $(AGGREGATOR_ADDRESS) --legacy --rpc-url $(L1_RPC_URL) +INIT_ACCOUNT_3 := cast send -f $(SEQUENCER_ADDRESS) --private-key $(SEQUENCER_PRIVATE_KEY) --value 1000ether $(RICH_ADDRESS) --legacy --rpc-url $(L1_RPC_URL) +INIT_ACCOUNT_4 := cast send -f $(SEQUENCER_ADDRESS) --private-key $(SEQUENCER_PRIVATE_KEY) --value 1000ether $(CHALLENGER_ADDRESS) --legacy --rpc-url $(L1_RPC_URL) + +INIT_BRIDGE_ACCOUNT := cast send -f $(DEPLOYER_ADDRESS) --private-key $(DEPLOYER_PRIVATE_KEY) --value 0.01ether $(SEQUENCER_ADDRESS) --legacy --rpc-url $(L2_ERIGON_RPC_URL) + +.PHONY: set-env +set-env: + @if [ "$(ENV)" = "local" ]; then \ + if [ -f local.env ]; then \ + cp local.env .env; \ + echo "Using local.env -> .env"; \ + else \ + echo "local.env not found"; \ + exit 1; \ + fi; \ + fi + +.PHONY: show-env +show-env: + @echo "Current ENV: $(ENV)" + @echo "Using compose file: $(COMPOSE_FILE)" + +.PHONY: run_erigon +run_erigon: set-env show-env + @echo "๐Ÿš€ Starting L1 PoS environment automatic dependency management..." + $(DOCKER_COMPOSE) up -d l1-validator + @echo "๐ŸŽ‰ L1 PoS environment started!" + sleep 30 + $(DEPLOY_ERC20_L1) + $(INIT_ACCOUNT_1) + $(INIT_ACCOUNT_2) + $(INIT_ACCOUNT_3) + $(INIT_ACCOUNT_4) + sleep 5 + ./init-erigon.sh + sleep 5 + $(DOCKER_COMPOSE) up -d xlayer-bridge-db + $(DOCKER_COMPOSE) up -d xlayer-pool-db + sleep 5 + $(DOCKER_COMPOSE) up -d xlayer-agglayer-prover + $(DOCKER_COMPOSE) up -d xlayer-agglayer + sleep 5 + + sleep 3 + $(DOCKER_COMPOSE) up -d xlayer-approve + $(DOCKER_COMPOSE) up -d xlayer-seq + $(DOCKER_COMPOSE) up -d xlayer-pool-manager + + sleep 5 + $(DOCKER_COMPOSE) up -d xlayer-rpc + + sleep 10 + $(DOCKER_COMPOSE) up -d xlayer-bridge-service + $(DOCKER_COMPOSE) up -d xlayer-bridge-ui + $(INIT_BRIDGE_ACCOUNT) + + $(DOCKER_COMPOSE) up -d xlayer-agg-sender + +.PHONY: mainnet +mainnet: + @echo "๐Ÿš€ Starting XLayer Fake Mainnet ..." + $(DOCKER_COMPOSE) up -d l1-validator + sleep 20 + $(INIT_ACCOUNT_1) + $(INIT_ACCOUNT_2) + $(INIT_ACCOUNT_3) + $(INIT_ACCOUNT_4) + $(DOCKER_COMPOSE) up -d xlayer-mainnet-seq + sleep 5 + $(DOCKER_COMPOSE) up -d xlayer-rpc + +.PHONY: build-docker +build-docker: ## build images for all + ./build_images.sh --all + +.PHONY: build-force +build-force: ## Force rebuild all images + ./build_images.sh --all --force + +.PHONY: build-op-geth +build-op-geth: ## Build op-geth image only + ./build_images.sh --op-geth + +.PHONY: build-op-stack +build-op-stack: ## Build op-stack images only + ./build_images.sh --op-stack + +.PHONY: build-cdk-erigon +build-cdk-erigon: + ./build_images.sh --cdk-erigon + +.PHONY: pause +pause: ## Stops all services + $(PAUSE) + +.PHONY: stop +stop: pause + rm -rf data + +.PHONY: clean +clean: stop + rm -rf data + rm -rf config-op/genesis.json + rm -rf config-op/genesis.json.gz + rm -rf config-op/implementations.json + rm -rf config-op/intent.toml + rm -rf config-op/rollup.json + rm -rf config-op/state.json + rm -rf config-op/superchain.json + rm -rf config-op/genesis-op-before-number.json + rm -rf config-op/genesis-op-after-number.json + rm -rf config-op/merged.genesis.gz.json + rm -rf config-op/196-* + rm -rf config-op/195-* + rm -rf config-op/1952-* + rm -rf l1-geth/consensus/beacondata/ + rm -rf l1-geth/consensus/genesis.ssz + rm -rf l1-geth/consensus/validatordata/ + rm -rf l1-geth/execution/genesis.json + rm -rf l1-geth/execution/geth/ + rm -rf merged.genesis.json + rm -rf migrate.log + rm -rf .env + +.PHONY: run +run: stop + @mkdir -p tmp + @echo "OP_GETH_BRANCH: $(OP_GETH_BRANCH)" + @if [ -n "$(OP_GETH_BRANCH)" ]; then \ + echo "Initializing with branch: $(OP_GETH_BRANCH)"; \ + ./init.sh $(OP_GETH_BRANCH); \ + else \ + echo "Initializing with default branch"; \ + ./init.sh; \ + fi + ./0-all.sh + +.PHONY: run-test +run-test: + @echo "OP_GETH_LOCAL_DIRECTORY: $$OP_GETH_LOCAL_DIRECTORY" + @echo "OP_GETH_BRANCH: $(OP_GETH_BRANCH)" + @if [ -n "$$OP_GETH_LOCAL_DIRECTORY" ]; then \ + echo "Using custom local directory: $$OP_GETH_LOCAL_DIRECTORY"; \ + cd "$$OP_GETH_LOCAL_DIRECTORY"; \ + else \ + echo "Using default submodule: ../op-geth"; \ + cd ../op-geth; \ + fi && \ + if [ -n "$(OP_GETH_BRANCH)" ]; then \ + echo "Switching to branch: $(OP_GETH_BRANCH)"; \ + git fetch origin && git checkout "$(OP_GETH_BRANCH)" && git pull origin "$(OP_GETH_BRANCH)"; \ + else \ + echo "Using current branch"; \ + fi && \ + echo "Running E2E tests..."; \ + MallocNanoZone=0 go test -count=1 -failfast -race -v -p 1 -timeout 600s ./test/e2e/... + +.PHONY: test-e2e +test-e2e: stop + @trap 'make stop' EXIT ERR INT TERM; + @echo "OP_GETH_BRANCH: $(OP_GETH_BRANCH)" + if [ -n "$(OP_GETH_BRANCH)" ]; then \ + echo "Running E2E tests with branch: $(OP_GETH_BRANCH)"; \ + make run && sleep 3 && make run-test; \ + else \ + echo "Running E2E tests with default branch"; \ + make run && sleep 3 && make run-test; \ + fi && echo "โœ… E2E tests passed โœ…" + diff --git a/test-pp-op/README.md b/test-pp-op/README.md new file mode 100644 index 0000000000000..b9c9ef6630041 --- /dev/null +++ b/test-pp-op/README.md @@ -0,0 +1,439 @@ +# Optimism Test Environment Setup Guide + +## run on local +```bash +# git submodule update --recursive --force +make clean +cp local.env .env +# ./build_images.sh --all # build all images. add --force if want to force rebuild +./1-start-erigon.sh +./2-deploy-op-contracts.sh +./3-stop-erigon.sh +./4-migrate-op.sh +./5-start-op.sh +./6-build-op-program.sh +./7-setup-fraud-proof.sh +``` + +## run on testnet +```bash +make clean +cp testnet.env .env +./2-deploy-op-contracts.sh +# AFTER DEPLOYING OP CONTRACTS, CHECK TRANSACTOR ADDRESS ON SEPOLIA. +# NOTE: l1ProxyAdminOwner + opcm + transactor addr checking (check intent.toml) + +# Update .env () +# pause erigon, update .env fork_num. +Update FORK_BLOCK+1 +# Overwrite .env to replace with inner node sepolia/beacon node +# Do this before you build op-migrate image. +https://fullnode-inner.okg.com/sepolia/fork/okbc/rpc +https://fullnode-inner.okg.com/ethsepoliabeacon/native/layer1/rpc + +# LOCAL ENVIRONMENT +# ---------------------------------------------------------------------------- +# Build the image locally after deploying contracts (rollup.json and genesis.json). +./build_images.sh --op-geth-migrate --force + +docker save op-migrate:amd64 | gzip > op-migrate-amd64.tar.gz + +# INSIDE DACs TERMINAL +# ---------------------------------------------------------------------------- +# Calculate md5 hash to create OSS ticket. +md5sum op-geth-migrate.tar.gz +# Use osstool to upload images to ECS. +./osstool -f op-geth-migrate.tar.gz -a upload -ticket ${ticket-id} + +# INSIDE ECS MACHINE +# ---------------------------------------------------------------------------- +# If not mounted memory, do this ONCE. +mkdir -p /mnt/ramdisk_op +mount -t tmpfs -o size=128g tmpfs /mnt/ramdisk_op +df -hT /mnt/ramdisk_op + +# In disk +cd /data +# download from OSS +osstool download -ticket ${ticket-id} +# untar the uploaded file +tar -xzvf op-geth-migrate.tar.gz +# load the docker image into local registry +docker load < op-geth-migrate.tar.gz + +# START REGENESIS (ECS host machine) +# ---------------------------------------------------------------------------- +docker run \ + --name $CONTAINER_NAME \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /data/erigon-data:/data/erigon-data \ + -v /mnt/ramdisk_op:/mnt/ramdisk_op \ + -v /mnt/ramdisk_op/test-pp-op/data/op-geth-seq:/app/op-geth/test-pp-op/data/op-geth-seq \ + -e DOCKER_HOST=unix:///var/run/docker.sock \ + -d op-geth-migrate:latest sleep infinity + +cd test-pp-op +# Execute regenesis only. +./4-migrate-op.sh + +# Leave container +exit + +# Inside ECS host, save everything needed (to start new sequencer and build OP program) to disk. +cp /mnt/ramdisk_op/test-pp-op/{.env,config-op/rollup.json,merged.genesis.json,data/op-geth-seq} /data +``` + +## Prerequisites + +### System Requirements +- Docker 20.10.0 or higher +- Docker Compose +- At least 32GB RAM +- At least 32GB available disk space + +> **Important**: If you encounter performance issues, increase Docker engine memory limit to over 32GB +> ![issue](./images/stuck.png) +> ![solution](./images/docker.png) + +### Initial Setup (First Time Only) +1. Run `./init.sh` to initialize the environment (only needed once): + - Install all git submodules + - Build required Docker images + - Prepare base environment + +> Important: `init.sh` should only be run once during initial setup. Re-run only if you need to rebuild Docker images after code changes. + +### Code Updates and Image Rebuilding (Optional) +If you've updated the Optimism codebase and need to rebuild Docker images: + +1. **Update image tags** in `example.env`: + ```bash + # Example: increment version numbers + OP_GETH_IMAGE_TAG=op-geth:v1.101512.0-patch + OP_STACK_IMAGE_TAG=op-stack:v1.13.5 + OP_CONTRACTS_IMAGE_TAG=op-contracts:v1.13.5 + ``` + +2. **Apply changes**: + ```bash + ./clean.sh # This will update .env from example.env + ``` + +3. **Rebuild images**: + ```bash + ./init.sh # Rebuilds all Docker images + + # Or rebuild specific images only (optional) + source .env && cd .. && docker build -t ${OP_STACK_IMAGE_TAG} -f Dockerfile-opstack . && cd - + ``` + +### Directory Structure +``` +test/ +โ”œโ”€โ”€ 0-all.sh # One-click deployment script +โ”œโ”€โ”€ init.sh # Initialization script +โ”œโ”€โ”€ clean.sh # Environment cleanup script +โ”œโ”€โ”€ 1-start-l1.sh # L1 chain startup script +โ”œโ”€โ”€ 2-deploy-op-contracts.sh # Contract deployment script +โ”œโ”€โ”€ 3-op-init.sh # Environment initialization script +โ”œโ”€โ”€ 4-op-start-service.sh # Service startup script +โ”œโ”€โ”€ scripts/ # Utility scripts +โ”‚ โ”œโ”€โ”€ transfer_leader.sh # Leader transfer script +โ”‚ โ”œโ”€โ”€ stop_leader_sequencer.sh # Sequencer stop script +โ”‚ โ”œโ”€โ”€ active_sequencer.sh # Check active sequencer +โ”‚ โ”œโ”€โ”€ add_game_type.sh # Add dispute game type +โ”‚ โ”œโ”€โ”€ deposit-from-l1.sh # L1 to L2 deposit script +โ”‚ โ”œโ”€โ”€ deposit-from-banker.sh # transfer ETH from banker script +โ”‚ โ””โ”€โ”€ show-dev-accounts.sh # Display dev accounts info +โ”œโ”€โ”€ config-op/ # Configuration directory +โ”œโ”€โ”€ data/ # Data storage directory +โ”œโ”€โ”€ contracts/ # Smart contracts +โ”œโ”€โ”€ images/ # Documentation images +โ”œโ”€โ”€ example.env # Environment template +``` + +## Quick Start + +### One-Click Deployment +Run `./0-all.sh` to automatically: +- Initialize the environment +- Start all required components +- Complete all configurations and deployments + +โš ๏ธ **Important Notes**: + +1. Configuration Management: + - Always make configuration changes in `example.env` + - Never modify `.env` directly as it will be reset by `clean.sh` + - Run `clean.sh` to apply changes from `example.env` + +2. Environment Reset: + - `clean.sh` will stop all containers + - Clean all data directories + - Reset `.env` to values from `example.env` + +> Note: For first-time setup, we recommend following the step-by-step deployment process to better understand each component and troubleshoot any potential issues. + +### Step-by-Step Deployment +For more granular control or troubleshooting, follow the steps below. + +## Deployment Process + +### 1. L1 Environment Setup +Run `./1-start-l1.sh`: +- Starts a complete PoS L1 test chain (EL + CL) +- CL node handles blob data storage +- Automatically funds test accounts: + - Batcher + - Proposer + - Challenger + +### 2. Smart Contract Deployment +Run `./2-deploy-op-contracts.sh`: +- Deploys Transactor contract +- Deploys and initializes all Optimism L1 contracts +- Generates configuration files: + - `rollup.json`: op-node configuration + - `genesis.json`: L2 initial state + +### 3. Environment Initialization +Run `./3-op-init.sh`: +- Initializes op-geth database + - Sequencer node + - RPC node +- Generates dispute game components: + - Compiles op-program + - Generates prestate files + - Creates state proofs + +### 4. Service Startup +Run `./4-op-start-service.sh`: +- Launches core services: + - op-batcher: L2 transaction batch processing + - op-proposer: L2 state submission + - op-node: State sync and validation + - op-geth: L2 execution engine + - op-challenger: State validation + - op-dispute-mon: Dispute monitoring + - op-conductor: Sequencer HA management + +### 5. Conductor Management +The test environment includes a 3-node conductor cluster for sequencer high availability (HA). + +#### Architecture +- **Cluster Type**: 3-node Raft consensus cluster +- **Active Sequencer**: Only runs on leader node +- **Failover**: Automatic when leader becomes unhealthy +- **High Availability**: Ensures continuous L2 block production + +#### Configuration +Enable or disable conductor cluster in `example.env`: +```bash +# Enable HA mode with conductor cluster +CONDUCTOR_ENABLED=true + +# Disable HA, run single sequencer +CONDUCTOR_ENABLED=false +``` + +#### Network Ports +Each conductor node uses three ports: +- **RPC Port**: Management API + - Node 1: 8547 + - Node 2: 8548 + - Node 3: 8549 + +- **Consensus Port**: Raft protocol + - Node 1: 50050 + - Node 2: 50051 + - Node 3: 50052 + +- **Sequencer Port**: L2 execution + - Node 1: 9545 + - Node 2: 9546 + - Node 3: 9547 + +#### Health Monitoring +The conductor cluster monitors each node's: +- Sync status with L1 +- P2P network connectivity +- Block production rate + +When leader becomes unhealthy: +- Automatically transfers leadership +- Deactivates unhealthy sequencer +- Activates sequencer on new leader + +#### Leadership Management +There are two ways to trigger leader transfer: + +1. Using `transfer-leader.sh`: +```bash +# Auto transfer to any healthy node +./scripts/transfer-leader.sh + +# Transfer to specific node (1 or 2 or 3) +./scripts/transfer-leader.sh 2 +``` + +2. Force transfer by stopping leader's sequencer: +```bash +# Stops block production while keeping the container running +# Automatically triggers leader transfer after health check timeout +# Can be run multiple times to test different leadership scenarios +./scripts/stop-leader-sequencer.sh +``` + +This method simulates a sequencer failure scenario, enabling comprehensive testing of automatic failover mechanisms. Each execution stops the current leader's sequencer and triggers a transfer to another node, allowing you to test different leadership scenarios by running the script multiple times. The cluster maintains high availability through dynamic role switching - when a sequencer stops producing blocks, it transitions to follower status while another node assumes leadership. The system remains resilient as any follower can automatically promote to leader if the current leader encounters issues. + +3. Gray upgrade using op-conductor: +```bash +# Emulate the whole gray upgrade process to achieve 0 downtime +./scripts/gray-upgrade-simulation.sh +# Meanwhile, open another terminal window to load test +polycli loadtest --rpc-url http://localhost:8124 \ + --private-key "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356" \ + --verbosity 700 --requests 50000 -c 1 --rate-limit -1 +``` + +The `scripts/gray-upgrade-simulation.sh` script simulates a rolling upgrade process for the sequencer cluster managed by op-conductor. It upgrades a follower sequencer while keeping the leader running, then transfers leadership to the upgraded node. This approach ensures service continuity and validates the cluster's resilience during upgrades. + +## Utility Scripts + +### L1 to L2 Deposit Script + +The `scripts/deposit-from-l1.sh` script facilitates testing L1 to L2 cross-chain deposits: + +#### Features +- **Automatic Deposit**: Deposits 3000 ETH from L1 to L2 +- **Balance Monitoring**: Monitors L2 balance changes in real-time +- **Wait Time Tracking**: Measures total deposit confirmation time +- **Status Updates**: Provides clear progress feedback + +#### Usage +```bash +# Run the deposit script +./scripts/deposit-from-l1.sh +``` + +#### What it does +1. **Funds Test Account**: Sends ETH to the test account on L1 +2. **Creates Deposit Transaction**: Calls OptimismPortal.depositTransaction() +3. **Monitors L2 Balance**: Continuously checks L2 balance until change detected +4. **Reports Results**: Shows deposit confirmation time and balance changes + +#### Configuration +The script uses these default parameters: +- **Deposit Amount**: 3000 ETH +- **Gas Limit**: 100,000 +- **Target Address**: Same as sender (self-deposit) +- **L2 RPC**: http://127.0.0.1:8123 + +This script is useful for: +- Testing cross-chain deposit functionality +- Measuring deposit confirmation times +- Verifying L1/L2 synchronization +- Validating OptimismPortal contract integration + +### Banker Account Deposit Script + +The `scripts/deposit-from-banker.sh` script enables large-scale testing using a banker account with massive balance: + +#### Features +- **Large Amount Transfers**: Transfers 1,000,000 ETH (1 million ETH) +- **Banker Account**: Uses a pre-funded account with astronomical balance +- **Simple Transfer**: Direct ETH transfer without cross-chain complexity +- **Legacy Transaction**: Uses legacy transaction format for compatibility + +#### Usage +```bash +# Run the banker deposit script +./scripts/deposit-from-banker.sh +``` + +#### What it does +1. **Uses Banker Account**: Leverages account `0x70997970C51812dc3A010C7d01b50e0d17dc79C8` +2. **Large Transfer**: Sends 1,000,000 ETH to target address +3. **Direct Transfer**: Simple ETH transfer on L2 network +4. **Legacy Format**: Uses legacy transaction format + +### Development Accounts Display Script + +The `scripts/show-dev-accounts.sh` script displays all development accounts with their private keys: + +#### Features +- **Account Listing**: Shows all 30 development accounts (paths 0-29) +- **Private Key Display**: Reveals private keys for testing +- **Address Generation**: Shows corresponding addresses +- **Mnemonic Path**: Displays derivation paths + +#### Usage +```bash +# Display all dev accounts +./scripts/show-dev-accounts.sh +``` + +#### What it does +1. **Generates Accounts**: Creates 30 accounts from standard mnemonic (paths 0-29) +2. **Shows Details**: Displays address, private key, and derivation path +3. **Standard Mnemonic**: Uses "test test test test test test test test test test test junk" +4. **Path Format**: Uses `m/44'/60'/0'/0/{i}` derivation paths + +#### Important Notes +- **Balance Status**: Most dev accounts are pre-funded with 10,000 ETH, but some accounts may have zero initial balance + +## Troubleshooting + +### Common Issues + +#### 1. Service Startup Failures +- **Check Docker logs**: `docker compose logs ` +- **Verify port availability**: Ensure ports 8545, 8546, 4000, 3500 are free +- **Validate environment variables**: Check `.env` file matches `example.env` +- **Memory issues**: Increase Docker memory limit to 32GB+ + +#### 2. Contract Deployment Issues +- **Verify L1 node is running**: Check `docker compose ps` +- **Check account balances**: Ensure test accounts have sufficient ETH +- **Validate gas settings**: Check gas limit and price in deployment logs + +#### 3. Synchronization Issues +- **L2 not syncing**: Check op-geth-seq is running and producing blocks +- **RPC node issues**: Verify op-geth-rpc can connect to op-geth-seq +- **Genesis mismatch**: Ensure rollup.json matches actual L2 genesis + +#### 4. Conductor Cluster Issues +- **Leader election problems**: Check Raft consensus logs +- **Sequencer not switching**: Verify health check configuration +- **P2P connectivity**: Check network configuration and firewall + +## Service Ports Overview + +| Service | Port | Description | +|---------|------|-------------| +| **L1 Services** | | | +| l1-geth | 8545 | L1 Ethereum RPC | +| l1-geth | 8546 | L1 Ethereum WebSocket | +| l1-geth | 8551 | L1 Ethereum Engine API | +| l1-beacon-chain | 4000 | L1 Beacon RPC | +| l1-beacon-chain | 3500 | L1 Beacon HTTP | +| l1-beacon-chain | 18080 | L1 Beacon Metrics | +| **L2 Services** | | | +| op-geth-seq | 8123 | L2 Sequencer RPC | +| op-geth-seq | 7546 | L2 Sequencer WebSocket | +| op-geth-seq | 8552 | L2 Sequencer Engine API | +| op-geth-rpc | 9123 | L2 RPC Node RPC | +| op-seq | 9545 | L2 Node RPC | +| op-seq | 7070 | L2 Node P2P | +| op-seq | 9223 | L2 Node P2P (UDP) | +| op-rpc | 9555 | L2 RPC Node RPC | +| **Conductor Cluster** | | | +| op-conductor | 8547 | Conductor 1 RPC | +| op-conductor | 50050 | Conductor 1 Consensus | +| op-conductor2 | 8548 | Conductor 2 RPC | +| op-conductor2 | 50051 | Conductor 2 Consensus | +| op-conductor3 | 8549 | Conductor 3 RPC | +| op-conductor3 | 50052 | Conductor 3 Consensus | +| **Other Services** | | | +| op-batcher | 8548 | Batcher RPC | +| op-proposer | 8560 | Proposer RPC | diff --git a/test-pp-op/build_images.sh b/test-pp-op/build_images.sh new file mode 100755 index 0000000000000..1f3d78988a83e --- /dev/null +++ b/test-pp-op/build_images.sh @@ -0,0 +1,301 @@ +#!/bin/bash +set -e +set -x + +# ============================================================================= +# Build Images Script +# ============================================================================= +# This script builds Docker images for the OP-Geth project with support for +# selective building and force rebuilds. +# +# USAGE: +# ./build_images.sh [OPTIONS] +# +# OPTIONS: +# --op-geth Build op-geth image only +# --op-stack Build op-stack images only (contracts + opstack) +# --op-contract Build op-contracts images only +# --bridge Build bridge service image only +# --aggkit Build aggkit image only +# --all Build all images (default if no options specified) +# --force Force rebuild even if images exist +# -h, --help Show this help message +# +# EXAMPLES: +# ./build_images.sh # Build all images (default) +# ./build_images.sh --op-geth # Build op-geth only +# ./build_images.sh --op-stack # Build op-stack only +# ./build_images.sh --bridge # Build bridge service only +# ./build_images.sh --aggkit # Build aggkit only +# ./build_images.sh --all --force # Force rebuild all images +# ./build_images.sh --op-geth --force # Force rebuild op-geth only +# ./build_images.sh --help # Show help +# +# IMAGES BUILT: +# - OP-Geth: Ethereum client with OP Stack modifications +# - OP-Stack: Core OP Stack components (contracts + opstack) +# - Bridge Service: Patched zkevm-bridge-service +# - AggKit: OKX aggregation toolkit +# ============================================================================= + +source .env + +# Default values +ARCH=$(docker version --format '{{.Server.Os}}/{{.Server.Arch}}') +BUILD_CDK_ERIGON=false +BUILD_OP_GETH=false +BUILD_OP_GETH_MIGRATE=false +BUILD_OP_STACK=false +BUILD_OP_CONTRACT=false +BUILD_BRIDGE=false +BUILD_AGGKIT=false +BUILD_ALL=false +FORCE=false + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --cdk-erigon) + BUILD_CDK_ERIGON=true + shift + ;; + --op-geth) + BUILD_OP_GETH=true + shift + ;; + --op-geth-migrate) + BUILD_OP_GETH_MIGRATE=true + shift + ;; + --op-stack) + BUILD_OP_STACK=true + shift + ;; + --op-contract) + BUILD_OP_CONTRACT=true + shift + ;; + --bridge) + BUILD_BRIDGE=true + shift + ;; + --aggkit) + BUILD_AGGKIT=true + shift + ;; + --all) + BUILD_ALL=true + shift + ;; + --force) + FORCE=true + shift + ;; + --arch) + echo "ARCH: $2" + ARCH="$2" + shift 2 + ;; + -h|--help) + echo "Usage: $0 [OPTIONS]" + echo "Options:" + echo " --cdk-erigon Build cdk-erigon image only" + echo " --op-geth Build op-geth image only" + echo " --op-geth-migrate Build op-geth-migrate image only" + echo " --op-stack Build op-stack images" + echo " --op-contract Build op contract image" + echo " --bridge Build bridge service image only" + echo " --aggkit Build aggkit image only" + echo " --all Build all images (default if no options specified)" + echo " --force Force rebuild even if images exist" + echo " -h, --help Show this help message" + exit 0 + ;; + *) + echo "Unknown option: $1" + echo "Use --help for usage information" + exit 1 + ;; + esac +done + +# If no specific options provided, build all +if [ "$BUILD_OP_GETH" = false ] && [ "$BUILD_CDK_ERIGON" = false ] && [ "$BUILD_OP_STACK" = false ] && [ "$BUILD_OP_CONTRACT" = false ] && [ "$BUILD_BRIDGE" = false ] && [ "$BUILD_AGGKIT" = false ] && [ "$BUILD_OP_GETH_MIGRATE" = false ] && [ "$BUILD_ALL" = false ]; then + BUILD_ALL=true +fi + +# If --all is specified, set all flags +if [ "$BUILD_ALL" = true ]; then + BUILD_CDK_ERIGON=true + BUILD_OP_GETH=true + BUILD_OP_GETH_MIGRATE=true + BUILD_OP_STACK=true + BUILD_OP_CONTRACT=true + BUILD_BRIDGE=true + BUILD_AGGKIT=true +fi + +build_patched_zkevm_bridge_service_image() { + echo "build patched zkevm bridge service image" + PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + rm -rf $PWD_DIR/tmp/zkevm-bridge-service + mkdir -p $PWD_DIR/tmp + cd $PWD_DIR/tmp/ + git clone -b v0.6.0-RC16 https://github.com/0xPolygon/zkevm-bridge-service.git + # it has docker file + cd zkevm-bridge-service + + # patch zkevm-bridge-service + git apply $PWD_DIR/patch/xlayer-bridge-service-0001-support-sync-L2-block-at-given-number.patch + git apply $PWD_DIR/patch/xlayer-bridge-service-0002-skip-reorg-check-after-regenesis.patch + git apply $PWD_DIR/patch/xlayer-bridge-service-0003-skip-syncing-blocks-before-regenesis.patch + + docker build --platform $ARCH -t $XLAYER_BRIDGE_SERVICE_IMAGE_TAG . + cd $PWD_DIR +} + +build_aggkit_image() { + echo "build aggkit image" + PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + rm -rf $PWD_DIR/tmp/aggkit + mkdir -p $PWD_DIR/tmp + cd $PWD_DIR/tmp/ + + echo "Cloning contract repository..." + git clone -b feature/0.1.0 https://github.com/okx/aggkit.git + cd ./aggkit + echo "Cleaning and resting contract repository..." + git reset --hard; git checkout feature/0.1.0;git pull + make build-docker + cd $PWD_DIR +} + +build_cdk_erigon_image() { + echo "build cdk_erigon image" + PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + rm -rf $PWD_DIR/tmp/xlayer-erigon + mkdir -p $PWD_DIR/tmp + cd $PWD_DIR/tmp/ + + echo "Cloning cdk-erigon repository..." + git clone -b dev https://github.com/okx/xlayer-erigon.git + cd ./xlayer-erigon + git reset --hard; git checkout dev;git pull + docker build --platform $ARCH -t ${CDK_ERIGON_IMAGE_TAG} -f ./Dockerfile.local . + cd $PWD_DIR +} + +build_op_stack_contract() { + echo "build op stack image" + PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + + # cp Transactor.sol to optimism, which is used for addGameType + cp $PWD_DIR/contracts/Transactor.sol ../packages/contracts-bedrock/src/periphery/Transactor.sol + + cd .. + docker build $( [ "$FORCE" = true ] && echo --no-cache ) --platform $ARCH -t $OP_CONTRACTS_IMAGE_TAG -f Dockerfile-contracts . + + cd $PWD_DIR + +} + +build_op_stack_image() { + echo "build op stack image" + # Check if op_contract image exists + if ! image_exists "$OP_CONTRACTS_IMAGE_TAG"; then + echo "Error: OP contracts image ($OP_CONTRACTS_IMAGE_TAG) does not exist." + echo "Please build the contracts image first using --op-contract or --all" + exit 1 + fi + + PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + + cd .. + docker tag "$OP_CONTRACTS_IMAGE_TAG" "op-contracts:latest" + docker build --platform $ARCH -t $OP_STACK_IMAGE_TAG -f Dockerfile-opstack . + docker tag "op-contracts:latest" "$OP_CONTRACTS_IMAGE_TAG" + + cd $PWD_DIR +} + +build_op_geth_migrate_image() { + echo "build op-geth image" + PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + PROJECT_ROOT="$(git rev-parse --show-toplevel)" + + # If tmp/optimism doesn't exist, clone it + if [ ! -d "$PWD_DIR/tmp/op-geth" ]; then + rm -rf $PWD_DIR/tmp/op-geth + mkdir -p $PWD_DIR/tmp + cd $PWD_DIR/tmp/ + echo "Cloning op-geth repository..." + git clone --recurse-submodules -b dev-op https://github.com/okx/op-geth.git + cd $PWD_DIR + fi + + # Must build at test-pp-op to copy config files (eg. .env) over as well. + docker build --platform $ARCH -t $OP_GETH_MIGRATION_IMAGE_TAG --progress=plain --no-cache -f dockerfile/Dockerfile.migrate . + # cd "$PWD_DIR/tmp/op-geth" + # docker build --platform $ARCH -t $OP_GETH_MIGRATION_IMAGE_TAG . + cd $PWD_DIR +} + +build_op_geth_image() { + echo "build op-geth image" + PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + + cd ../op-geth + docker build $( [ "$FORCE" = true ] && echo --no-cache ) --platform $ARCH -t $OP_GETH_IMAGE_TAG . + cd $PWD_DIR +} + +# Helper function to check if image exists +image_exists() { + local image_tag=$1 + docker image inspect "$image_tag" >/dev/null 2>&1 +} + +# Helper function to build if needed +build_if_needed() { + local image_tag=$1 + local build_function=$2 + local description=$3 + + if [ "$FORCE" = true ] || ! image_exists "$image_tag"; then + echo "Building $description..." + $build_function + else + echo "Image $image_tag already exists (use --force to rebuild)" + fi +} + +# Build images based on selected options +if [ "$BUILD_OP_CONTRACT" = true ]; then + build_if_needed "$OP_CONTRACTS_IMAGE_TAG" "build_op_stack_contract" "OP Stack contracts" +fi + +if [ "$BUILD_OP_STACK" = true ]; then + build_if_needed "$OP_STACK_IMAGE_TAG" "build_op_stack_image" "OP Stack image" +fi + +if [ "$BUILD_OP_GETH" = true ]; then + build_if_needed "$OP_GETH_IMAGE_TAG" "build_op_geth_image" "OP-Geth image" +fi + +if [ "$BUILD_OP_GETH_MIGRATE" = true ]; then + build_if_needed "$OP_GETH_MIGRATION_IMAGE_TAG" "build_op_geth_migrate_image" "OP-Geth migrate image" +fi + +if [ "$BUILD_CDK_ERIGON" = true ]; then + build_if_needed "$CDK_ERIGON_IMAGE_TAG" "build_cdk_erigon_image" "cdk-erigon image" +fi + +if [ "$BUILD_BRIDGE" = true ]; then + build_if_needed "$XLAYER_BRIDGE_SERVICE_IMAGE_TAG" "build_patched_zkevm_bridge_service_image" "patched zkevm bridge service" +fi + +if [ "$BUILD_AGGKIT" = true ]; then + build_if_needed "aggkit:local" "build_aggkit_image" "aggkit" +fi + +echo "Build completed!" diff --git a/test-pp-op/cgt-only-contract.sh b/test-pp-op/cgt-only-contract.sh new file mode 100755 index 0000000000000..e322ed1a8e832 --- /dev/null +++ b/test-pp-op/cgt-only-contract.sh @@ -0,0 +1,200 @@ +#!/bin/bash +echo "Custom Gas Token Demo: only modify contract, without modifying sequencer code" +set -e + +ROOT_DIR=$(git rev-parse --show-toplevel) +PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +cd $PWD_DIR + +source .env + +echo "๐Ÿ”ง Setting up Custom Gas Token (CGT) configuration..." +echo "" + +# Run the Foundry script to deploy and configure CGT +echo "๐Ÿ“ Step 1: Running Foundry setup script..." +cd $ROOT_DIR/packages/contracts-bedrock +export SYSTEM_CONFIG_PROXY_ADDRESS=$SYSTEM_CONFIG_PROXY_ADDRESS +export OPTIMISM_PORTAL_PROXY_ADDRESS=$OPTIMISM_PORTAL_PROXY_ADDRESS + +# Capture forge script output +# forge script scripts/SetupCustomGasToken.s.sol:SetupCustomGasToken \ +# --rpc-url "$L1_RPC_URL" \ +# --private-key "$DEPLOYER_PRIVATE_KEY" + +FORGE_OUTPUT=$(forge script scripts/SetupCustomGasToken.s.sol:SetupCustomGasToken \ + --rpc-url "$L1_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast 2>&1) + +echo "$FORGE_OUTPUT" + +# Extract contract addresses from forge output +OKB_TOKEN=$(echo "$FORGE_OUTPUT" | grep "MockOKB deployed at:" | awk '{print $NF}') +ADAPTER_ADDRESS=$(echo "$FORGE_OUTPUT" | grep "DepositedOKBAdapter deployed at:" | awk '{print $NF}') + +# Query initial OKB total supply +INIT_TOTAL_SUPPLY=$(cast call "$OKB_TOKEN" "totalSupply()(uint256)" --rpc-url "$L1_RPC_URL") +echo "" +echo "๐Ÿ“Š Initial OKB Total Supply: $INIT_TOTAL_SUPPLY" + +echo "" +echo "โœ… L1 Custom Gas Token setup complete!" +echo "" +echo "๐Ÿ“‹ Deployed Contract Addresses:" +echo " OKB Token: $OKB_TOKEN" +echo " Adapter: $ADAPTER_ADDRESS" +echo "" + +# Check if L2 is running before verifying L2 configuration +if curl -s -X POST "$L2_RPC_URL" \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ + > /dev/null 2>&1; then + + echo "๐Ÿ“ Step 2: Verifying L2 configuration..." + echo "" + + # Call L1Block predeploy to check configuration + L1_BLOCK_ADDR="0x4200000000000000000000000000000000000015" + + # Check isCustomGasToken + IS_CUSTOM_GAS_TOKEN=$(cast call "$L1_BLOCK_ADDR" \ + "isCustomGasToken()(bool)" \ + --rpc-url "$L2_RPC_URL") + + echo " L1Block.isCustomGasToken(): $IS_CUSTOM_GAS_TOKEN" + + # Check gasPayingTokenName + TOKEN_NAME=$(cast call "$L1_BLOCK_ADDR" \ + "gasPayingTokenName()(string)" \ + --rpc-url "$L2_RPC_URL") + + echo " L1Block.gasPayingTokenName(): $TOKEN_NAME" + + # Check gasPayingTokenSymbol + TOKEN_SYMBOL=$(cast call "$L1_BLOCK_ADDR" \ + "gasPayingTokenSymbol()(string)" \ + --rpc-url "$L2_RPC_URL") + + echo " L1Block.gasPayingTokenSymbol(): $TOKEN_SYMBOL" + + echo "" + if [ "$IS_CUSTOM_GAS_TOKEN" = "true" ]; then + echo "โœ… L2 Custom Gas Token configuration verified!" + else + echo "โš ๏ธ WARNING: L2 custom gas token not yet active" + echo " The L2 chain needs to process the setCustomGasToken transaction" + echo " This will happen automatically when the chain processes L1 data" + fi +else + echo "โš ๏ธ L2 node is not running yet - skipping L2 verification" + echo " Please verify L2 configuration after the L2 node starts" +fi + +echo "" +echo "๐ŸŽ‰ Custom Gas Token setup script completed!" +echo "" + +# Perform test deposit +if [ -n "$OKB_TOKEN" ] && [ -n "$ADAPTER_ADDRESS" ]; then + echo "๐Ÿ“ Step 3: Performing test deposit..." + echo "" + + DEPOSIT_AMOUNT="7999000000000000" + + # L2 recipient address + L2_RECIPIENT=0x70997970C51812dc3A010C7d01b50e0d17dc79C9 + + INIT_BALANCE=$(cast balance $L2_RECIPIENT --rpc-url $L2_RPC_URL) + echo " Deposit Amount: $DEPOSIT_AMOUNT" + echo " L2 Recipient: $L2_RECIPIENT" + echo " Initial Balance: $INIT_BALANCE" + echo "" + + # Check deployer's OKB balance before proceeding + DEPLOYER_ADDRESS=$(cast wallet address --private-key "$DEPLOYER_PRIVATE_KEY") + DEPLOYER_OKB_BALANCE=$(cast call "$OKB_TOKEN" "balanceOf(address)(uint256)" "$DEPLOYER_ADDRESS" --rpc-url "$L1_RPC_URL") + echo " Deployer ($DEPLOYER_ADDRESS) OKB Balance: $DEPLOYER_OKB_BALANCE" + echo "" + + # Step 3a: Approve the adapter to spend OKB + cast send "$OKB_TOKEN" \ + "approve(address,uint256)" \ + "$ADAPTER_ADDRESS" \ + "$DEPOSIT_AMOUNT" \ + --rpc-url "$L1_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" + + # Step 3b: Perform the deposit + cast send "$ADAPTER_ADDRESS" \ + "deposit(address,uint256,uint64,bool,bytes)" \ + "$L2_RECIPIENT" \ + "$DEPOSIT_AMOUNT" \ + "100000" \ + "false" \ + "0x" \ + --rpc-url "$L1_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" + + echo "" + echo "โœ… Test deposit transaction sent!" + echo "" + echo "โณ Waiting for L2 to process the deposit..." + echo " Checking balance every 5 seconds..." + echo "" + + # Expected final balance + EXPECTED_BALANCE=$((INIT_BALANCE + DEPOSIT_AMOUNT)) + + # Timeout after 5 minutes (60 attempts * 5 seconds) + MAX_ATTEMPTS=60 + ATTEMPT=0 + + while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do + CURRENT_BALANCE=$(cast balance $L2_RECIPIENT --rpc-url $L2_RPC_URL) + + echo " [Attempt $((ATTEMPT + 1))/$MAX_ATTEMPTS] Current Balance: $CURRENT_BALANCE (Expected: $EXPECTED_BALANCE)" + + if [ "$CURRENT_BALANCE" = "$EXPECTED_BALANCE" ]; then + echo "" + echo "๐ŸŽ‰ Deposit processed successfully!" + echo "" + + # Query OKB total supply after successful deposit + DEPOSIT_FINAL_TOTAL_SUPPLY=$(cast call "$OKB_TOKEN" "totalSupply()(uint256)" --rpc-url "$L1_RPC_URL") + + echo "๐Ÿ“Š Final Status:" + echo " Initial Balance: $INIT_BALANCE" + echo " Deposit Amount: $DEPOSIT_AMOUNT" + echo " Final Balance: $CURRENT_BALANCE" + echo " L2 Recipient: $L2_RECIPIENT" + echo "" + echo "๐Ÿ”ฅ OKB Token Supply Status:" + echo " Initial Total Supply: $INIT_TOTAL_SUPPLY" + echo " Final Total Supply: $DEPOSIT_FINAL_TOTAL_SUPPLY" + echo "" + break + fi + + ATTEMPT=$((ATTEMPT + 1)) + + if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then + sleep 5 + fi + done + + if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then + echo "" + echo "โš ๏ธ WARNING: Deposit not processed within timeout period (5 minutes)" + echo " Current Balance: $CURRENT_BALANCE" + echo " Expected Balance: $EXPECTED_BALANCE" + echo "" + echo "๐Ÿ“š Troubleshooting:" + echo " 1. Check if L2 node is running and syncing" + echo " 2. Check L1 transaction status" + echo " 3. Monitor TransactionDeposited events on OptimismPortal: $OPTIMISM_PORTAL_PROXY_ADDRESS" + echo " 4. Manually check balance: cast balance $L2_RECIPIENT --rpc-url $L2_RPC_URL" + fi +fi diff --git a/test-pp-op/config-op/intent.local.toml.bak b/test-pp-op/config-op/intent.local.toml.bak new file mode 100644 index 0000000000000..3265223ca8fd1 --- /dev/null +++ b/test-pp-op/config-op/intent.local.toml.bak @@ -0,0 +1,36 @@ +configType = "standard-overrides" +l1ChainID = 1337 +fundDevAccounts = true +opcmAddress = "0x0000000000000000000000000000000000000000" +l1ContractsLocator = "file:///app/packages/contracts-bedrock/forge-artifacts" +l2ContractsLocator = "file:///app/packages/contracts-bedrock/forge-artifacts" + +[[chains]] + id = "0x00000000000000000000000000000000000000000000000000000000000000c3" + baseFeeVaultRecipient = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + l1FeeVaultRecipient = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + sequencerFeeVaultRecipient = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + eip1559DenominatorCanyon = 250 + eip1559Denominator = 50 + eip1559Elasticity = 6 + operatorFeeScalar = 0 + operatorFeeConstant = 0 + gasLimit = 30000000 + minBaseFee = 1000000 + [chains.deployOverrides] + l2GenesisBlockGasLimit = "0xbebc200" + l2GenesisBlockBaseFeePerGas = "0x3B9ACA00" + l2BlockTime = 1 + [chains.customGasToken] + enabled = true + name = "OKB" + symbol = "OKB" + initialLiquidity = "0x0" + [chains.roles] + l1ProxyAdminOwner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + l2ProxyAdminOwner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + systemConfigOwner = "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534" + unsafeBlockSigner = "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" + batcher = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" + proposer = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" + challenger = "0x7d18A1B858253b5588f61fb5739d52e4b84e2cdA" diff --git a/test-pp-op/config-op/intent.testnet.toml.bak b/test-pp-op/config-op/intent.testnet.toml.bak new file mode 100644 index 0000000000000..1aa95c7848d35 --- /dev/null +++ b/test-pp-op/config-op/intent.testnet.toml.bak @@ -0,0 +1,36 @@ +configType = "standard-overrides" +l1ChainID = 11155111 +fundDevAccounts = false +opcmAddress = "0x0000000000000000000000000000000000000000" +l1ContractsLocator = "file:///app/packages/contracts-bedrock/forge-artifacts" +l2ContractsLocator = "file:///app/packages/contracts-bedrock/forge-artifacts" + +[[chains]] + id = "0x00000000000000000000000000000000000000000000000000000000000007A0" + baseFeeVaultRecipient = "0x86Df3Aa8a02b7b67A1b83f1B062F93563F7494d2" + l1FeeVaultRecipient = "0x86Df3Aa8a02b7b67A1b83f1B062F93563F7494d2" + sequencerFeeVaultRecipient = "0x86Df3Aa8a02b7b67A1b83f1B062F93563F7494d2" + eip1559DenominatorCanyon = 100000000 + eip1559Denominator = 100000000 + eip1559Elasticity = 1 + operatorFeeScalar = 0 + operatorFeeConstant = 0 + gasLimit = 30000000 + [chains.deployOverrides] + l2GenesisBlockGasLimit = "0x1C9C380" + l2GenesisBlockBaseFeePerGas = "0x5F5E100" + l2BlockTime = 1 + [chains.customGasToken] + enabled = true + name = "OKB" + symbol = "OKB" + initialLiquidity = "0x0" + [chains.roles] + l1ProxyAdminOwner = "0x86Df3Aa8a02b7b67A1b83f1B062F93563F7494d2" + l2ProxyAdminOwner = "0x86Df3Aa8a02b7b67A1b83f1B062F93563F7494d2" + systemConfigOwner = "0x1183f158515091c94188C13Cd16923cee663d4c4" + unsafeBlockSigner = "0x8A8926FEbCFEdD0B189886858B32ad1e7F4a5b4B" + batcher = "0x8EDf9B54e1c693b7B0caEa85E6a005C35e229124" + proposer = "0x829D57F38D2A94514a3dbA2297fDD1Bc52bB1938" + challenger = "0x7c3787BF0D78a9e2F802916110e4Ddd6E3eD262C" + diff --git a/test-pp-op/config-op/intent.toml.bak b/test-pp-op/config-op/intent.toml.bak new file mode 100644 index 0000000000000..cf04ac0b40e8b --- /dev/null +++ b/test-pp-op/config-op/intent.toml.bak @@ -0,0 +1,35 @@ +configType = "standard-overrides" +l1ChainID = 1337 +fundDevAccounts = true +opcmAddress = "0x0000000000000000000000000000000000000000" +l1ContractsLocator = "file:///app/packages/contracts-bedrock/forge-artifacts" +l2ContractsLocator = "file:///app/packages/contracts-bedrock/forge-artifacts" + +[[chains]] + id = "0x00000000000000000000000000000000000000000000000000000000000000c4" + baseFeeVaultRecipient = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + l1FeeVaultRecipient = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + sequencerFeeVaultRecipient = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + eip1559DenominatorCanyon = 250 + eip1559Denominator = 50 + eip1559Elasticity = 6 + gasLimit = 60000000 + operatorFeeScalar = 0 + operatorFeeConstant = 0 + [chains.deployOverrides] + l2GenesisBlockGasLimit = "0xbebc200" + l2GenesisBlockBaseFeePerGas = "0x3B9ACA00" + l2BlockTime = 1 + [chains.roles] + l1ProxyAdminOwner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + l2ProxyAdminOwner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + systemConfigOwner = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + unsafeBlockSigner = "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" + batcher = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" + proposer = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" + challenger = "0x7d18A1B858253b5588f61fb5739d52e4b84e2cdA" + [chains.customGasToken] + enabled = true + name = "OKB" + symbol = "OKB" + InitialLiquidity = "0x0" # 0 OKB, no premint diff --git a/test-pp-op/config-op/jwt.txt b/test-pp-op/config-op/jwt.txt new file mode 100644 index 0000000000000..f9be65a53906f --- /dev/null +++ b/test-pp-op/config-op/jwt.txt @@ -0,0 +1 @@ +0c00f14247582fcd3c837311148cda1f56e7c2caa42fb1ba8a3cc7843603846e diff --git a/test-pp-op/config-op/state.json.bak b/test-pp-op/config-op/state.json.bak new file mode 100755 index 0000000000000..466b3f965891e --- /dev/null +++ b/test-pp-op/config-op/state.json.bak @@ -0,0 +1,13 @@ +{ + "version": 1, + "create2Salt": "0x0000000000000000000000000000000000000000000000000000000000000000", + "appliedIntent": null, + "prestateManifest": null, + "superchainContracts": null, + "superchainRoles": null, + "implementationsDeployment": null, + "opChainDeployments": null, + "l1StateDump": null, + "DeploymentCalldata": null +} + diff --git a/test-pp-op/config-op/test.rpc.config.toml b/test-pp-op/config-op/test.rpc.config.toml new file mode 100644 index 0000000000000..d0470fc21f615 --- /dev/null +++ b/test-pp-op/config-op/test.rpc.config.toml @@ -0,0 +1,38 @@ +[Node] +HTTPHost = "0.0.0.0" +HTTPPort = 8545 +HTTPCors = ["*"] +HTTPVirtualHosts = ["*"] +HTTPModules = ["web3", "debug", "eth", "txpool", "net", "engine", "miner", "admin"] +WSHost = "0.0.0.0" +WSPort = 7546 +WSOrigins = ["*"] +WSModules = ["debug", "eth", "txpool", "net", "engine"] +AuthAddr = "0.0.0.0" +AuthPort = 8552 +AuthVirtualHosts = ["*"] +JWTSecret = "/jwt.txt" + +[Node.P2P] +MaxPeers = 30 +DiscoveryV5 = true + +[Eth] +NetworkId = 901 +SyncMode = "full" +EnableInnerTx = true + + +[Eth.GPO] +Blocks = 20 +Percentile = 60 +MaxHeaderHistory = 1024 +MaxBlockHistory = 1024 +MaxPrice = "50000000000" #50GWei +IgnorePrice = "2" +MinSuggestedPriorityFee = 1 + +[Eth.GPO.XLayer] +Type = "default" +UpdatePeriod = 3000000000 # 3s +Default = "100000000" # 0.1 GWei diff --git a/test-pp-op/config-op/test.seq.config.toml b/test-pp-op/config-op/test.seq.config.toml new file mode 100644 index 0000000000000..117652fb59b31 --- /dev/null +++ b/test-pp-op/config-op/test.seq.config.toml @@ -0,0 +1,46 @@ +[Node] +HTTPHost = "0.0.0.0" +HTTPPort = 8545 +HTTPCors = ["*"] +HTTPVirtualHosts = ["*"] +HTTPModules = ["web3", "debug", "eth", "txpool", "net", "engine", "miner", "admin"] +WSHost = "0.0.0.0" +WSPort = 7546 +WSOrigins = ["*"] +WSModules = ["debug", "eth", "txpool", "net", "engine"] +AuthAddr = "0.0.0.0" +AuthPort = 8552 +AuthVirtualHosts = ["*"] +JWTSecret = "/jwt.txt" + +[Node.P2P] +MaxPeers = 30 +DiscoveryV5 = true + +[Eth] +NetworkId = 901 +SyncMode = "full" +EnableInnerTx = true + + + +[Eth.TxPool] +GlobalSlots = 500000 +GlobalQueue = 100000 +AccountSlots = 50000 +AccountQueue = 10000 + + +[Eth.GPO] +Blocks = 20 +Percentile = 60 +MaxHeaderHistory = 1024 +MaxBlockHistory = 1024 +MaxPrice = "50000000000" #50GWei +IgnorePrice = "2" +MinSuggestedPriorityFee = 1 + +[Eth.GPO.XLayer] +Type = "default" +UpdatePeriod = 3000000000 # 3s +Default = "100000000" # 0.1 GWei diff --git a/test-pp-op/config/aggkit.toml b/test-pp-op/config/aggkit.toml new file mode 100644 index 0000000000000..3740349a09bcd --- /dev/null +++ b/test-pp-op/config/aggkit.toml @@ -0,0 +1,129 @@ +PathRWData = "/tmp/" +L1URL="http://l1-geth:8545" + +L2URL="http://xlayer-rpc:8545" + +AggLayerURL="xlayer-agglayer:4443" + +ForkId = 13 +ContractVersions = "banana" +IsValidiumMode = false +NetworkID = 1 + +L2Coinbase = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +SequencerPrivateKeyPath = "/etc/aggkit/sequencer.keystore" +SequencerPrivateKeyPassword = "testonly" + +AggregatorPrivateKeyPath = "/etc/aggkit/aggregator.keystore" +AggregatorPrivateKeyPassword = "testonly" +SenderProofToL1Addr = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" +polygonBridgeAddr = "0xb2fAc1CE54bb9BF77A7FE106fA69F81453b72851" + +rollupCreationBlockNumber = "91" +rollupManagerCreationBlockNumber = "100" +genesisBlockNumber = "91" + +[Common] +NetworkID = 1 +IsValidiumMode = false +ContractVersions = "banana" +# TODO, should we config with base +L2RPC = { Mode = "basic", URL = "{{L2URL}}", OpNodeURL = "http://op-rpc:8545" } + +[L1Config] +chainId = "1337" +polygonZkEVMGlobalExitRootAddress = "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" +polygonRollupManagerAddress = "0xE96dBF374555C6993618906629988d39184716B3" +polTokenAddress = "0x5FbDB2315678afecb367f032d93F642f64180aa3" +polygonZkEVMAddress = "0xE45CCD0757670580a4a3600DE5cef1e45F0Ec2bd" + +[L2Config] +GlobalExitRootAddr = "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa" + +[Log] +Environment = "development" +Level = "debug" +Outputs = ["stderr"] + +[RPC] +Port = 5576 + +[AggSender] +StoragePath = "/tmp/aggsender.sqlite" +AggsenderPrivateKey = {Path = "/etc/aggkit/sequencer.keystore", Password = "testonly"} +CheckStatusCertificateInterval = "1s" +Mode="PessimisticProof" +UseAgglayerTLS = false +MaxCertSize = 0 +MaxL2BlockNumber = 0 +StopOnFinishedSendingAllCertificates = false + +[AggSender.MaxSubmitCertificateRate] +NumRequests = 20 +Interval = "1m" +BlockFinality = "LatestBlock" +SaveCertificatesToFilesPath = "/tmp/certificates" +KeepCertificatesHistory = true +[AggOracle] +BlockFinality = "LatestBlock" +WaitPeriodNextGER = "10s" + +[AggOracle.EVMSender] +GlobalExitRootL2 = "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa" +WaitPeriodMonitorTx = "10s" + +[AggOracle.EVMSender.EthTxManager] +PrivateKeys = [{Path = "/etc/aggkit/aggoracle.keystore", Password = "testonly"}] +[AggOracle.EVMSender.EthTxManager.Etherman] +L1ChainID = "195" + +[BridgeL1Sync] +BlockFinality = "LatestBlock" + +[BridgeL2Sync] +BridgeAddr = "0xb2fAc1CE54bb9BF77A7FE106fA69F81453b72851" + +DBPath = "/tmp/bridgel2sync.sqlite" +BlockFinality = "LatestBlock" + +SyncBlockChunkSize = 1000 + +[ReorgDetectorL1] +DBPath = "/tmp/reorgdetectorl1.sqlite" +LatestBlock="LatestBlock" + +[ReorgDetectorL2] +DBPath = "/tmp/reorgdetectorl2.sqlite" +LatestBlock="LatestBlock" + +[L1InfoTreeSync] +InitialBlock = "36" +BlockFinality = "LatestBlock" + +[LastGERSync] +BlockFinality = "LatestBlock" + +[ClaimSponsor] +DBPath = "/tmp/claimsponsor.sqlite" +Enabled = false + +SenderAddr = "0x5f5dB0D4D58310F53713eF4Df80ba6717868A9f8" + +BridgeAddrL2 = "0xb2fAc1CE54bb9BF77A7FE106fA69F81453b72851" + +[ClaimSponsor.EthTxManager] +PrivateKeys = [ + {Path = "/etc/aggkit/claimtxmanager.keystore", Password = ""}, +] + +StoragePath = "" + +[ClaimSponsor.EthTxManager.Etherman] +URL = "" + +L1ChainID = "195" + +[Profiling] +ProfilingHost = "0.0.0.0" + +ProfilingPort = 6060 \ No newline at end of file diff --git a/test-pp-op/config/agglayer-config.toml b/test-pp-op/config/agglayer-config.toml new file mode 100644 index 0000000000000..d070a4ce6aee8 --- /dev/null +++ b/test-pp-op/config/agglayer-config.toml @@ -0,0 +1,91 @@ +prover-entrypoint = "http://xlayer-agglayer-prover:4445" +debug-mode = true + +# Only supported by fork 12+ +mock-verifier = true + +[full-node-rpcs] +# TODO switch this to permissionless +1 = "http://op-geth-rpc:8545" + +[proof-signers] +1 = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" + +[rpc] +grpc-port = 4443 +readrpc-port = 4444 +admin-port = 4446 +host = "0.0.0.0" +request-timeout = 180 +# size is define in bytes e.g. 100 * 1024 * 1024 +# same for `max_response_body_size` +# default value is equal to 10MB +max-request-body-size = 104857600 + +[prover.grpc] +# size is define in bytes e.g. 100 * 1024 * 1024 +# same for `max-encoding-message-size` +# default value is equal to 4MB +max-decoding-message-size = 104857600 + +[outbound.rpc.settle] +max-retries = 3 +retry-interval = 7 +confirmations = 1 +settlement-timeout = 1200 + +[log] +# level = "info" +# we want debug visibility here for now +level = "debug" +outputs = ["stderr"] +format = "json" + +[auth.local] +private-keys = [ + { path = "/etc/zkevm/agglayer.keystore", password = "testonly" }, +] + +[l1] +chain-id = 1337 +node-url = "http://l1-geth:8545" +ws-node-url = "ws://l1-geth:8546" +rollup-manager-contract = "0xE96dBF374555C6993618906629988d39184716B3" +polygon-zkevm-global-exit-root-v2-contract = "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" +rpc-timeout = 45 + +[l2] +rpc-timeout = 45 + +[telemetry] +prometheus-addr = "0.0.0.0:9092" + +# https://github.com/orgs/agglayer/discussions/213 + +[rate-limiting] +send-tx = "unlimited" +# [rate-limiting.send-tx] +# max-per-interval = 1 +# time-interval = "15m" + +[rate-limiting.network] + +[epoch.block-clock] +epoch-duration = 6 +genesis-block = 0 + +[shutdown] +runtime-timeout = 5 + +[certificate-orchestrator] +input-backpressure-buffer-size = 1000 + +[certificate-orchestrator.prover.sp1-local] + +[storage] +db-path = "/etc/zkevm/storage" + +[storage.backup] +path = "/etc/zkevm/backups" +state-max-backup-count = 100 +pending-max-backup-count = 100 \ No newline at end of file diff --git a/test-pp-op/config/agglayer-prover-config.toml b/test-pp-op/config/agglayer-prover-config.toml new file mode 100644 index 0000000000000..fb7255e14c7f9 --- /dev/null +++ b/test-pp-op/config/agglayer-prover-config.toml @@ -0,0 +1,25 @@ +grpc-endpoint = "0.0.0.0:4445" +max-concurrency-limit = 100 +max-request-duration = 300 +max-buffered-queries = 100 + +[log] +environment = "production" # "production" or "development" +# level = "info" +level = "debug" +outputs = ["stderr"] +format = "json" + +[telemetry] +prometheus-addr = "0.0.0.0:9093" + + +[primary-prover.mock-prover] + +proving-timeout = 900 + +[grpc] +# size is define in bytes e.g. 100 * 1024 * 1024 +# same for `max-encoding-message-size` +# default value is equal to 4MB +max-decoding-message-size = 104857600 \ No newline at end of file diff --git a/test-pp-op/config/cdk.config.toml b/test-pp-op/config/cdk.config.toml new file mode 100644 index 0000000000000..8500a1af38bfc --- /dev/null +++ b/test-pp-op/config/cdk.config.toml @@ -0,0 +1,296 @@ +ForkUpgradeBatchNumber = 0 +ForkUpgradeNewForkId = 0 + +[Log] +Environment = "development" # "production" or "development" +Level = "info" +Outputs = ["stderr"] + +[NetworkConfig.L1] +L1ChainID = 1337 +PolAddr = "0x5FbDB2315678afecb367f032d93F642f64180aa3" +ZkEVMAddr = "0xeb173087729c88a47568AF87b17C653039377BA6" +RollupManagerAddr = "0x2d42E2899662EFf08b13eeb65b154b904C7a1c8a" +GlobalExitRootManagerAddr = "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" + +[Etherman] + URL="http://xlayer-mock-l1-network:8545" + ForkIDChunkSize=100 + [Etherman.EthermanConfig] + URL="http://xlayer-mock-l1-network:8545" + MultiGasProvider=false + L1ChainID=1337 + HTTPHeaders=[] + [Etherman.EthermanConfig.Etherscan] + ApiKey="" + Url="https://api.etherscan.io/api?module=gastracker&action=gasoracle&apikey=" + +[Common] +NetworkID = 1 +IsValidiumMode = true +ContractVersions = "banana" + +[SequenceSender] +WaitPeriodSendSequence = "15s" +LastBatchVirtualizationTimeMaxWaitPeriod = "10s" +L1BlockTimestampMargin = "30s" +MaxTxSizeForL1 = 131072 +L2Coinbase = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +PrivateKey = {Path = "/pk/sequencer.keystore", Password = "testonly"} +SequencesTxFileName = "sequencesender.json" +GasOffset = 80000 +WaitPeriodPurgeTxFile = "60m" +MaxPendingTx = 1 +MaxBatchesForL1 = 300 +BlockFinality = "FinalizedBlock" +RPCURL = "http://xlayer-rpc:8545" +GetBatchWaitInterval = "10s" + [SequenceSender.EthTxManager] + FrequencyToMonitorTxs = "1s" + WaitTxToBeMined = "2m" + GetReceiptMaxTime = "250ms" + GetReceiptWaitInterval = "1s" + PrivateKeys = [ + {Path = "/pk/sequencer.keystore", Password = "testonly"}, + ] + ForcedGas = 0 + GasPriceMarginFactor = 1 + MaxGasPriceLimit = 0 + StoragePath = "/tmp/cdk/ethtxmanager.sqlite" + ReadPendingL1Txs = false + SafeStatusL1NumberOfBlocks = 0 + FinalizedStatusL1NumberOfBlocks = 0 + [SequenceSender.EthTxManager.Etherman] + URL = "http://xlayer-mock-l1-network:8545" + MultiGasProvider = false + L1ChainID = 1337 +[Aggregator] +# GRPC server host +Host = "0.0.0.0" +# GRPC server port +Port = 50081 +RetryTime = "5s" +VerifyProofInterval = "10s" +ProofStatePollingInterval = "5s" +TxProfitabilityCheckerType = "acceptall" +TxProfitabilityMinReward = "1.1" +IntervalAfterWhichBatchConsolidateAnyway="0s" +BatchProofSanityCheckEnabled = true +# ChainID is L2ChainID. Is populated on runtimme +ChainID = 0 +ForkId = 13 +SenderAddress = "0x70997970c51812dc3a010c7d01b50e0d17dc79c8" +CleanupLockedProofsInterval = "2m" +GeneratingProofCleanupThreshold = "10m" +GasOffset = 0 +RPCURL = "http://xlayer-rpc:8545" +WitnessURL = "http://xlayer-rpc:8545" +UseFullWitness = false +SettlementBackend = "l1" +AggLayerTxTimeout = "5m" +AggLayerURL = "" +SyncModeOnlyEnabled = false + [Aggregator.SequencerPrivateKey] + Path = "/pk/sequencer.keystore" + Password = "testonly" + [Aggregator.DB] + Name = "aggregator_db" + User = "aggregator_user" + Password = "aggregator_password" + Host = "xlayer-agg-db-old" + Port = "5432" + EnableLog = false + MaxConns = 200 + [Aggregator.Log] + Environment = "development" # "production" or "development" + Level = "info" + Outputs = ["stderr"] + [Aggregator.EthTxManager] + FrequencyToMonitorTxs = "1s" + WaitTxToBeMined = "2m" + GetReceiptMaxTime = "250ms" + GetReceiptWaitInterval = "1s" + PrivateKeys = [ + {Path = "/pk/aggregator.keystore", Password = "testonly"}, + ] + ForcedGas = 0 + GasPriceMarginFactor = 1 + MaxGasPriceLimit = 0 + StoragePath = "/tmp/cdk/ethtxmanager.sqlite" + ReadPendingL1Txs = false + SafeStatusL1NumberOfBlocks = 0 + FinalizedStatusL1NumberOfBlocks = 0 + [Aggregator.EthTxManager.Etherman] + URL = "http://xlayer-mock-l1-network:8545" + L1ChainID = 1337 + HTTPHeaders = [] + [Aggregator.Synchronizer] + [Aggregator.Synchronizer.Log] + Environment = "development" # "production" or "development" + Level = "info" + Outputs = ["stderr"] + [Aggregator.Synchronizer.SQLDB] + DriverName = "sqlite3" + DataSource = "/tmp/cdk/aggregator_sync_db.sqlite" + [Aggregator.Synchronizer.Synchronizer] + SyncInterval = "10s" + SyncChunkSize = 1000 + GenesisBlockNumber = 123 + SyncUpToBlock = "finalized" + BlockFinality = "finalized" + OverrideStorageCheck = false + [Aggregator.Synchronizer.Etherman] + L1URL = "http://xlayer-mock-l1-network:8545" + ForkIDChunkSize = 100 + L1ChainID = 1337 + PararellBlockRequest = false + [Aggregator.Synchronizer.Etherman.Contracts] + GlobalExitRootManagerAddr = "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" + RollupManagerAddr = "0x2d42E2899662EFf08b13eeb65b154b904C7a1c8a" + ZkEVMAddr = "0xeb173087729c88a47568AF87b17C653039377BA6" + [Aggregator.Synchronizer.Etherman.Validium] + Enabled = true + # L2URL, empty ask to contract + TrustedSequencerURL = "" + RetryOnDACErrorInterval = "1m" + DataSourcePriority = ["trusted", "external"] + [Aggregator.Synchronizer.Etherman.Validium.Translator] + FullMatchRules = [] + [Aggregator.Synchronizer.Etherman.Validium.RateLimit] + NumRequests = 1000 + Interval = "1s" +[ReorgDetectorL1] +DBPath = "/tmp/cdk/reorg_detector_l1.sqlite" + +# Only for AGGORACLE, RPC, AGGSENDER +#[ReorgDetectorL2] +#DBPath = "/tmp/cdk/reorg_detector_l2.sqlite" + +[L1InfoTreeSync] +DBPath = "/tmp/cdk/l1_info_tree_sync.sqlite" +GlobalExitRootAddr="0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" +RollupManagerAddr = "0x2d42E2899662EFf08b13eeb65b154b904C7a1c8a" +SyncBlockChunkSize=10 +BlockFinality="LatestBlock" +WaitForNewBlocksPeriod="100ms" +InitialBlock= 123 + +# Only for AGGORACLE, RPC, AGGSENDER +#[AggOracle] +#TargetChainType="EVM" +#URLRPCL1="" +#BlockFinality="FinalizedBlock" +#WaitPeriodNextGER="100ms" +# [AggOracle.EVMSender] +# GlobalExitRootL2="0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa" +# URLRPCL2="" +# ChainIDL2=195 +# GasOffset=0 +# WaitPeriodMonitorTx="100ms" +# SenderAddr="0x70997970c51812dc3a010c7d01b50e0d17dc79c8" +# [AggOracle.EVMSender.EthTxManager] +# FrequencyToMonitorTxs = "1s" +# WaitTxToBeMined = "2s" +# GetReceiptMaxTime = "250ms" +# GetReceiptWaitInterval = "1s" +# PrivateKeys = [ +# {Path = "/app/keystore/aggoracle.keystore", Password = "testonly"}, +# ] +# ForcedGas = 0 +# GasPriceMarginFactor = 1 +# MaxGasPriceLimit = 0 +# StoragePath = "/tmp/cdk/ethtxmanager-sequencesender.sqlite" +# ReadPendingL1Txs = false +# SafeStatusL1NumberOfBlocks = 5 +# FinalizedStatusL1NumberOfBlocks = 10 +# [AggOracle.EVMSender.EthTxManager.Etherman] +# URL = "http://xlayer-mock-l1-network:8545" +# MultiGasProvider = false +# L1ChainID = 1337 +# HTTPHeaders = [] + +# Only for RPC +#[RPC] +#Host = "0.0.0.0" +#Port = 5576 +#ReadTimeout = "2s" +#WriteTimeout = "2s" +#MaxRequestsPerIPAndSecond = 10 + +# Only for RPC +#[ClaimSponsor] +#DBPath = "/tmp/cdk/claimsopnsor.sqlite" +#Enabled = true +#SenderAddr = "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +#BridgeAddrL2 = "0x3a277Fa4E78cc1266F32E26c467F99A8eAEfF7c3" +#MaxGas = 200000 +#RetryAfterErrorPeriod = "1s" +#MaxRetryAttemptsAfterError = -1 +#WaitTxToBeMinedPeriod = "3s" +#WaitOnEmptyQueue = "3s" +#GasOffset = 0 +# [ClaimSponsor.EthTxManager] +# FrequencyToMonitorTxs = "1s" +# WaitTxToBeMined = "2s" +# GetReceiptMaxTime = "250ms" +# GetReceiptWaitInterval = "1s" +# PrivateKeys = [ +# {Path = "/app/keystore/claimsopnsor.keystore", Password = "testonly"}, +# ] +# ForcedGas = 0 +# GasPriceMarginFactor = 1 +# MaxGasPriceLimit = 0 +# StoragePath = "/tmp/cdk/ethtxmanager-claimsponsor.sqlite" +# ReadPendingL1Txs = false +# SafeStatusL1NumberOfBlocks = 5 +# FinalizedStatusL1NumberOfBlocks = 10 +# [ClaimSponsor.EthTxManager.Etherman] +# URL = "http://xlayer-mock-l1-network:8545" +# MultiGasProvider = false +# L1ChainID = 1337 +# HTTPHeaders = [] + +# Only for RPC +#[BridgeL1Sync] +#DBPath = "/tmp/cdk/bridgel1sync.sqlite" +#BlockFinality = "LatestBlock" +#InitialBlockNum = 0 +#BridgeAddr = "0x3a277Fa4E78cc1266F32E26c467F99A8eAEfF7c3" +#SyncBlockChunkSize = 100 +#RetryAfterErrorPeriod = "1s" +#MaxRetryAttemptsAfterError = -1 +#WaitForNewBlocksPeriod = "3s" +#OriginNetwork=0 + +# For RPC and aggsender +#[BridgeL2Sync] +#DBPath = "/tmp/cdk/bridgel2sync.sqlite" +#BlockFinality = "LatestBlock" +#InitialBlockNum = 0 +#BridgeAddr = "0x3a277Fa4E78cc1266F32E26c467F99A8eAEfF7c3" +#SyncBlockChunkSize = 100 +#RetryAfterErrorPeriod = "1s" +#MaxRetryAttemptsAfterError = -1 +#WaitForNewBlocksPeriod = "3s" +#OriginNetwork=1 + +# Only for RPC +#[LastGERSync] +## MDBX database path +#DBPath = "/tmp/cdk/lastgersync.sqlite" +#BlockFinality = "LatestBlock" +#InitialBlockNum = 0 +#GlobalExitRootL2Addr = "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa" +#RetryAfterErrorPeriod = "1s" +#MaxRetryAttemptsAfterError = -1 +#WaitForNewBlocksPeriod = "1s" +#DownloadBufferSize = 100 + +#[AggSender] +#StoragePath = "/tmp/cdk/aggsender.sqlite" +#AggLayerURL = "" +#AggsenderPrivateKey = {Path = "/pk/sequencer.keystore", Password = "testonly"} +#BlockGetInterval = "2s" +#URLRPCL2="http://xlayer-rpc:8545" +#CheckSettledInterval = "2s" +#SaveCertificatesToFiles = false \ No newline at end of file diff --git a/test-pp-op/config/dynamic-mynetwork-allocs.json b/test-pp-op/config/dynamic-mynetwork-allocs.json new file mode 100644 index 0000000000000..013af5343dd56 --- /dev/null +++ b/test-pp-op/config/dynamic-mynetwork-allocs.json @@ -0,0 +1,100 @@ +{ + "0x1eDa899fE24907035Ed6F5C6472a1f1E627aB359": { + "contractName": "BytecodeStorer", + "balance": "0", + "nonce": "1", + "code": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c8063c514f24e1461002d575b5f5ffd5b61003561004b565b604051610042919061006a565b60405180910390f35b60405180610f000160405280610ec881526020016100b6610ec8913981565b602081525f82518060208401525f5b818110156100965760208186018101516040868401015201610079565b505f604082850101526040601f19601f8301168401019150509291505056fe60806040819052631d97f74d60e11b81523390633b2fee9a90608490602090600481865afa158015610033573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100579190610433565b604080515f80825260208201909252905061007382825f6100e2565b50506100dd336001600160a01b03166338b8fbbb6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100b4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100d89190610433565b61010d565b6104c8565b6100eb8361017a565b5f825111806100f75750805b156101085761010683836101b9565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61014c5f516020610e815f395f51905f52546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1610177816101e5565b50565b61018381610280565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606101de8383604051806060016040528060278152602001610ea160279139610314565b9392505050565b6001600160a01b03811661024f5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b805f516020610e815f395f51905f525b80546001600160a01b0319166001600160a01b039290921691909117905550565b6001600160a01b0381163b6102ed5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610246565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61025f565b60605f5f856001600160a01b031685604051610330919061047b565b5f60405180830381855af49150503d805f8114610368576040519150601f19603f3d011682016040523d82523d5f602084013e61036d565b606091505b50909250905061037f86838387610389565b9695505050505050565b606083156103f75782515f036103f0576001600160a01b0385163b6103f05760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610246565b5081610401565b6104018383610409565b949350505050565b8151156104195781518083602001fd5b8060405162461bcd60e51b81526004016102469190610496565b5f60208284031215610443575f5ffd5b81516001600160a01b03811681146101de575f5ffd5b5f5b8381101561047357818101518382015260200161045b565b50505f910152565b5f825161048c818460208701610459565b9190910192915050565b602081525f82518060208401526104b4816040850160208701610459565b601f01601f19169190910160400192915050565b6109ac806104d55f395ff3fe60806040526004361061005d575f3560e01c80635c60da1b116100425780635c60da1b146100a65780638f283970146100e3578063f851a440146101025761006c565b80633659cfe6146100745780634f1ef286146100935761006c565b3661006c5761006a610116565b005b61006a610116565b34801561007f575f5ffd5b5061006a61008e366004610854565b610130565b61006a6100a136600461086d565b610178565b3480156100b1575f5ffd5b506100ba6101eb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ee575f5ffd5b5061006a6100fd366004610854565b610228565b34801561010d575f5ffd5b506100ba610255565b61011e610282565b61012e610129610359565b610362565b565b610138610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d8160405180602001604052805f8152505f6103bf565b50565b61016d610116565b610180610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101e3576101de8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250600192506103bf915050565b505050565b6101de610116565b5f6101f4610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610359565b905090565b610225610116565b90565b610230610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d816103e9565b5f61025e610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610380565b61028a610380565b73ffffffffffffffffffffffffffffffffffffffff16330361012e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b5f61021861044a565b365f5f375f5f365f845af43d5f5f3e80801561037c573d5ff35b3d5ffd5b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6103c883610471565b5f825111806103d45750805b156101de576103e383836104bd565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610412610380565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161016d816104e9565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103a3565b61047a816105f5565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606104e28383604051806060016040528060278152602001610979602791396106c0565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661058c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610350565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b73ffffffffffffffffffffffffffffffffffffffff81163b610699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610350565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105af565b60605f5f8573ffffffffffffffffffffffffffffffffffffffff16856040516106e9919061090d565b5f60405180830381855af49150503d805f8114610721576040519150601f19603f3d011682016040523d82523d5f602084013e610726565b606091505b509150915061073786838387610741565b9695505050505050565b606083156107d65782515f036107cf5773ffffffffffffffffffffffffffffffffffffffff85163b6107cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610350565b50816107e0565b6107e083836107e8565b949350505050565b8151156107f85781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103509190610928565b803573ffffffffffffffffffffffffffffffffffffffff8116811461084f575f5ffd5b919050565b5f60208284031215610864575f5ffd5b6104e28261082c565b5f5f5f6040848603121561087f575f5ffd5b6108888461082c565b9250602084013567ffffffffffffffff8111156108a3575f5ffd5b8401601f810186136108b3575f5ffd5b803567ffffffffffffffff8111156108c9575f5ffd5b8660208284010111156108da575f5ffd5b939660209190910195509293505050565b5f5b838110156109055781810151838201526020016108ed565b50505f910152565b5f825161091e8184602087016108eb565b9190910192915050565b602081525f82518060208401526109468160408501602087016108eb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300081c000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220f9f921f910b22a2a14f9dce017cc4be5206c1f1f3690adcea59699078c36984a64736f6c634300081c0033", + "storage": null + }, + "0xccF2F75629fF55768cAF87F9D2e733dee92373DC": { + "contractName": "TokenWrapped Implementation", + "balance": "0", + "nonce": "1", + "code": "0x608060405234801561000f575f5ffd5b5060043610610106575f3560e01c806370a082311161009e5780639dc29fac1161006e5780639dc29fac1461023c578063a3c573eb1461024f578063a9059cbb14610297578063d505accf146102aa578063dd62ed3e146102bd575f5ffd5b806370a08231146101f35780637ecebe001461020657806384b0196e1461021957806395d89b4114610234575f5ffd5b806323b872dd116100d957806323b872dd14610191578063313ce567146101a45780633644e515146101d857806340c10f19146101e0575f5ffd5b806306fdde031461010a578063095ea7b3146101285780631624f6c61461014b57806318160ddd14610160575b5f5ffd5b610112610314565b60405161011f919061115f565b60405180910390f35b61013b610136366004611193565b6103b9565b604051901515815260200161011f565b61015e61015936600461126a565b6103d2565b005b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b60405190815260200161011f565b61013b61019f3660046112de565b61054a565b7f863b064fe9383d75d38f584f64f1aaba4520e9ebc98515fa15bdeae8c4274d005460405160ff909116815260200161011f565b61018361056d565b61015e6101ee366004611193565b61057b565b610183610201366004611318565b6105de565b610183610214366004611318565b61060e565b610221610618565b60405161011f9796959493929190611331565b6101126106ce565b61015e61024a366004611193565b61070c565b7f863b064fe9383d75d38f584f64f1aaba4520e9ebc98515fa15bdeae8c4274d005461010090046001600160a01b03166040516001600160a01b03909116815260200161011f565b61013b6102a5366004611193565b61076a565b61015e6102b83660046113c7565b610777565b6101836102cb36600461142d565b6001600160a01b039182165f9081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b60605f5f5160206115c95f395f51905f525b90508060030180546103379061145e565b80601f01602080910402602001604051908101604052809291908181526020018280546103639061145e565b80156103ae5780601f10610385576101008083540402835291602001916103ae565b820191905f5260205f20905b81548152906001019060200180831161039157829003601f168201915b505050505091505090565b5f336103c68185856108cc565b60019150505b92915050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f8115801561041c5750825b90505f8267ffffffffffffffff1660011480156104385750303b155b905081158015610446575080155b156104645760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561049857845468ff00000000000000001916680100000000000000001785555b6104a288886108d9565b6104ab886108ef565b7f863b064fe9383d75d38f584f64f1aaba4520e9ebc98515fa15bdeae8c4274d00805460ff881674ffffffffffffffffffffffffffffffffffffffffff19909116176101003302179055831561054057845468ff000000000000000019168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b5050505050505050565b5f3361055785828561091d565b6105628585856109b7565b506001949350505050565b5f610576610a14565b905090565b5f7f863b064fe9383d75d38f584f64f1aaba4520e9ebc98515fa15bdeae8c4274d00805490915061010090046001600160a01b031633146105cf576040516338da3b1560e01b815260040160405180910390fd5b6105d98383610a1d565b505050565b5f805f5160206115c95f395f51905f525b6001600160a01b039093165f9081526020939093525050604090205490565b5f6103cc82610a51565b5f60608082808083815f5160206115e95f395f51905f52805490915015801561064357506001810154155b6106945760405162461bcd60e51b815260206004820152601560248201527f4549503731323a20556e696e697469616c697a6564000000000000000000000060448201526064015b60405180910390fd5b61069c610a5b565b6106a4610a99565b604080515f80825260208201909252600f60f81b9c939b5091995046985030975095509350915050565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060915f5160206115c95f395f51905f52916103379061145e565b5f7f863b064fe9383d75d38f584f64f1aaba4520e9ebc98515fa15bdeae8c4274d00805490915061010090046001600160a01b03163314610760576040516338da3b1560e01b815260040160405180910390fd5b6105d98383610aaf565b5f336103c68185856109b7565b8342111561079b5760405163313c898160e11b81526004810185905260240161068b565b5f7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98888886108058c6001600160a01b03165f9081527f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb006020526040902080546001810190915590565b6040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61085f82610ae3565b90505f61086e82878787610b0f565b9050896001600160a01b0316816001600160a01b0316146108b5576040516325c0072360e11b81526001600160a01b0380831660048301528b16602482015260440161068b565b6108c08a8a8a6108cc565b50505050505050505050565b6105d98383836001610b3b565b6108e1610c1f565b6108eb8282610c6f565b5050565b6108f7610c1f565b61091a81604051806040016040528060018152602001603160f81b815250610cbf565b50565b6001600160a01b038381165f9081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0160209081526040808320938616835292905220545f1981146109b157818110156109a357604051637dc7a0d960e11b81526001600160a01b0384166004820152602481018290526044810183905260640161068b565b6109b184848484035f610b3b565b50505050565b6001600160a01b0383166109e057604051634b637e8f60e11b81525f600482015260240161068b565b6001600160a01b038216610a095760405163ec442f0560e01b81525f600482015260240161068b565b6105d9838383610d1e565b5f610576610e57565b6001600160a01b038216610a465760405163ec442f0560e01b81525f600482015260240161068b565b6108eb5f8383610d1e565b5f6103cc82610eca565b7fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d10280546060915f5160206115e95f395f51905f52916103379061145e565b60605f5f5160206115e95f395f51905f52610326565b6001600160a01b038216610ad857604051634b637e8f60e11b81525f600482015260240161068b565b6108eb825f83610d1e565b5f6103cc610aef610a14565b8360405161190160f01b8152600281019290925260228201526042902090565b5f5f5f5f610b1f88888888610ef2565b925092509250610b2f8282610fba565b50909695505050505050565b5f5160206115c95f395f51905f526001600160a01b038516610b725760405163e602df0560e01b81525f600482015260240161068b565b6001600160a01b038416610b9b57604051634a1406b160e11b81525f600482015260240161068b565b6001600160a01b038086165f90815260018301602090815260408083209388168352929052208390558115610c1857836001600160a01b0316856001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051610c0f91815260200190565b60405180910390a35b5050505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff16610c6d57604051631afcd79f60e31b815260040160405180910390fd5b565b610c77610c1f565b5f5160206115c95f395f51905f527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace03610cb084826114da565b50600481016109b183826114da565b610cc7610c1f565b5f5160206115e95f395f51905f527fa16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d102610d0084826114da565b5060038101610d0f83826114da565b505f8082556001909101555050565b5f5160206115c95f395f51905f526001600160a01b038416610d585781816002015f828254610d4d9190611595565b90915550610dc89050565b6001600160a01b0384165f9081526020829052604090205482811015610daa5760405163391434e360e21b81526001600160a01b0386166004820152602481018290526044810184905260640161068b565b6001600160a01b0385165f9081526020839052604090209083900390555b6001600160a01b038316610de6576002810180548390039055610e04565b6001600160a01b0383165f9081526020829052604090208054830190555b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e4991815260200190565b60405180910390a350505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610e81611072565b610e896110da565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f807f5ab42ced628888259c08ac98db1eb0cf702fc1501344311d8b100cd1bfe4bb006105ef565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0841115610f2b57505f91506003905082610fb0565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa158015610f7c573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116610fa757505f925060019150829050610fb0565b92505f91508190505b9450945094915050565b5f826003811115610fcd57610fcd6115b4565b03610fd6575050565b6001826003811115610fea57610fea6115b4565b036110085760405163f645eedf60e01b815260040160405180910390fd5b600282600381111561101c5761101c6115b4565b0361103d5760405163fce698f760e01b81526004810182905260240161068b565b6003826003811115611051576110516115b4565b036108eb576040516335e2f38360e21b81526004810182905260240161068b565b5f5f5160206115e95f395f51905f528161108a610a5b565b8051909150156110a257805160209091012092915050565b815480156110b1579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b5f5f5160206115e95f395f51905f52816110f2610a99565b80519091501561110a57805160209091012092915050565b600182015480156110b1579392505050565b5f81518084525f5b8181101561114057602081850181015186830182015201611124565b505f602082860101526020601f19601f83011685010191505092915050565b602081525f611171602083018461111c565b9392505050565b80356001600160a01b038116811461118e575f5ffd5b919050565b5f5f604083850312156111a4575f5ffd5b6111ad83611178565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f8301126111de575f5ffd5b813567ffffffffffffffff8111156111f8576111f86111bb565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611227576112276111bb565b60405281815283820160200185101561123e575f5ffd5b816020850160208301375f918101602001919091529392505050565b803560ff8116811461118e575f5ffd5b5f5f5f6060848603121561127c575f5ffd5b833567ffffffffffffffff811115611292575f5ffd5b61129e868287016111cf565b935050602084013567ffffffffffffffff8111156112ba575f5ffd5b6112c6868287016111cf565b9250506112d56040850161125a565b90509250925092565b5f5f5f606084860312156112f0575f5ffd5b6112f984611178565b925061130760208501611178565b929592945050506040919091013590565b5f60208284031215611328575f5ffd5b61117182611178565b60ff60f81b8816815260e060208201525f61134f60e083018961111c565b8281036040840152611361818961111c565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152845180825260208087019350909101905f5b818110156113b6578351835260209384019390920191600101611398565b50909b9a5050505050505050505050565b5f5f5f5f5f5f5f60e0888a0312156113dd575f5ffd5b6113e688611178565b96506113f460208901611178565b955060408801359450606088013593506114106080890161125a565b9699959850939692959460a0840135945060c09093013592915050565b5f5f6040838503121561143e575f5ffd5b61144783611178565b915061145560208401611178565b90509250929050565b600181811c9082168061147257607f821691505b60208210810361149057634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156105d957805f5260205f20601f840160051c810160208510156114bb5750805b601f840160051c820191505b81811015610c18575f81556001016114c7565b815167ffffffffffffffff8111156114f4576114f46111bb565b61150881611502845461145e565b84611496565b6020601f82116001811461153a575f83156115235750848201515b5f19600385901b1c1916600184901b178455610c18565b5f84815260208120601f198516915b828110156115695787850151825560209485019460019092019101611549565b508482101561158657868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b808201808211156103cc57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52602160045260245ffdfe52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00a16a46d94261c7517cc8ff89f61c0ce93598e3c849801011dee649a6a557d100a2646970667358221220f0e100f498b6f41fbf597025b81d217623a1e4b7d8ee5bf92572b87e86172a6264736f6c634300081c0033", + "storage": null + }, + "0x9C1aBd1fB3569e951DcC3cd5D678a7a618088CFa": { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "4", + "code": "0x60806040526004361061006e575f3560e01c8063715018a61161004c578063715018a6146100e25780638da5cb5b146100f6578063e11ae6cb1461011f578063f2fde38b14610132575f80fd5b80632b79805a146100725780634a94d487146100875780636d07dbf81461009a575b5f80fd5b610085610080366004610908565b610151565b005b6100856100953660046109a2565b6101c2565b3480156100a5575f80fd5b506100b96100b43660046109f5565b610203565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ed575f80fd5b50610085610215565b348015610101575f80fd5b505f5473ffffffffffffffffffffffffffffffffffffffff166100b9565b61008561012d366004610a15565b610228565b34801561013d575f80fd5b5061008561014c366004610a61565b61028e565b61015961034a565b5f6101658585856103ca565b90506101718183610527565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101ca61034a565b6101d583838361056a565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b905f90a1505050565b5f61020e8383610598565b9392505050565b61021d61034a565b6102265f6105a4565b565b61023061034a565b5f61023c8484846103ca565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b61029661034a565b73ffffffffffffffffffffffffffffffffffffffff811661033e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610347816105a4565b50565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610226576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610335565b5f83471015610435576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610335565b81515f0361049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610335565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff811661020e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610335565b606061020e83835f6040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610618565b6060610590848484604051806060016040528060298152602001610b0860299139610618565b949350505050565b5f61020e83833061072d565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610335565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516106d29190610a9c565b5f6040518083038185875af1925050503d805f811461070c576040519150601f19603f3d011682016040523d82523d5f602084013e610711565b606091505b509150915061072287838387610756565b979650505050505050565b5f604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156107eb5782515f036107e45773ffffffffffffffffffffffffffffffffffffffff85163b6107e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610335565b5081610590565b61059083838151156108005781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103359190610ab7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112610870575f80fd5b813567ffffffffffffffff8082111561088b5761088b610834565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108d1576108d1610834565b816040528381528660208588010111156108e9575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f806080858703121561091b575f80fd5b8435935060208501359250604085013567ffffffffffffffff80821115610940575f80fd5b61094c88838901610861565b93506060870135915080821115610961575f80fd5b5061096e87828801610861565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff8116811461099d575f80fd5b919050565b5f805f606084860312156109b4575f80fd5b6109bd8461097a565b9250602084013567ffffffffffffffff8111156109d8575f80fd5b6109e486828701610861565b925050604084013590509250925092565b5f8060408385031215610a06575f80fd5b50508035926020909101359150565b5f805f60608486031215610a27575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115610a4b575f80fd5b610a5786828701610861565b9150509250925092565b5f60208284031215610a71575f80fd5b61020e8261097a565b5f5b83811015610a94578181015183820152602001610a7c565b50505f910152565b5f8251610aad818460208701610a7a565b9190910192915050565b602081525f8251806020840152610ad5816040850160208701610a7a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a26469706673582212206c37fb6ca2362734c4736703fbea1e2f5c6060623d61a5acc99beb96437a122364736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000008f8e2d6cf621f30e9a11309d6a56a876281fd534" + } + }, + "0xc2c5fb710E85BedC5C18A8a0Fa931D75983F2185": { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "code": "0x608060405260043610610079575f3560e01c80639623609d1161004c5780639623609d1461012357806399a88ec414610136578063f2fde38b14610155578063f3b7dead14610174575f5ffd5b8063204e1c7a1461007d578063715018a6146100c55780637eff275e146100db5780638da5cb5b146100fa575b5f5ffd5b348015610088575f5ffd5b5061009c6100973660046105e8565b610193565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d0575f5ffd5b506100d9610244565b005b3480156100e6575f5ffd5b506100d96100f536600461060a565b610257565b348015610105575f5ffd5b505f5473ffffffffffffffffffffffffffffffffffffffff1661009c565b6100d961013136600461066e565b6102e0565b348015610141575f5ffd5b506100d961015036600461060a565b610371565b348015610160575f5ffd5b506100d961016f3660046105e8565b6103cd565b34801561017f575f5ffd5b5061009c61018e3660046105e8565b610489565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b5f60405180830381855afa9150503d805f8114610215576040519150601f19603f3d011682016040523d82523d5f602084013e61021a565b606091505b509150915081610228575f5ffd5b8080602001905181019061023c9190610782565b949350505050565b61024c6104d3565b6102555f610553565b565b61025f6104d3565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b5f604051808303815f87803b1580156102c6575f5ffd5b505af11580156102d8573d5f5f3e3d5ffd5b505050505050565b6102e86104d3565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061033e908690869060040161079d565b5f604051808303818588803b158015610355575f5ffd5b505af1158015610367573d5f5f3e3d5ffd5b5050505050505050565b6103796104d3565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102af565b6103d56104d3565b73ffffffffffffffffffffffffffffffffffffffff811661047d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61048681610553565b50565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610474565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610486575f5ffd5b5f602082840312156105f8575f5ffd5b8135610603816105c7565b9392505050565b5f5f6040838503121561061b575f5ffd5b8235610626816105c7565b91506020830135610636816105c7565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f5f60608486031215610680575f5ffd5b833561068b816105c7565b9250602084013561069b816105c7565b9150604084013567ffffffffffffffff8111156106b6575f5ffd5b8401601f810186136106c6575f5ffd5b803567ffffffffffffffff8111156106e0576106e0610641565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561074c5761074c610641565b604052818152828201602001881015610763575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f60208284031215610792575f5ffd5b8151610603816105c7565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f82518060408401525f5b818110156107e557602081860181015160608684010152016107c8565b505f6060828501015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116840101915050939250505056fea26469706673582212208ab8743c787ecb046e26764a23735b65ae0affe7a9153fa2f3410ff80a26ba0464736f6c634300081c0033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000027284dba79e6df953fbd232a9d8d87029f03bbf5" + } + }, + "0x12060cA70f50A24fde90fEA110002C235f558a56": { + "contractName": "PolygonZkEVMBridgeV2 implementation", + "balance": "0", + "nonce": "3", + "code": "0x608060405260043610610233575f3560e01c806383f2440311610129578063ccaa2d11116100a8578063ee25560b1161006d578063ee25560b146106fe578063f214e16114610729578063f5efcd7914610748578063f811bff714610767578063fb57083414610786575f5ffd5b8063ccaa2d1114610671578063cd58657914610690578063d02103ca146106a3578063dbc16976146106cb578063ece93c6f146106df575f5ffd5b8063bab161bf116100ee578063bab161bf146105db578063be5831c7146105fc578063c00f14ab1461061f578063c514f24e1461063e578063cc46163214610652575f5ffd5b806383f244031461054b5780638bd309c31461056a5780638c668f1c146105895780638ed7e3f21461059d578063b8b284d0146105bc575f5ffd5b80633c351e10116101b557806365d6f6541161017a57806365d6f6541461049c5780636e4ecfed146104d057806379e2cf97146104ef5780638129fc1c1461050357806381b1c17414610517575f5ffd5b80633c351e10146103f35780633cbc795b146104125780633e1970431461044a5780634b2f336d146104695780635ca1e16514610488575f5ffd5b80632dfdf0b5116101fb5780632dfdf0b5146102e6578063318aee3d14610309578063381fef6d1461037157806338b8fbbb146103a45780633b2fee9a146103c1575f5ffd5b806315064c96146102375780632072f6c51461026557806322e95f2c1461027b578063240ff378146102b257806327aef4e8146102c5575b5f5ffd5b348015610242575f5ffd5b506068546102509060ff1681565b60405190151581526020015b60405180910390f35b348015610270575f5ffd5b506102796107a5565b005b348015610286575f5ffd5b5061029a610295366004612f92565b6107da565b6040516001600160a01b03909116815260200161025c565b6102796102c0366004613019565b610844565b3480156102d0575f5ffd5b506102d96108b4565b60405161025c91906130db565b3480156102f1575f5ffd5b506102fb60535481565b60405190815260200161025c565b348015610314575f5ffd5b5061034d6103233660046130ed565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b0390911660208301520161025c565b34801561037c575f5ffd5b5061029a7f0000000000000000000000001eda899fe24907035ed6f5c6472a1f1e627ab35981565b3480156103af575f5ffd5b506070546001600160a01b031661029a565b3480156103cc575f5ffd5b507f000000000000000000000000ccf2f75629ff55768caf87f9d2e733dee92373dc61029a565b3480156103fe575f5ffd5b50606d5461029a906001600160a01b031681565b34801561041d575f5ffd5b50606d5461043590600160a01b900463ffffffff1681565b60405163ffffffff909116815260200161025c565b348015610455575f5ffd5b506102fb610464366004613116565b610940565b348015610474575f5ffd5b50606f5461029a906001600160a01b031681565b348015610493575f5ffd5b506102fb6109d1565b3480156104a7575f5ffd5b506102d9604051806040016040528060098152602001680616c2d76302e332e360bc1b81525081565b3480156104db575f5ffd5b5060705461029a906001600160a01b031681565b3480156104fa575f5ffd5b50610279610a50565b34801561050e575f5ffd5b50610279610a71565b348015610522575f5ffd5b5061029a610531366004613190565b606a6020525f90815260409020546001600160a01b031681565b348015610556575f5ffd5b506102fb6105653660046131b8565b610baf565b348015610575575f5ffd5b506102796105843660046130ed565b610c3e565b348015610594575f5ffd5b50610279610ccc565b3480156105a8575f5ffd5b50606c5461029a906001600160a01b031681565b3480156105c7575f5ffd5b506102796105d63660046131f4565b610d5d565b3480156105e6575f5ffd5b5060685461043590610100900463ffffffff1681565b348015610607575f5ffd5b5060685461043590600160c81b900463ffffffff1681565b34801561062a575f5ffd5b506102d96106393660046130ed565b610ddb565b348015610649575f5ffd5b506102d9610e20565b34801561065d575f5ffd5b5061025061066c366004613272565b610ea9565b34801561067c575f5ffd5b5061027961068b3660046132a3565b610f31565b61027961069e366004613382565b61136e565b3480156106ae575f5ffd5b5060685461029a906501000000000090046001600160a01b031681565b3480156106d6575f5ffd5b5061027961170a565b3480156106ea575f5ffd5b5060715461029a906001600160a01b031681565b348015610709575f5ffd5b506102fb610718366004613190565b60696020525f908152604090205481565b348015610734575f5ffd5b5061029a610743366004612f92565b61173d565b348015610753575f5ffd5b506102796107623660046132a3565b61182a565b348015610772575f5ffd5b5061027961078136600461347e565b611a8a565b348015610791575f5ffd5b506102506107a036600461354e565b611d6c565b606c546001600160a01b031633146107d057604051631736745960e31b815260040160405180910390fd5b6107d8611d83565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff161561086857604051630bc011ff60e21b815260040160405180910390fd5b34158015906108815750606f546001600160a01b031615155b1561089f576040516301bd897160e61b815260040160405180910390fd5b6108ad858534868686611dde565b5050505050565b606e80546108c190613593565b80601f01602080910402602001604051908101604052809291908181526020018280546108ed90613593565b80156109385780601f1061090f57610100808354040283529160200191610938565b820191905f5260205f20905b81548152906001019060200180831161091b57829003601f168201915b505050505081565b6040516001600160f81b031960f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610a47578083901c600116600103610a2057610a1960338260208110610a0857610a086135cb565b0154855f9182526020526040902090565b9350610a30565b5f84815260208390526040902093505b5f82815260208390526040902091506001016109db565b50919392505050565b605354606854600160c81b900463ffffffff1610156107d8576107d8611eba565b5f5460ff166071805460ff60a01b1916600160a01b60ff938416021790555f5460029161010090910416158015610aae57505f5460ff8083169116105b610b165760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805461ffff191660ff80841691909117610100178255607154600160a01b9004169003610b575760405163f57ac68360e01b815260040160405180910390fd5b610b5f611f50565b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a1506071805460ff60a01b19169055565b5f83815b6020811015610c3357600163ffffffff8516821c81169003610bff57610bf8858260208110610be457610be46135cb565b6020020135835f9182526020526040902090565b9150610c2b565b610c2882868360208110610c1557610c156135cb565b60200201355f9182526020526040902090565b91505b600101610bb3565b5090505b9392505050565b6070546001600160a01b03163314610c6957604051630866750360e01b815260040160405180910390fd5b607180546001600160a01b0319166001600160a01b038381169182179092556070546040805191909316815260208101919091527f0a34baa3feb299aef9c05cb59c6e0c8e7c0bcc65cbf0a647e7a7c8a2411591e291015b60405180910390a150565b6071546001600160a01b03163314610cf757604051630b59ef2760e21b815260040160405180910390fd5b60708054607180546001600160a01b038082166001600160a01b0319808616821790965594909116909155604080519190921680825260208201939093527fa9da6fb8c39e9c2fafda878eac316815987bdc948d241ba6d75ed035e0e829f29101610cc1565b60685460ff1615610d8157604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610daa5760405163dde3cda760e01b815260040160405180910390fd5b606f545f90610dc2906001600160a01b031686612071565b9050610dd2878783878787611dde565b50505050505050565b6060610de6826120d5565b610def83612198565b610df88461224c565b604051602001610e0a939291906135df565b6040516020818303038152906040529050919050565b60607f0000000000000000000000001eda899fe24907035ed6f5c6472a1f1e627ab3596001600160a01b031663c514f24e6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610e7d573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610ea49190810190613645565b905090565b6068545f908190610100900463ffffffff16158015610ece575063ffffffff83166001145b15610ee0575063ffffffff8316610f08565b610ef564010000000063ffffffff851661369e565b610f059063ffffffff86166136b5565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610f5557604051630bc011ff60e21b815260040160405180910390fd5b610f5d612300565b60685463ffffffff8681166101009092041614610f8d576040516302caf51760e11b815260040160405180910390fd5b610fb88c8c8c8c8c5f8d8d8d8d8d8d8d604051610fab9291906136c8565b6040518091039020612359565b6001600160a01b038616158015610fd3575063ffffffff8716155b156110b157606f546001600160a01b0316611095575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015611020576020820181803683370190505b5060405161102e91906136d7565b5f6040518083038185875af1925050503d805f8114611068576040519150601f19603f3d011682016040523d82523d5f602084013e61106d565b606091505b505090508061108f57604051630ce8f45160e31b815260040160405180910390fd5b506112fb565b606f546110ac906001600160a01b03168585612375565b6112fb565b606d546001600160a01b0387811691161480156110df5750606d5463ffffffff888116600160a01b90920416145b156110f6575f6001600160a01b0385168482610ff6565b60685463ffffffff610100909104811690881603611122576110ac6001600160a01b03871685856123ce565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b0316806112ed575f6111cc8386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061243292505050565b90506111d9818888612375565b80606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516112df95949392919061371a565b60405180910390a1506112f8565b6112f8818787612375565b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a161136060018055565b505050505050505050505050565b60685460ff161561139257604051630bc011ff60e21b815260040160405180910390fd5b61139a612300565b60685463ffffffff6101009091048116908816036113cb576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b0388166114ae578834146113fe5760405163b89240f560e01b815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff1694509061142b90613593565b80601f016020809104026020016040519081016040528092919081815260200182805461145790613593565b80156114a25780601f10611479576101008083540402835291602001916114a2565b820191905f5260205f20905b81548152906001019060200180831161148557829003601f168201915b50505050509150611692565b34156114cd5760405163798ee6f160e01b815260040160405180910390fd5b84156114de576114de888787612519565b606f546001600160a01b0390811690891603611505576114fe888a612071565b9050611692565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901515806115585750805163ffffffff1615155b1561157a57611567898b612071565b6020820151825190965094509150611685565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156115be573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e29190613762565b90506115f96001600160a01b038b1633308e612833565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561163d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116619190613762565b905061166d8282613779565b6068548c9850610100900463ffffffff169650935050505b61168e89610ddb565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e86886053546040516116d198979695949392919061378c565b60405180910390a16116ef5f84868e8e86888051906020012061286c565b86156116fd576116fd611eba565b50505050610dd260018055565b606c546001600160a01b0316331461173557604051631736745960e31b815260040160405180910390fd5b6107d8612883565b6040516001600160e01b031960e084901b1660208201526bffffffffffffffffffffffff19606083901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308361179c610e20565b6040516020016117ac91906136d7565b6040516020818303038152906040528051906020012060405160200161180994939291906001600160f81b031994909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012095945050505050565b60685460ff161561184e57604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff868116610100909204161461187e576040516302caf51760e11b815260040160405180910390fd5b61189d8c8c8c8c8c60018d8d8d8d8d8d8d604051610fab9291906136c8565b606f545f906001600160a01b031661195057846001600160a01b031684888a86866040516024016118d19493929190613800565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161190691906136d7565b5f6040518083038185875af1925050503d805f8114611940576040519150601f19603f3d011682016040523d82523d5f602084013e611945565b606091505b505080915050611a01565b606f54611967906001600160a01b03168686612375565b846001600160a01b0316878985856040516024016119889493929190613800565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b179052516119bd91906136d7565b5f604051808303815f865af19150503d805f81146119f6576040519150601f19603f3d011682016040523d82523d5f602084013e6119fb565b606091505b50909150505b80611a1f576040516337e391c360e01b815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f5460ff166071805460ff60a01b1916600160a01b60ff938416021790555f5460029161010090910416158015611ac757505f5460ff8083169116105b611b2a5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610b0d565b5f805461ffff191660ff8084169190911761010017909155607154600160a01b90041615611b6b5760405163f57ac68360e01b815260040160405180910390fd5b611b73611f50565b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c80546001600160a01b0319168583161790558616611c285763ffffffff851615611c2357604051630d43a60960e11b815260040160405180910390fd5b611d0e565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e611c778382613872565b50611ced5f5f1b6012604051602001611cd991906060808252600d908201526c2bb930b83832b21022ba3432b960991b608082015260a060208201819052600490820152630ae8aa8960e31b60c082015260ff91909116604082015260e00190565b604051602081830303815290604052612432565b606f80546001600160a01b0319166001600160a01b03929092169190911790555b611d166128da565b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150506071805460ff60a01b191690555050505050565b5f81611d79868686610baf565b1495945050505050565b60685460ff1615611da757604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611e0f576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611e639998979695949392919061392d565b60405180910390a1611ea46001606860019054906101000a900463ffffffff16338989898888604051611e979291906136c8565b604051809103902061286c565b8215611eb257611eb2611eba565b505050505050565b6053546068805463ffffffff909216600160c81b0263ffffffff60c81b1990921691909117908190556001600160a01b0365010000000000909104166333d6247d611f036109d1565b6040518263ffffffff1660e01b8152600401611f2191815260200190565b5f604051808303815f87803b158015611f38575f5ffd5b505af1158015611f4a573d5f5f3e3d5ffd5b50505050565b5f611f827fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103546001600160a01b031690565b9050806001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fc0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fe491906139a3565b607080546001600160a01b0319166001600160a01b03929092169182179055819061202e57604051632a506c0560e11b81526001600160a01b039091166004820152602401610b0d565b50607054604080515f81526001600160a01b0390921660208301527fa9da6fb8c39e9c2fafda878eac316815987bdc948d241ba6d75ed035e0e829f29101610cc1565b604051632770a7eb60e21b8152336004820152602481018290525f906001600160a01b03841690639dc29fac906044015f604051808303815f87803b1580156120b8575f5ffd5b505af11580156120ca573d5f5f3e3d5ffd5b509395945050505050565b60408051600481526024810182526020810180516001600160e01b03166306fdde0360e01b17905290516060915f9182916001600160a01b0386169161211b91906136d7565b5f60405180830381855afa9150503d805f8114612153576040519150601f19603f3d011682016040523d82523d5f602084013e612158565b606091505b50915091508161218757604051806040016040528060078152602001664e4f5f4e414d4560c81b815250612190565b6121908161294c565b949350505050565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b17905290516060915f9182916001600160a01b038616916121de91906136d7565b5f60405180830381855afa9150503d805f8114612216576040519150601f19603f3d011682016040523d82523d5f602084013e61221b565b606091505b50915091508161218757604051806040016040528060098152602001681393d7d4d6535093d360ba1b815250612190565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b17905290515f91829182916001600160a01b0386169161229191906136d7565b5f60405180830381855afa9150503d805f81146122c9576040519150601f19603f3d011682016040523d82523d5f602084013e6122ce565b606091505b50915091508180156122e1575080516020145b6122ec576012612190565b8080602001905181019061219091906139be565b6002600154036123525760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b0d565b6002600155565b6113608c8c8c8c8c6123708d8d8d8d8d8d8d610940565b612ae4565b6040516340c10f1960e01b81526001600160a01b038381166004830152602482018390528416906340c10f19906044015f604051808303815f87803b1580156123bc575f5ffd5b505af1158015610dd2573d5f5f3e3d5ffd5b6040516001600160a01b0383811660248301526044820183905261242d91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612c35565b505050565b5f5f61243c610e20565b60405160200161244c91906136d7565b6040516020818303038152906040529050838151602083015ff591506001600160a01b03821661248f576040516331682e8d60e11b815260040160405180910390fd5b5f5f5f858060200190518101906124a691906139f7565b925092509250846001600160a01b0316631624f6c68484846040518463ffffffff1660e01b81526004016124dc939291906135df565b5f604051808303815f87803b1580156124f3575f5ffd5b505af1158015612505573d5f5f3e3d5ffd5b505050505050505092915050565b60018055565b5f6125276004828486613a6f565b61253091613a96565b9050632afa533160e01b6001600160e01b031982160161269f575f80808080808061255e896004818d613a6f565b81019061256b9190613ace565b9650965096509650965096509650336001600160a01b0316876001600160a01b0316146125ab5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03861630146125d45760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b031663d505accf60e01b1790529151918d169161265291906136d7565b5f604051808303815f865af19150503d805f811461268b576040519150601f19603f3d011682016040523d82523d5f602084013e612690565b606091505b50505050505050505050611f4a565b6001600160e01b031981166323f2ebc360e21b146126d057604051637141605d60e11b815260040160405180910390fd5b5f808080808080806126e58a6004818e613a6f565b8101906126f29190613b1d565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146127345760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038716301461275d5760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918e16916127e491906136d7565b5f604051808303815f865af19150503d805f811461281d576040519150601f19603f3d011682016040523d82523d5f602084013e612822565b606091505b505050505050505050505050505050565b6040516001600160a01b038481166024830152838116604483015260648201839052611f4a9186918216906323b872dd906084016123fb565b610dd261287e88888888888888610940565b612c96565b60685460ff166128a657604051635386698160e01b815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff166129445760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610b0d565b6107d8612d55565b6060604082511061296b578180602001905181019061083e9190613b9b565b8151602003612ab1575f5b6020811080156129a55750828181518110612993576129936135cb565b01602001516001600160f81b03191615155b156129bc57806129b481613bcd565b915050612976565b805f036129f35750506040805180820190915260128152714e4f545f56414c49445f454e434f44494e4760701b6020820152919050565b5f8167ffffffffffffffff811115612a0d57612a0d613412565b6040519080825280601f01601f191660200182016040528015612a37576020820181803683370190505b5090505f5b82811015612aa957848181518110612a5657612a566135cb565b602001015160f81c60f81b828281518110612a7357612a736135cb565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600101612a3c565b509392505050565b50506040805180820190915260128152714e4f545f56414c49445f454e434f44494e4760701b602082015290565b919050565b6068545f906501000000000090046001600160a01b031663257b3632612b1386865f9182526020526040902090565b6040518263ffffffff1660e01b8152600401612b3191815260200190565b6020604051808303815f875af1158015612b4d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b719190613762565b9050805f03612b9257604051622f6fad60e01b815260040160405180910390fd5b5f8068010000000000000000871615612bd657869150612bb4848a8489611d6c565b612bd1576040516338105f3b60e21b815260040160405180910390fd5b612c20565b602087901c612be6816001613be5565b9150879250612c01612bf9868c86610baf565b8a8389611d6c565b612c1e576040516338105f3b60e21b815260040160405180910390fd5b505b612c2a8282612dbf565b505050505050505050565b5f612c496001600160a01b03841683612e66565b905080515f14158015612c6d575080806020019051810190612c6b9190613c01565b155b1561242d57604051635274afe760e01b81526001600160a01b0384166004820152602401610b0d565b806001612ca560206002613cff565b612caf9190613779565b60535410612cd0576040516377ae67b360e11b815260040160405180910390fd5b5f60535f8154612cdf90613bcd565b918290555090505f5b6020811015612d4c578082901c600116600103612d1b578260338260208110612d1357612d136135cb565b015550505050565b612d4260338260208110612d3157612d316135cb565b0154845f9182526020526040902090565b9250600101612ce8565b5061242d613d0a565b5f54610100900460ff166125135760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610b0d565b6068545f90610100900463ffffffff16158015612de2575063ffffffff82166001145b15612df4575063ffffffff8216612e1c565b612e0964010000000063ffffffff841661369e565b612e199063ffffffff85166136b5565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003610dd257604051630c8d9eab60e31b815260040160405180910390fd5b6060610c3783835f845f5f856001600160a01b03168486604051612e8a91906136d7565b5f6040518083038185875af1925050503d805f8114612ec4576040519150601f19603f3d011682016040523d82523d5f602084013e612ec9565b606091505b5091509150612ed9868383612ee3565b9695505050505050565b606082612ef857612ef382612f3f565b610c37565b8151158015612f0f57506001600160a01b0384163b155b15612f3857604051639996b31560e01b81526001600160a01b0385166004820152602401610b0d565b5080610c37565b805115612f4f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b803563ffffffff81168114612adf575f5ffd5b6001600160a01b0381168114612f68575f5ffd5b5f5f60408385031215612fa3575f5ffd5b612fac83612f6b565b91506020830135612fbc81612f7e565b809150509250929050565b8015158114612f68575f5ffd5b5f5f83601f840112612fe4575f5ffd5b50813567ffffffffffffffff811115612ffb575f5ffd5b602083019150836020828501011115613012575f5ffd5b9250929050565b5f5f5f5f5f6080868803121561302d575f5ffd5b61303686612f6b565b9450602086013561304681612f7e565b9350604086013561305681612fc7565b9250606086013567ffffffffffffffff811115613071575f5ffd5b61307d88828901612fd4565b969995985093965092949392505050565b5f5b838110156130a8578181015183820152602001613090565b50505f910152565b5f81518084526130c781602086016020860161308e565b601f01601f19169290920160200192915050565b602081525f610c3760208301846130b0565b5f602082840312156130fd575f5ffd5b8135610c3781612f7e565b60ff81168114612f68575f5ffd5b5f5f5f5f5f5f5f60e0888a03121561312c575f5ffd5b873561313781613108565b965061314560208901612f6b565b9550604088013561315581612f7e565b945061316360608901612f6b565b9350608088013561317381612f7e565b9699959850939692959460a0840135945060c09093013592915050565b5f602082840312156131a0575f5ffd5b5035919050565b80610400810183101561083e575f5ffd5b5f5f5f61044084860312156131cb575f5ffd5b833592506131dc85602086016131a7565b91506131eb6104208501612f6b565b90509250925092565b5f5f5f5f5f5f60a08789031215613209575f5ffd5b61321287612f6b565b9550602087013561322281612f7e565b945060408701359350606087013561323981612fc7565b9250608087013567ffffffffffffffff811115613254575f5ffd5b61326089828a01612fd4565b979a9699509497509295939492505050565b5f5f60408385031215613283575f5ffd5b61328c83612f6b565b915061329a60208401612f6b565b90509250929050565b5f5f5f5f5f5f5f5f5f5f5f5f6109208d8f0312156132bf575f5ffd5b6132c98e8e6131a7565b9b506132d98e6104008f016131a7565b9a506108008d013599506108208d013598506108408d013597506133006108608e01612f6b565b96506133106108808e0135612f7e565b6108808d013595506133256108a08e01612f6b565b94506108c08d013561333681612f7e565b93506108e08d0135925067ffffffffffffffff6109008e01351115613359575f5ffd5b61336a8e6109008f01358f01612fd4565b81935080925050509295989b509295989b509295989b565b5f5f5f5f5f5f5f60c0888a031215613398575f5ffd5b6133a188612f6b565b965060208801356133b181612f7e565b95506040880135945060608801356133c881612f7e565b935060808801356133d881612fc7565b925060a088013567ffffffffffffffff8111156133f3575f5ffd5b6133ff8a828b01612fd4565b989b979a50959850939692959293505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561344f5761344f613412565b604052919050565b5f67ffffffffffffffff82111561347057613470613412565b50601f01601f191660200190565b5f5f5f5f5f5f60c08789031215613493575f5ffd5b61349c87612f6b565b955060208701356134ac81612f7e565b94506134ba60408801612f6b565b935060608701356134ca81612f7e565b925060808701356134da81612f7e565b915060a087013567ffffffffffffffff8111156134f5575f5ffd5b8701601f81018913613505575f5ffd5b803561351861351382613457565b613426565b8181528a602083850101111561352c575f5ffd5b816020840160208301375f602083830101528093505050509295509295509295565b5f5f5f5f6104608587031215613562575f5ffd5b8435935061357386602087016131a7565b92506135826104208601612f6b565b939692955092936104400135925050565b600181811c908216806135a757607f821691505b6020821081036135c557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b606081525f6135f160608301866130b0565b828103602084015261360381866130b0565b91505060ff83166040830152949350505050565b5f61362461351384613457565b9050828152838383011115613637575f5ffd5b610c3783602083018461308e565b5f60208284031215613655575f5ffd5b815167ffffffffffffffff81111561366b575f5ffd5b8201601f8101841361367b575f5ffd5b61219084825160208401613617565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761083e5761083e61368a565b8082018082111561083e5761083e61368a565b818382375f9101908152919050565b5f82516136e881846020870161308e565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681526001600160a01b03851660208201526001600160a01b0384166040820152608060608201525f6137576080830184866136f2565b979650505050505050565b5f60208284031215613772575f5ffd5b5051919050565b8181038181111561083e5761083e61368a565b60ff8916815263ffffffff881660208201526001600160a01b038716604082015263ffffffff861660608201526001600160a01b03851660808201528360a082015261010060c08201525f6137e56101008301856130b0565b905063ffffffff831660e08301529998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f612ed96060830184866136f2565b601f82111561242d57805f5260205f20601f840160051c810160208510156138535750805b601f840160051c820191505b818110156108ad575f815560010161385f565b815167ffffffffffffffff81111561388c5761388c613412565b6138a08161389a8454613593565b8461382e565b6020601f8211600181146138d2575f83156138bb5750848201515b5f19600385901b1c1916600184901b1784556108ad565b5f84815260208120601f198516915b8281101561390157878501518255602094850194600190920191016138e1565b508482101561391e57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b60ff8a16815263ffffffff891660208201526001600160a01b038816604082015263ffffffff871660608201526001600160a01b03861660808201528460a082015261010060c08201525f613987610100830185876136f2565b905063ffffffff831660e08301529a9950505050505050505050565b5f602082840312156139b3575f5ffd5b8151610c3781612f7e565b5f602082840312156139ce575f5ffd5b8151610c3781613108565b5f82601f8301126139e8575f5ffd5b610c3783835160208501613617565b5f5f5f60608486031215613a09575f5ffd5b835167ffffffffffffffff811115613a1f575f5ffd5b613a2b868287016139d9565b935050602084015167ffffffffffffffff811115613a47575f5ffd5b613a53868287016139d9565b9250506040840151613a6481613108565b809150509250925092565b5f5f85851115613a7d575f5ffd5b83861115613a89575f5ffd5b5050820193919092039150565b80356001600160e01b03198116906004841015613ac7576001600160e01b0319600485900360031b81901b82161691505b5092915050565b5f5f5f5f5f5f5f60e0888a031215613ae4575f5ffd5b8735613aef81612f7e565b96506020880135613aff81612f7e565b95506040880135945060608801359350608088013561317381613108565b5f5f5f5f5f5f5f5f610100898b031215613b35575f5ffd5b8835613b4081612f7e565b97506020890135613b5081612f7e565b965060408901359550606089013594506080890135613b6e81612fc7565b935060a0890135613b7e81613108565b979a969950949793969295929450505060c08201359160e0013590565b5f60208284031215613bab575f5ffd5b815167ffffffffffffffff811115613bc1575f5ffd5b612190848285016139d9565b5f60018201613bde57613bde61368a565b5060010190565b63ffffffff818116838216019081111561083e5761083e61368a565b5f60208284031215613c11575f5ffd5b8151610c3781612fc7565b6001815b6001841115613c5757808504811115613c3b57613c3b61368a565b6001841615613c4957908102905b60019390931c928002613c20565b935093915050565b5f82613c6d5750600161083e565b81613c7957505f61083e565b8160018114613c8f5760028114613c9957613cb5565b600191505061083e565b60ff841115613caa57613caa61368a565b50506001821b61083e565b5060208310610133831016604e8410600b8410161715613cd8575081810a61083e565b613ce45f198484613c1c565b805f1904821115613cf757613cf761368a565b029392505050565b5f610c378383613c5f565b634e487b7160e01b5f52600160045260245ffdfea2646970667358221220063c266597e2ffb56d9201c033295ea34c1635e74b868a78fefd4480fab2183364736f6c634300081c0033", + "storage": null + }, + "0xb2fAc1CE54bb9BF77A7FE106fA69F81453b72851": { + "contractName": "PolygonZkEVMBridgeV2 proxy", + "balance": "340282366920938463463374607431768211455", + "nonce": "1", + "code": "0x60806040526004361061005d575f3560e01c80635c60da1b116100425780635c60da1b146100a65780638f283970146100e3578063f851a440146101025761006c565b80633659cfe6146100745780634f1ef286146100935761006c565b3661006c5761006a610116565b005b61006a610116565b34801561007f575f5ffd5b5061006a61008e366004610854565b610130565b61006a6100a136600461086d565b610178565b3480156100b1575f5ffd5b506100ba6101eb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ee575f5ffd5b5061006a6100fd366004610854565b610228565b34801561010d575f5ffd5b506100ba610255565b61011e610282565b61012e610129610359565b610362565b565b610138610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d8160405180602001604052805f8152505f6103bf565b50565b61016d610116565b610180610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101e3576101de8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250600192506103bf915050565b505050565b6101de610116565b5f6101f4610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610359565b905090565b610225610116565b90565b610230610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d816103e9565b5f61025e610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610380565b61028a610380565b73ffffffffffffffffffffffffffffffffffffffff16330361012e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b5f61021861044a565b365f5f375f5f365f845af43d5f5f3e80801561037c573d5ff35b3d5ffd5b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6103c883610471565b5f825111806103d45750805b156101de576103e383836104bd565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610412610380565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161016d816104e9565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103a3565b61047a816105f5565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606104e28383604051806060016040528060278152602001610979602791396106c0565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661058c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610350565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b73ffffffffffffffffffffffffffffffffffffffff81163b610699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610350565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105af565b60605f5f8573ffffffffffffffffffffffffffffffffffffffff16856040516106e9919061090d565b5f60405180830381855af49150503d805f8114610721576040519150601f19603f3d011682016040523d82523d5f602084013e610726565b606091505b509150915061073786838387610741565b9695505050505050565b606083156107d65782515f036107cf5773ffffffffffffffffffffffffffffffffffffffff85163b6107cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610350565b50816107e0565b6107e083836107e8565b949350505050565b8151156107f85781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103509190610928565b803573ffffffffffffffffffffffffffffffffffffffff8116811461084f575f5ffd5b919050565b5f60208284031215610864575f5ffd5b6104e28261082c565b5f5f5f6040848603121561087f575f5ffd5b6108888461082c565b9250602084013567ffffffffffffffff8111156108a3575f5ffd5b8401601f810186136108b3575f5ffd5b803567ffffffffffffffff8111156108c9575f5ffd5b8660208284010111156108da575f5ffd5b939660209190910195509293505050565b5f5b838110156109055781810151838201526020016108ed565b50505f910152565b5f825161091e8184602087016108eb565b9190910192915050565b602081525f82518060208401526109468160408501602087016108eb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220e5f7d1b8c5bf56b8d0f8312db5fe19231c55d442867ab851e163d2e86985168464736f6c634300081c0033", + "storage": { + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000012060ca70f50a24fde90fea110002c235f558a56", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000c2c5fb710e85bedc5c18a8a0fa931d75983f2185" + } + }, + "0x21BD2401BA404841c7feC1816F5a0AaAdbc486eF": { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "code": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c806301fd90441461004e578063257b36321461006a57806333d6247d14610089578063a3c573eb1461009e575b5f5ffd5b61005760015481565b6040519081526020015b60405180910390f35b61005761007836600461015e565b5f6020819052908152604090205481565b61009c61009736600461015e565b6100ea565b005b6100c57f000000000000000000000000b2fac1ce54bb9bf77a7fe106fa69f81453b7285181565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610061565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b2fac1ce54bb9bf77a7fe106fa69f81453b728511614610159576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b5f6020828403121561016e575f5ffd5b503591905056fea2646970667358221220f0c42c4ea26e8c61a4cac40e1273224f46c3c1fd3c84d399b407eb29edfebdc864736f6c634300081c0033", + "storage": null + }, + "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa": { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "code": "0x60806040523661001357610011610017565b005b6100115b61001f6101b7565b6001600160a01b0316336001600160a01b0316141561016f5760606001600160e01b031960003516631b2ce7f360e11b8114156100655761005e6101ea565b9150610167565b6001600160e01b0319811663278f794360e11b14156100865761005e610241565b6001600160e01b031981166308f2839760e41b14156100a75761005e610287565b6001600160e01b031981166303e1469160e61b14156100c85761005e6102b8565b6001600160e01b03198116635c60da1b60e01b14156100e95761005e6102f8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b61017761030c565b565b606061019e83836040518060600160405280602781526020016108576027913961031c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101f4610394565b600061020336600481846106a2565b81019061021091906106e8565b905061022d8160405180602001604052806000815250600061039f565b505060408051602081019091526000815290565b606060008061025336600481846106a2565b8101906102609190610719565b915091506102708282600161039f565b604051806020016040528060008152509250505090565b6060610291610394565b60006102a036600481846106a2565b8101906102ad91906106e8565b905061022d816103cb565b60606102c2610394565b60006102cc6101b7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b6060610302610394565b60006102cc610422565b610177610317610422565b610431565b6060600080856001600160a01b0316856040516103399190610807565b600060405180830381855af49150503d8060008114610374576040519150601f19603f3d011682016040523d82523d6000602084013e610379565b606091505b509150915061038a86838387610455565b9695505050505050565b341561017757600080fd5b6103a8836104d3565b6000825111806103b55750805b156103c6576103c48383610179565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103f46101b7565b604080516001600160a01b03928316815291841660208301520160405180910390a161041f81610513565b50565b600061042c6105bc565b905090565b3660008037600080366000845af43d6000803e808015610450573d6000f35b3d6000fd5b606083156104c15782516104ba576001600160a01b0385163b6104ba5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161015e565b50816104cb565b6104cb83836105e4565b949350505050565b6104dc8161060e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105785760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161015e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101db565b8151156105f45781518083602001fd5b8060405162461bcd60e51b815260040161015e9190610823565b6001600160a01b0381163b61067b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161015e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61059b565b600080858511156106b257600080fd5b838611156106bf57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106e357600080fd5b919050565b6000602082840312156106fa57600080fd5b61019e826106cc565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561072c57600080fd5b610735836106cc565b9150602083013567ffffffffffffffff8082111561075257600080fd5b818501915085601f83011261076657600080fd5b81358181111561077857610778610703565b604051601f8201601f19908116603f011681019083821181831017156107a0576107a0610703565b816040528281528860208487010111156107b957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107f65781810151838201526020016107de565b838111156103c45750506000910152565b600082516108198184602087016107db565b9190910192915050565b60208152600082518060208401526108428160408501602087016107db565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122012bb4f564f73959a03513dc74fc3c6e40e8386e6f02c16b78d6db00ce0aa16af64736f6c63430008090033", + "storage": { + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000021bd2401ba404841c7fec1816f5a0aaadbc486ef", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000c2c5fb710e85bedc5c18a8a0fa931d75983f2185" + } + }, + "0x27284DBa79e6DF953Fbd232A9d8D87029F03BBf5": { + "contractName": "PolygonZkEVMTimelock", + "balance": "0", + "nonce": "1", + "code": "0x6080604052600436106101bd575f3560e01c806364d62353116100f2578063b1c5f42711610092578063d547741f11610062578063d547741f1461063a578063e38335e514610659578063f23a6e611461066c578063f27a0c92146106b0575f80fd5b8063b1c5f4271461058d578063bc197c81146105ac578063c4d252f5146105f0578063d45c44351461060f575f80fd5b80638f61f4f5116100cd5780638f61f4f5146104c557806391d14854146104f8578063a217fddf14610547578063b08e51c01461055a575f80fd5b806364d62353146104685780638065657f146104875780638f2a0bb0146104a6575f80fd5b8063248a9ca31161015d57806331d507501161013857806331d50750146103b357806336568abe146103d25780633a6aae72146103f1578063584b153e14610449575f80fd5b8063248a9ca3146103375780632ab0f529146103655780632f2ff15d14610394575f80fd5b80630d3cf6fc116101985780630d3cf6fc1461025e578063134008d31461029157806313bc9f20146102a4578063150b7a02146102c3575f80fd5b806301d5062a146101c857806301ffc9a7146101e957806307bd02651461021d575f80fd5b366101c457005b5f80fd5b3480156101d3575f80fd5b506101e76101e2366004611bf6565b6106c4565b005b3480156101f4575f80fd5b50610208610203366004611c65565b610757565b60405190151581526020015b60405180910390f35b348015610228575f80fd5b506102507fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610214565b348015610269575f80fd5b506102507f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101e761029f366004611ca4565b6107b2565b3480156102af575f80fd5b506102086102be366004611d0b565b6108a7565b3480156102ce575f80fd5b506103066102dd366004611e28565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610214565b348015610342575f80fd5b50610250610351366004611d0b565b5f9081526020819052604090206001015490565b348015610370575f80fd5b5061020861037f366004611d0b565b5f908152600160208190526040909120541490565b34801561039f575f80fd5b506101e76103ae366004611e8c565b6108cc565b3480156103be575f80fd5b506102086103cd366004611d0b565b6108f5565b3480156103dd575f80fd5b506101e76103ec366004611e8c565b61090d565b3480156103fc575f80fd5b506104247f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b348015610454575f80fd5b50610208610463366004611d0b565b6109c5565b348015610473575f80fd5b506101e7610482366004611d0b565b6109da565b348015610492575f80fd5b506102506104a1366004611ca4565b610aaa565b3480156104b1575f80fd5b506101e76104c0366004611ef7565b610ae8565b3480156104d0575f80fd5b506102507fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610503575f80fd5b50610208610512366004611e8c565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b348015610552575f80fd5b506102505f81565b348015610565575f80fd5b506102507ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b348015610598575f80fd5b506102506105a7366004611fa0565b610d18565b3480156105b7575f80fd5b506103066105c63660046120be565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b3480156105fb575f80fd5b506101e761060a366004611d0b565b610d5c565b34801561061a575f80fd5b50610250610629366004611d0b565b5f9081526001602052604090205490565b348015610645575f80fd5b506101e7610654366004611e8c565b610e56565b6101e7610667366004611fa0565b610e7a565b348015610677575f80fd5b50610306610686366004612161565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106bb575f80fd5b50610250611121565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16106ee81611200565b5f6106fd898989898989610aaa565b9050610709818461120d565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161074496959493929190612208565b60405180910390a3505050505050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107ac57506107ac82611359565b92915050565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661082e5761082e81336113ef565b5f61083d888888888888610aaa565b905061084981856114a6565b610855888888886115e2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a60405161088c9493929190612252565b60405180910390a361089d816116e2565b5050505050505050565b5f818152600160205260408120546001811180156108c55750428111155b9392505050565b5f828152602081905260409020600101546108e681611200565b6108f0838361178a565b505050565b5f8181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109c18282611878565b5050565b5f818152600160208190526040822054610906565b333014610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109ae565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b5f868686868686604051602001610ac696959493929190612208565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b1281611200565b888714610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b888514610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f610c418b8b8b8b8b8b8b8b610d18565b9050610c4d818461120d565b5f5b8a811015610d0a5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c8c57610c8c612291565b9050602002016020810190610ca191906122be565b8d8d86818110610cb357610cb3612291565b905060200201358c8c87818110610ccc57610ccc612291565b9050602002810190610cde91906122d7565b8c8b604051610cf296959493929190612208565b60405180910390a3610d0381612365565b9050610c4f565b505050505050505050505050565b5f8888888888888888604051602001610d38989796959493929190612447565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610d8681611200565b610d8f826109c5565b610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109ae565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610e7081611200565b6108f08383611878565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610ef657610ef681336113ef565b878614610f85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b878414611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f6110258a8a8a8a8a8a8a8a610d18565b905061103181856114a6565b5f5b8981101561110b575f8b8b8381811061104e5761104e612291565b905060200201602081019061106391906122be565b90505f8a8a8481811061107857611078612291565b905060200201359050365f8a8a8681811061109557611095612291565b90506020028101906110a791906122d7565b915091506110b7848484846115e2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516110ee9493929190612252565b60405180910390a3505050508061110490612365565b9050611033565b50611115816116e2565b50505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16158015906111ef57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ef919061250c565b156111f957505f90565b5060025490565b61120a81336113ef565b50565b611216826108f5565b156112a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109ae565b6112ab611121565b81101561133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109ae565b611344814261252b565b5f928352600160205260409092209190915550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ac57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ac565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c15761142c8161192d565b61143783602061194c565b604051602001611448929190612560565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109ae916004016125e0565b6114af826108a7565b61153b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b80158061155657505f81815260016020819052604090912054145b6109c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f8473ffffffffffffffffffffffffffffffffffffffff1684848460405161160b929190612630565b5f6040518083038185875af1925050503d805f8114611645576040519150601f19603f3d011682016040523d82523d5f602084013e61164a565b606091505b50509050806116db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109ae565b5050505050565b6116eb816108a7565b611777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b5f90815260016020819052604090912055565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561181a3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107ac73ffffffffffffffffffffffffffffffffffffffff831660145b60605f61195a83600261263f565b61196590600261252b565b67ffffffffffffffff81111561197d5761197d611d22565b6040519080825280601f01601f1916602001820160405280156119a7576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106119dd576119dd612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a3f57611a3f612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f611a7984600261263f565b611a8490600161252b565b90505b6001811115611b20577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611ac557611ac5612291565b1a60f81b828281518110611adb57611adb612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060049490941c93611b1981612656565b9050611a87565b5083156108c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109ae565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bac575f80fd5b919050565b5f8083601f840112611bc1575f80fd5b50813567ffffffffffffffff811115611bd8575f80fd5b602083019150836020828501011115611bef575f80fd5b9250929050565b5f805f805f805f60c0888a031215611c0c575f80fd5b611c1588611b89565b965060208801359550604088013567ffffffffffffffff811115611c37575f80fd5b611c438a828b01611bb1565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f60208284031215611c75575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108c5575f80fd5b5f805f805f8060a08789031215611cb9575f80fd5b611cc287611b89565b955060208701359450604087013567ffffffffffffffff811115611ce4575f80fd5b611cf089828a01611bb1565b979a9699509760608101359660809091013595509350505050565b5f60208284031215611d1b575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d9657611d96611d22565b604052919050565b5f82601f830112611dad575f80fd5b813567ffffffffffffffff811115611dc757611dc7611d22565b611df860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d4f565b818152846020838601011115611e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611e3b575f80fd5b611e4485611b89565b9350611e5260208601611b89565b925060408501359150606085013567ffffffffffffffff811115611e74575f80fd5b611e8087828801611d9e565b91505092959194509250565b5f8060408385031215611e9d575f80fd5b82359150611ead60208401611b89565b90509250929050565b5f8083601f840112611ec6575f80fd5b50813567ffffffffffffffff811115611edd575f80fd5b6020830191508360208260051b8501011115611bef575f80fd5b5f805f805f805f805f60c08a8c031215611f0f575f80fd5b893567ffffffffffffffff80821115611f26575f80fd5b611f328d838e01611eb6565b909b50995060208c0135915080821115611f4a575f80fd5b611f568d838e01611eb6565b909950975060408c0135915080821115611f6e575f80fd5b50611f7b8c828d01611eb6565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f805f805f805f8060a0898b031215611fb7575f80fd5b883567ffffffffffffffff80821115611fce575f80fd5b611fda8c838d01611eb6565b909a50985060208b0135915080821115611ff2575f80fd5b611ffe8c838d01611eb6565b909850965060408b0135915080821115612016575f80fd5b506120238b828c01611eb6565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112612050575f80fd5b8135602067ffffffffffffffff82111561206c5761206c611d22565b8160051b61207b828201611d4f565b9283528481018201928281019087851115612094575f80fd5b83870192505b848310156120b35782358252918301919083019061209a565b979650505050505050565b5f805f805f60a086880312156120d2575f80fd5b6120db86611b89565b94506120e960208701611b89565b9350604086013567ffffffffffffffff80821115612105575f80fd5b61211189838a01612041565b94506060880135915080821115612126575f80fd5b61213289838a01612041565b93506080880135915080821115612147575f80fd5b5061215488828901611d9e565b9150509295509295909350565b5f805f805f60a08688031215612175575f80fd5b61217e86611b89565b945061218c60208701611b89565b93506040860135925060608601359150608086013567ffffffffffffffff8111156121b5575f80fd5b61215488828901611d9e565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201525f61223d60a0830186886121c1565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201525f6122876060830184866121c1565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156122ce575f80fd5b6108c582611b89565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261230a575f80fd5b83018035915067ffffffffffffffff821115612324575f80fd5b602001915036819003821315611bef575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239557612395612338565b5060010190565b8183525f6020808501808196508560051b81019150845f5b8781101561243a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126123f2575f80fd5b8701858101903567ffffffffffffffff81111561240d575f80fd5b80360382131561241b575f80fd5b6124268682846121c1565b9a87019a95505050908401906001016123b4565b5091979650505050505050565b60a080825281018890525f8960c08301825b8b8110156124945773ffffffffffffffffffffffffffffffffffffffff61247f84611b89565b16825260209283019290910190600101612459565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8911156124cc575f80fd5b8860051b9150818a602083013701828103602090810160408501526124f4908201878961239c565b60608401959095525050608001529695505050505050565b5f6020828403121561251c575f80fd5b815180151581146108c5575f80fd5b808201808211156107ac576107ac612338565b5f5b83811015612558578181015183820152602001612540565b50505f910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161259781601785016020880161253e565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125d481602884016020880161253e565b01602801949350505050565b602081525f82518060208401526125fe81604085016020870161253e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b818382375f9101908152919050565b80820281158282048414176107ac576107ac612338565b5f8161266457612664612338565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220ffae92f944289ff2d8d50b1f6dc43374b9a4ff2979d908883d35eec5819b612c64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", + "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x35fa115b92f0a8d03c972ada19f34c3fa238589ba573a59a419692abc6a91f1a": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x3e92e57d702d5fdc47a588386c93df7f5578fb6af324e63318e76ec6cffcab32": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x6b347b5397bd05b592ec00f3e3a28ac3cedc5d7ee6994c7533215f223a0cfe84": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x73aec4d9eb3be1097d809826691104f0c28da74ebf68d903dc9c6f12562fd822": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc05edde0499e76380516353a6ad6ced0d360179c67da013977526f6fbac38774": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + } + }, + "0x6Ea4D2dd7dFEb6945d1B57a42DC68FE7E06126ce": { + "contractName": null, + "balance": "0", + "nonce": "1", + "code": null, + "storage": null + }, + "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534": { + "contractName": null, + "balance": "100000000000000000000000", + "nonce": "8", + "code": null, + "storage": null + } +} \ No newline at end of file diff --git a/test-pp-op/config/dynamic-mynetwork-chainspec.json b/test-pp-op/config/dynamic-mynetwork-chainspec.json new file mode 100644 index 0000000000000..62d49e44e1b6b --- /dev/null +++ b/test-pp-op/config/dynamic-mynetwork-chainspec.json @@ -0,0 +1,25 @@ +{ + "ChainName": "dynamic-mynetwork", + "chainId": 195, + "consensus": "ethash", + "homesteadBlock": 0, + "daoForkBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 9999999999999999999999999999999999999999999999999, + "arrowGlacierBlock": 9999999999999999999999999999999999999999999999999, + "grayGlacierBlock": 9999999999999999999999999999999999999999999999999, + "terminalTotalDifficulty": 58750000000000000000000, + "terminalTotalDifficultyPassed": false, + "shanghaiTime": 9999999999999999999999999999999999999999999999999, + "cancunTime": 9999999999999999999999999999999999999999999999999, + "pragueTime": 9999999999999999999999999999999999999999999999999, + "ethash": {} +} + diff --git a/test-pp-op/config/dynamic-mynetwork-conf.json b/test-pp-op/config/dynamic-mynetwork-conf.json new file mode 100644 index 0000000000000..9ce28d4252cc1 --- /dev/null +++ b/test-pp-op/config/dynamic-mynetwork-conf.json @@ -0,0 +1,6 @@ +{ + "root": "0x6565265b546acdc3b714218d5bdb667725002a6fa07b5045f5ed4ad7595ebd62", + "timestamp": 1760602860, + "gasLimit": 0, + "difficulty": 0 +} diff --git a/test-pp-op/config/first-batch-config.json b/test-pp-op/config/first-batch-config.json new file mode 100644 index 0000000000000..f622df8200c75 --- /dev/null +++ b/test-pp-op/config/first-batch-config.json @@ -0,0 +1,9 @@ +{ + "batchL2Data": "0xf901e480808401c9c38094b2fac1ce54bb9bf77a7fe106fa69f81453b7285180b901c4f811bff700000000000000000000000000000000000000000000000000000000000000010000000000000000000000005fbdb2315678afecb367f032d93f642f64180aa30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a40d5f56745a118d0906a34e69aec8c0db1cb8fa000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000084f4b42546f6b656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034f4b42000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ca1ab1e0000000000000000000000000000000000000000000000000000000005ca1ab1e1bff", + "globalExitRoot": "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "timestamp": 1760602860, + "sequencer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "l1BlockNumber": 100, + "l1BlockHash": "0xfbd5bff822e23e6864b1185686864ac8bc9a7645756dce00586ed909b9f3c78e", + "l1ParentHash": "0xd3bf883426e5f8f374ed2699fc9c9026d136e212c57f4fc48288f8c2d189fadd" +} diff --git a/test-pp-op/config/local/local.erigon.rpc.config.yaml b/test-pp-op/config/local/local.erigon.rpc.config.yaml new file mode 100644 index 0000000000000..9368b7782aa84 --- /dev/null +++ b/test-pp-op/config/local/local.erigon.rpc.config.yaml @@ -0,0 +1,114 @@ +datadir: /home/erigon/data/ +chain: dynamic-mynetwork +http: true +private.api.addr: localhost:9091 +zkevm.l2-chain-id: 195 +zkevm.l2-sequencer-rpc-url: xlayer-seq:8545 +zkevm.l2-datastreamer-url: xlayer-seq:6900 +zkevm.l1-chain-id: 1337 +zkevm.l1-rpc-url: http://xlayer-mock-l1-network:8545 +zkevm.l1-highest-block-type: latest + +zkevm.address-sequencer: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +zkevm.address-zkevm: "0xE45CCD0757670580a4a3600DE5cef1e45F0Ec2bd" +zkevm.address-admin: "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534" +zkevm.address-rollup: "0xE96dBF374555C6993618906629988d39184716B3" +zkevm.address-ger-manager: "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" + +zkevm.l1-rollup-id: 1 +zkevm.l1-first-block: 75 +zkevm.l1-block-range: 10 +zkevm.l1-query-delay: 6000 +zkevm.rpc-ratelimit: 0 +zkevm.datastream-version: 2 + +log.console.verbosity: info + +#zkevm.executor-urls: xlayer-executor:50071 +# zkevm.executor-strict: false +# zkevm.witness-full: false +# zkevm.executor-mock: true + +zkevm.sequencer-block-seal-time: "1s" +zkevm.sequencer-max-block-seal-time: "3s" +zkevm.sequencer-batch-seal-time: "10s" +zkevm.sequencer-batch-sleep-duration: "0s" + +#zkevm.data-stream-host: "localhost" +#zkevm.data-stream-port: 6900 +zkevm.default-gas-price: 1000000000 +zkevm.max-gas-price: 0 +zkevm.gas-price-factor: 0.000001 +zkevm.allow-free-transactions: true + +externalcl: true +http.api: [eth, debug, net, trace, web3, erigon, txpool, zkevm] +http.addr: 0.0.0.0 +http.port: 8545 +http.vhosts: any +http.corsdomain: any +http.timeouts.read: "10s" +http.timeouts.write: "10s" +http.timeouts.idle: "10s" +rpc.batch.concurrency: 2 +rpc.batch.limit: 20 +ws: true + +zkevm.apollo-enabled: false +zkevm.apollo-ip-addr: "" +zkevm.apollo-app-id: "" +zkevm.apollo-namespace-name: "" + +zkevm.nacos-urls: "" +zkevm.nacos-namespace-id: "" +zkevm.nacos-application-name: "" +zkevm.nacos-external-listen-addr: "" + +metrics: true +metrics.addr: "0.0.0.0" +metrics.port: 9095 + +db.read.concurrency: 20000 +txpool.globalslots: 1000000 +txpool.globalbasefeeslots: 1000000 +txpool.globalqueue: 1000000 +txpool.packbatchspeciallist : ["0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534"] +txpool.gaspricemultiple : 2 +txpool.blockedlist: ["0xdD2FD4581271e230360230F9337D5c0430Bf44C0"] +txpool.enablefreegasbynonce : true +txpool.freegascountperaddr : 100 +txpool.commit.every: "10m" + +gpo.type: "follower" +gpo.update-period: "3s" +gpo.factor: 0.01 +gpo.kafka-url: "0.0.0.0" +gpo.topic: "explorer" +gpo.group-id: "web3" +gpo.blocks: 3 +gpo.default-l1-coin-price: 2000 +gpo.default-l2-coin-price: 50 +gpo.gas-price-usdt: 0.000000476190476 +gpo.congestion-threshold: 0 + +networkid: 195 + +pprof: true +pprof.port: 6060 +pprof.addr: 0.0.0.0 +txpool.enablefreegaslist : true +txpool.freegaslist : '[{"name":"e2e", "from_list":["0x586cbc95ed16031d9efdaebacf1c1d2bc3ccaa78"], "to_list":["0xad1d01007a56ee0a4ffd0488fb58fc6500cb1fbe"], "method_sigs":["a9059cbb"], "gas_price_multiple": 1}]' + +# close a block/batch immediately after the 1st zkCounter overflow TX +zkevm.seal-batch-immediately-on-overflow: true +zkevm.sequencer-timeout-on-empty-tx-pool: 5ms +zkevm.pre-run-address-list: [""] +zkevm.block-info-concurrent: true +zkevm.standalone-smt-db: true # true: enable split smt db, false: not split +zkevm.enable-async-commit: true + +# to reduce lock race in stress test +txpool.enabletimsort: true +zkevm.bulk-add-txs: true +zkevm.enable-add-tx-notify: true +zkevm.initial-batch.config: /usr/src/app/first-batch-config.json \ No newline at end of file diff --git a/test-pp-op/config/local/local.erigon.seq.config.yaml b/test-pp-op/config/local/local.erigon.seq.config.yaml new file mode 100644 index 0000000000000..05534cd103af4 --- /dev/null +++ b/test-pp-op/config/local/local.erigon.seq.config.yaml @@ -0,0 +1,109 @@ +datadir: /home/erigon/data/ +chain: dynamic-mynetwork +http: true +private.api.addr: localhost:9091 +zkevm.l2-chain-id: 195 +zkevm.l2-sequencer-rpc-url: +zkevm.l2-datastreamer-url: +zkevm.l1-chain-id: 1337 +zkevm.l1-rpc-url: http://xlayer-mock-l1-network:8545 +zkevm.l1-highest-block-type: latest + +zkevm.address-sequencer: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +zkevm.address-zkevm: "0xE45CCD0757670580a4a3600DE5cef1e45F0Ec2bd" +zkevm.address-admin: "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534" +zkevm.address-rollup: "0xE96dBF374555C6993618906629988d39184716B3" +zkevm.address-ger-manager: "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" + +zkevm.l1-rollup-id: 1 +zkevm.l1-first-block: 156 +zkevm.l1-block-range: 10 +zkevm.l1-query-delay: 6000 +zkevm.rpc-ratelimit: 0 +zkevm.datastream-version: 2 + +log.console.verbosity: info + +zkevm.sequencer-block-seal-time: "1s" +zkevm.sequencer-max-block-seal-time: "3s" +zkevm.sequencer-batch-seal-time: "10s" +zkevm.sequencer-batch-sleep-duration: "0s" + +zkevm.data-stream-host: "localhost" +zkevm.data-stream-port: 6900 +zkevm.default-gas-price: 1000000000 +zkevm.max-gas-price: 0 +zkevm.gas-price-factor: 0.000001 +zkevm.allow-free-transactions: true + +externalcl: true +http.api: [eth, debug, net, trace, web3, erigon, txpool, zkevm] +http.addr: 0.0.0.0 +http.port: 8545 +http.vhosts: any +http.corsdomain: any +http.timeouts.read: "10s" +http.timeouts.write: "10s" +http.timeouts.idle: "10s" +rpc.batch.concurrency: 2 +rpc.batch.limit: 20 +ws: true + +zkevm.apollo-enabled: false +zkevm.apollo-ip-addr: "" +zkevm.apollo-app-id: "" +zkevm.apollo-namespace-name: "" + +zkevm.nacos-urls: "" +zkevm.nacos-namespace-id: "" +zkevm.nacos-application-name: "" +zkevm.nacos-external-listen-addr: "" + +metrics: true +metrics.addr: "0.0.0.0" +metrics.port: 9095 + +db.read.concurrency: 20000 +txpool.globalslots: 1000000 +txpool.globalbasefeeslots: 1000000 +txpool.globalqueue: 1000000 +txpool.packbatchspeciallist : ["0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534"] +txpool.gaspricemultiple : 2 +txpool.blockedlist: ["0xdD2FD4581271e230360230F9337D5c0430Bf44C0"] +txpool.enablefreegasbynonce : true +txpool.freegascountperaddr : 100 +txpool.commit.every: "10m" + +gpo.type: "follower" +gpo.update-period: "3s" +gpo.factor: 0.01 +gpo.kafka-url: "0.0.0.0" +gpo.topic: "explorer" +gpo.group-id: "web3" +gpo.blocks: 3 +gpo.default-l1-coin-price: 2000 +gpo.default-l2-coin-price: 50 +gpo.gas-price-usdt: 0.000000476190476 +gpo.congestion-threshold: 0 + +networkid: 195 + +pprof: true +pprof.port: 6060 +pprof.addr: 0.0.0.0 +txpool.enablefreegaslist : true +txpool.freegaslist : '[{"name":"e2e", "from_list":["0x586cbc95ed16031d9efdaebacf1c1d2bc3ccaa78"], "to_list":["0xad1d01007a56ee0a4ffd0488fb58fc6500cb1fbe"], "method_sigs":["a9059cbb"], "gas_price_multiple": 1}]' + +# close a block/batch immediately after the 1st zkCounter overflow TX +zkevm.seal-batch-immediately-on-overflow: true +zkevm.sequencer-timeout-on-empty-tx-pool: 5ms +zkevm.pre-run-address-list: [""] +zkevm.block-info-concurrent: true +zkevm.standalone-smt-db: true # true: enable split smt db, false: not split +zkevm.enable-async-commit: true + +# to reduce lock race in stress test +txpool.enabletimsort: true +zkevm.bulk-add-txs: true +zkevm.enable-add-tx-notify: true +zkevm.initial-batch.config: /usr/src/app/first-batch-config.json diff --git a/test-pp-op/config/test.bridge.config.toml b/test-pp-op/config/test.bridge.config.toml new file mode 100644 index 0000000000000..87b7fc7e05729 --- /dev/null +++ b/test-pp-op/config/test.bridge.config.toml @@ -0,0 +1,132 @@ +[Log] +# Set the logging level (e.g., debug, info, warn, error) to control verbosity +Level = "debug" +# Specify the environment in which the application is running (e.g., production, development) +Environment = "production" +# Define where to output logs; options include stderr (standard error) or stdout +Outputs = ["stderr"] + +# Database Synchronization Configuration +# This section contains the database connection settings required for +# synchronizing data. +[SyncDB] +# Type of database to use (e.g., postgres) +Database = "postgres" + [SyncDB.PgStorage] + # Username for database authentication + User = "test_user" + # Name of the database to connect to + Name = "test_db" + # Password for the database user + Password = "test_password" + # Host address of the database server + Host = "xlayer-bridge-db" + # Port number on which the database server is listening + Port = "5432" + # Maximum number of concurrent connections to the database + MaxConns = 20 + +# Etherman Configuration +# This section specifies the RPC URLs for interacting with Layer 1 and Layer 2's. +[Etherman] +# URL for Layer 1 RPC endpoint to interact with the main blockchain +L1URL = "http://l1-geth:8545" +# URLs for Layer 2 RPC endpoints +L2URLs = ["http://xlayer-rpc:8545"] + +# Synchronization Settings +# This section defines the parameters for synchronizing data, including +# the interval and chunk size for synchronization operations. +[Synchronizer] +# Time interval for synchronization iterations (e.g., every 5 seconds) +SyncInterval = "1s" +# Number of blocks to read in each synchronization operation if the service is not synced and if there is enough data. +SyncChunkSize = 50 +# Forces the SyncChunkSize for L2 networks. The chunck size won't be higher than the value specified but if there is not enough events in the network, the reorg protection can be affected. +ForceL2SyncChunk = true + +# Bridge Controller Configuration +# This section contains settings for the bridge controller, including merkle tree height parameter. +[BridgeController] +# Height parameter specifies the height of the merkle tree used for the bridge. +Height = 32 + +# Bridge Server Configuration +# This section defines the settings for the bridge server API, including +# ports for gRPC and HTTP communication, pagination limits, and database. +[BridgeServer] +# Port for gRPC communication with the bridge server +GRPCPort = "9090" +# Port for HTTP communication with the bridge server +HTTPPort = "8080" +# Default limit for paginated results returned by the server +DefaultPageLimit = 25 +# Maximum limit for paginated results to prevent excessive data retrieval +MaxPageLimit = 1000 + # Database configuration for the bridge server. Could be the same config as SyncDB but ideally It should be a read replica to distribute the load. + [BridgeServer.DB] + # Type of database for the bridge server + Database = "postgres" + [BridgeServer.DB.PgStorage] + # Database user for authentication + User = "test_user" + # Database name for the bridge server + Name = "test_db" + # Password for the database user + Password = "test_password" + # Host address of the database server + Host = "xlayer-bridge-db" + # Port number for the database connection + Port = "5432" + # Maximum number of connections to the database for the bridge server + MaxConns = 20 + +# Network Configuration +# This section contains settings related to the network, including smart contract addresses and +# L1 bridge genesis block. +[NetworkConfig] +# Block number where the L1 bridge smart contract was deployed. The bridge needs to compute the merkle tree based on events from that block. +GenBlockNumber = 50 +# Address of the Polygon bridge smc +PolygonBridgeAddress = "0xb2fAc1CE54bb9BF77A7FE106fA69F81453b72851" +# Address of the Global exit root smc +PolygonZkEVMGlobalExitRootAddress = "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" +# Address of the rollup manager smc +PolygonRollupManagerAddress = "0xE96dBF374555C6993618906629988d39184716B3" +# Address of the zkEVM smc +PolygonZkEVMAddress = "0xE45CCD0757670580a4a3600DE5cef1e45F0Ec2bd" +# List of Layer 2 Polygon bridge addresses. It must have the same length as L2URLs. e.g. If 5 networks need to be synced, the urls must be in this array. +L2PolygonBridgeAddresses = ["0xb2fAc1CE54bb9BF77A7FE106fA69F81453b72851"] +# Flag indicating whether to require sovereign chain smcs or not. It must have the same length as L2PolygonBridgeAddresses +RequireSovereignChainSmcs = [false] +# List of global exit root addresses for Layer 2. Same length as L2PolygonBridgeAddresses +L2PolygonZkEVMGlobalExitRootAddresses = ["0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa"] + +# Claim Transaction Manager Configuration +# This section contains settings for managing claim transactions. It includes +# enabling or disabling the ClaimTxManager, monitoring frequency, private key +# configuration, and retry settings for sending transactions. +[ClaimTxManager] +# Enable or disable the claim transaction manager +Enabled = true +# Frequency to monitor transactions +FrequencyToMonitorTxs = "5s" +# Path and password for the private key +PrivateKey = {Path = "/pk/keystore.claimtxmanager", Password = "testonly"} +# Interval between retries +RetryInterval = "1s" +# Number of retry attempts +RetryNumber = 10 + +# Metrics Configuration +# This section defines settings for collecting and exposing metrics related +# to the application's performance and health. It includes options to enable +# or disable metrics collection, as well as the host and port for metrics +# exposure. +[Metrics] +# Enable or disable metrics +Enabled = true +# Host address for the metrics +Host = "0.0.0.0" +# Port for the metrics +Port = "8090" diff --git a/test-pp-op/config/test.erigon.rpc.config.yaml b/test-pp-op/config/test.erigon.rpc.config.yaml new file mode 100644 index 0000000000000..ce41932f177d6 --- /dev/null +++ b/test-pp-op/config/test.erigon.rpc.config.yaml @@ -0,0 +1,86 @@ +datadir: /home/erigon/data/ +chain: dynamic-mynetwork +http: true +private.api.addr: localhost:9091 +zkevm.l2-chain-id: 195 +zkevm.l2-sequencer-rpc-url: http://xlayer-seq:8545 +zkevm.l2-datastreamer-url: xlayer-seq:6900 +zkevm.l1-chain-id: 1337 +zkevm.l1-rpc-url: http://l1-geth:8545 +zkevm.l1-highest-block-type: latest + +zkevm.address-sequencer: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +zkevm.address-zkevm: "0xE45CCD0757670580a4a3600DE5cef1e45F0Ec2bd" +zkevm.address-admin: "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534" +zkevm.address-rollup: "0xE96dBF374555C6993618906629988d39184716B3" +zkevm.address-ger-manager: "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" + +zkevm.l1-rollup-id: 1 +zkevm.l1-first-block: 156 +zkevm.l1-block-range: 10 +zkevm.l1-query-delay: 6000 +zkevm.rpc-ratelimit: 300 +zkevm.datastream-version: 2 + +log.console.verbosity: info + +#zkevm.executor-urls: xlayer-executor:50071 +# zkevm.executor-urls: "" +# zkevm.executor-strict: false +# zkevm.witness-full: false + +zkevm.sequencer-block-seal-time: "6s" +zkevm.sequencer-batch-seal-time: "12s" +zkevm.sequencer-batch-sleep-duration: "0s" + +zkevm.data-stream-host: "localhost" +zkevm.data-stream-port: 6900 +zkevm.default-gas-price: 1000000000 +zkevm.max-gas-price: 0 +zkevm.gas-price-factor: 0.000001 +zkevm.allow-free-transactions: true +zkevm.allow-internal-transactions: true +externalcl: true +http.api: [eth, debug, net, trace, web3, erigon, txpool, zkevm] +http.addr: 0.0.0.0 +http.port: 8545 +http.vhosts: any +http.corsdomain: any +http.timeouts.read: "10s" +http.timeouts.write: "10s" +http.timeouts.idle: "10s" +http.methodratelimit: "{\"methods\":[\"eth_syncing\"],\"count\":10,\"bucket\":1}" +# http.apikeys: | +# {"project":"Biconomy","key":"45543e0adc5dd3e316044909d32501a5","timeout":"2030-12-31","methods":["eth_syncing"],"count":10000,"bucket":1} + +ws: true + +zkevm.apollo-enabled: false +zkevm.apollo-ip-addr: "" +zkevm.apollo-app-id: "" +zkevm.apollo-namespace-name: "" + +zkevm.nacos-urls: "" +zkevm.nacos-namespace-id: "" +zkevm.nacos-application-name: "" +zkevm.nacos-external-listen-addr: "" + +metrics: true +metrics.addr: "0.0.0.0" +metrics.port: 9095 + +db.read.concurrency: 20000 +txpool.globalslots: 100000 +networkid: 195 + +zkevm.pool-manager-url: http://xlayer-pool-manager:8545 + +http.methodratelimit: "{\"methods\":[\"eth_syncing\"],\"count\":10,\"bucket\":1}" +#http.apikeys: | +# {"project":"project1","key":"944cd2a6939eb23053289d9b91d6c498","timeout":"2033-12-12","methods":["eth_syncing"],"count":5,"bucket":1} + +pprof: true +pprof.port: 6060 +pprof.addr: 0.0.0.0 + +zkevm.standalone-smt-db: true # true: enalbe split smt db, false: not split \ No newline at end of file diff --git a/test-pp-op/config/test.erigon.seq.config.yaml b/test-pp-op/config/test.erigon.seq.config.yaml new file mode 100644 index 0000000000000..44c8a3a7a6fe1 --- /dev/null +++ b/test-pp-op/config/test.erigon.seq.config.yaml @@ -0,0 +1,114 @@ +datadir: /home/erigon/data/ +chain: dynamic-mynetwork +http: true +private.api.addr: localhost:9091 +zkevm.l2-chain-id: 195 +zkevm.l2-sequencer-rpc-url: +zkevm.l2-datastreamer-url: +zkevm.l1-chain-id: 1337 +zkevm.l1-rpc-url: http://l1-geth:8545 +zkevm.l1-highest-block-type: latest + +zkevm.address-sequencer: "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" +zkevm.address-zkevm: "0xE45CCD0757670580a4a3600DE5cef1e45F0Ec2bd" +zkevm.address-admin: "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534" +zkevm.address-rollup: "0xE96dBF374555C6993618906629988d39184716B3" +zkevm.address-ger-manager: "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" + +zkevm.l1-rollup-id: 1 +zkevm.l1-first-block: 91 +zkevm.l1-block-range: 10 +zkevm.l1-query-delay: 6000 +zkevm.rpc-ratelimit: 0 +zkevm.datastream-version: 2 + +log.console.verbosity: info + +#zkevm.executor-urls: xlayer-executor:50071 +# zkevm.executor-strict: false +# zkevm.witness-full: false +# zkevm.executor-mock: true + +zkevm.sequencer-block-seal-time: "1s" +zkevm.sequencer-max-block-seal-time: "3s" +zkevm.sequencer-batch-seal-time: "10s" +zkevm.sequencer-batch-sleep-duration: "0s" + +zkevm.data-stream-host: "localhost" +zkevm.data-stream-port: 6900 +zkevm.default-gas-price: 1000000000 +zkevm.max-gas-price: 0 +zkevm.gas-price-factor: 0.000001 +zkevm.allow-free-transactions: true + +externalcl: true +http.api: [eth, debug, net, trace, web3, erigon, txpool, zkevm] +http.addr: 0.0.0.0 +http.port: 8545 +http.vhosts: any +http.corsdomain: any +http.timeouts.read: "10s" +http.timeouts.write: "10s" +http.timeouts.idle: "10s" +rpc.batch.concurrency: 2 +rpc.batch.limit: 20 +ws: true + +zkevm.apollo-enabled: false +zkevm.apollo-ip-addr: "" +zkevm.apollo-app-id: "" +zkevm.apollo-namespace-name: "" + +zkevm.nacos-urls: "" +zkevm.nacos-namespace-id: "" +zkevm.nacos-application-name: "" +zkevm.nacos-external-listen-addr: "" + +metrics: true +metrics.addr: "0.0.0.0" +metrics.port: 9095 + +db.read.concurrency: 20000 +txpool.globalslots: 1000000 +txpool.globalbasefeeslots: 1000000 +txpool.globalqueue: 1000000 +txpool.packbatchspeciallist : ["0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534"] +txpool.gaspricemultiple : 2 +txpool.blockedlist: ["0xdD2FD4581271e230360230F9337D5c0430Bf44C0"] +txpool.enablefreegasbynonce : true +txpool.freegascountperaddr : 100 +txpool.commit.every: "10m" + +gpo.type: "follower" +gpo.update-period: "3s" +gpo.factor: 0.01 +gpo.kafka-url: "0.0.0.0" +gpo.topic: "explorer" +gpo.group-id: "web3" +gpo.blocks: 3 +gpo.default-l1-coin-price: 2000 +gpo.default-l2-coin-price: 50 +gpo.gas-price-usdt: 0.000000476190476 +gpo.congestion-threshold: 0 + +networkid: 195 + +pprof: true +pprof.port: 6060 +pprof.addr: 0.0.0.0 +txpool.enablefreegaslist : true +txpool.freegaslist : '[{"name":"e2e", "from_list":["0x586cbc95ed16031d9efdaebacf1c1d2bc3ccaa78"], "to_list":["0xad1d01007a56ee0a4ffd0488fb58fc6500cb1fbe"], "method_sigs":["a9059cbb"], "gas_price_multiple": 1}]' + +# close a block/batch immediately after the 1st zkCounter overflow TX +zkevm.seal-batch-immediately-on-overflow: true +zkevm.sequencer-timeout-on-empty-tx-pool: 5ms +zkevm.pre-run-address-list: [""] +zkevm.block-info-concurrent: true +zkevm.standalone-smt-db: true # true: enable split smt db, false: not split +zkevm.enable-async-commit: true + +# to reduce lock race in stress test +txpool.enabletimsort: true +zkevm.bulk-add-txs: true +zkevm.enable-add-tx-notify: true +zkevm.initial-batch.config: /usr/src/app/first-batch-config.json \ No newline at end of file diff --git a/test-pp-op/config/test.genesis.config.json b/test-pp-op/config/test.genesis.config.json new file mode 100644 index 0000000000000..dca366627bfdc --- /dev/null +++ b/test-pp-op/config/test.genesis.config.json @@ -0,0 +1,109 @@ +{ + "L1Config": { + "chainId": 1337, + "polygonZkEVMAddress": "0xE45CCD0757670580a4a3600DE5cef1e45F0Ec2bd", + "polygonRollupManagerAddress": "0xE96dBF374555C6993618906629988d39184716B3", + "polTokenAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "polygonZkEVMGlobalExitRootAddress": "0xB8cedD4B9eF683f0887C44a6E4312dC7A6e2fcdB" + }, + "genesisBlockNumber": 91, + "rollupCreationBlockNumber": 100, + "rollupManagerCreationBlockNumber": 91, + "root": "0xef7bb96e820d4d8440f9bae6b1d58427c06e324ac9d5f7a5156438dd42e837c5", + "genesis": [ + { + "contractName": "TokenWrappedBridgeInitCode", + "balance": "0", + "nonce": "1", + "address": "0x750a9c3AB9334e28bdB05B121BDe530351733BC2", + "bytecode": "0x608060405234801561000f575f5ffd5b5060043610610029575f3560e01c806383c43a551461002d575b5f5ffd5b61003561004b565b604051610042919061006a565b60405180910390f35b60405180611ba00160405280611b6681526020016100b6611b66913981565b602081525f82518060208401525f5b818110156100965760208186018101516040868401015201610079565b505f604082850101526040601f19601f8301168401019150509291505056fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220e2e0b7899260251baf2cfa7cf6126f1d0a5731b4f1051ae5b437d90ddbc6867164736f6c634300081c0033" + }, + { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "4", + "address": "0x18c279c3Ed0b54b9f9D815cD12bee2d2d68a4B42", + "bytecode": "0x60806040526004361061006e575f3560e01c8063715018a61161004c578063715018a6146100e25780638da5cb5b146100f6578063e11ae6cb1461011f578063f2fde38b14610132575f80fd5b80632b79805a146100725780634a94d487146100875780636d07dbf81461009a575b5f80fd5b610085610080366004610908565b610151565b005b6100856100953660046109a2565b6101c2565b3480156100a5575f80fd5b506100b96100b43660046109f5565b610203565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ed575f80fd5b50610085610215565b348015610101575f80fd5b505f5473ffffffffffffffffffffffffffffffffffffffff166100b9565b61008561012d366004610a15565b610228565b34801561013d575f80fd5b5061008561014c366004610a61565b61028e565b61015961034a565b5f6101658585856103ca565b90506101718183610527565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101ca61034a565b6101d583838361056a565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b905f90a1505050565b5f61020e8383610598565b9392505050565b61021d61034a565b6102265f6105a4565b565b61023061034a565b5f61023c8484846103ca565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b61029661034a565b73ffffffffffffffffffffffffffffffffffffffff811661033e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610347816105a4565b50565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610226576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610335565b5f83471015610435576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610335565b81515f0361049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610335565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff811661020e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610335565b606061020e83835f6040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610618565b6060610590848484604051806060016040528060298152602001610b0860299139610618565b949350505050565b5f61020e83833061072d565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610335565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516106d29190610a9c565b5f6040518083038185875af1925050503d805f811461070c576040519150601f19603f3d011682016040523d82523d5f602084013e610711565b606091505b509150915061072287838387610756565b979650505050505050565b5f604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156107eb5782515f036107e45773ffffffffffffffffffffffffffffffffffffffff85163b6107e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610335565b5081610590565b61059083838151156108005781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103359190610ab7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112610870575f80fd5b813567ffffffffffffffff8082111561088b5761088b610834565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108d1576108d1610834565b816040528381528660208588010111156108e9575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f806080858703121561091b575f80fd5b8435935060208501359250604085013567ffffffffffffffff80821115610940575f80fd5b61094c88838901610861565b93506060870135915080821115610961575f80fd5b5061096e87828801610861565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff8116811461099d575f80fd5b919050565b5f805f606084860312156109b4575f80fd5b6109bd8461097a565b9250602084013567ffffffffffffffff8111156109d8575f80fd5b6109e486828701610861565b925050604084013590509250925092565b5f8060408385031215610a06575f80fd5b50508035926020909101359150565b5f805f60608486031215610a27575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115610a4b575f80fd5b610a5786828701610861565b9150509250925092565b5f60208284031215610a71575f80fd5b61020e8261097a565b5f5b83811015610a94578181015183820152602001610a7c565b50505f910152565b5f8251610aad818460208701610a7a565b9190910192915050565b602081525f8251806020840152610ad5816040850160208701610a7a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220330b94dc698c4d290bf55c23f13b473cde6a6bae0030cb902de18af54e35839f64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000008f8e2d6cf621f30e9a11309d6a56a876281fd534" + } + }, + { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "address": "0x5DE1783073a44e3bdE977689a768b9cFA1ac58E7", + "bytecode": "0x608060405260043610610079575f3560e01c80639623609d1161004c5780639623609d1461012357806399a88ec414610136578063f2fde38b14610155578063f3b7dead14610174575f5ffd5b8063204e1c7a1461007d578063715018a6146100c55780637eff275e146100db5780638da5cb5b146100fa575b5f5ffd5b348015610088575f5ffd5b5061009c6100973660046105e8565b610193565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d0575f5ffd5b506100d9610244565b005b3480156100e6575f5ffd5b506100d96100f536600461060a565b610257565b348015610105575f5ffd5b505f5473ffffffffffffffffffffffffffffffffffffffff1661009c565b6100d961013136600461066e565b6102e0565b348015610141575f5ffd5b506100d961015036600461060a565b610371565b348015610160575f5ffd5b506100d961016f3660046105e8565b6103cd565b34801561017f575f5ffd5b5061009c61018e3660046105e8565b610489565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b5f60405180830381855afa9150503d805f8114610215576040519150601f19603f3d011682016040523d82523d5f602084013e61021a565b606091505b509150915081610228575f5ffd5b8080602001905181019061023c9190610782565b949350505050565b61024c6104d3565b6102555f610553565b565b61025f6104d3565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b5f604051808303815f87803b1580156102c6575f5ffd5b505af11580156102d8573d5f5f3e3d5ffd5b505050505050565b6102e86104d3565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061033e908690869060040161079d565b5f604051808303818588803b158015610355575f5ffd5b505af1158015610367573d5f5f3e3d5ffd5b5050505050505050565b6103796104d3565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102af565b6103d56104d3565b73ffffffffffffffffffffffffffffffffffffffff811661047d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61048681610553565b50565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610474565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610486575f5ffd5b5f602082840312156105f8575f5ffd5b8135610603816105c7565b9392505050565b5f5f6040838503121561061b575f5ffd5b8235610626816105c7565b91506020830135610636816105c7565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5f5f60608486031215610680575f5ffd5b833561068b816105c7565b9250602084013561069b816105c7565b9150604084013567ffffffffffffffff8111156106b6575f5ffd5b8401601f810186136106c6575f5ffd5b803567ffffffffffffffff8111156106e0576106e0610641565b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160116810181811067ffffffffffffffff8211171561074c5761074c610641565b604052818152828201602001881015610763575f5ffd5b816020840160208301375f602083830101528093505050509250925092565b5f60208284031215610792575f5ffd5b8151610603816105c7565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f82518060408401525f5b818110156107e557602081860181015160608684010152016107c8565b505f6060828501015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116840101915050939250505056fea2646970667358221220e111b2ba242ce4421950dc7ff545a01914c776103ce1cd642024c628867ecbf064736f6c634300081c0033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000027284dba79e6df953fbd232a9d8d87029f03bbf5" + } + }, + { + "contractName": "PolygonZkEVMBridgeV2 implementation", + "balance": "0", + "nonce": "2", + "address": "0xa5a941061eF748466b31002415d6dCAe831b015A", + "bytecode": "0x60806040526004361061020f575f3560e01c806383c43a5511610117578063cc461632116100ac578063dbc169761161007c578063f5efcd7911610062578063f5efcd7914610683578063f811bff7146106a2578063fb570834146106c1575f5ffd5b8063dbc1697614610644578063ee25560b14610658575f5ffd5b8063cc461632146105cb578063ccaa2d11146105ea578063cd58657914610609578063d02103ca1461061c575f5ffd5b8063b8b284d0116100e7578063b8b284d014610549578063bab161bf14610568578063be5831c714610589578063c00f14ab146105ac575f5ffd5b806383c43a55146104d857806383f24403146104ec5780638ed7e3f21461050b578063aaa13cc21461052a575f5ffd5b80633c351e10116101a75780635ca1e165116101775780637843298b1161015d5780637843298b1461047157806379e2cf971461049057806381b1c174146104a4575f5ffd5b80635ca1e1651461041557806365d6f65414610429575f5ffd5b80633c351e10146103805780633cbc795b1461039f5780633e197043146103d75780634b2f336d146103f6575f5ffd5b806327aef4e8116101e257806327aef4e8146102a15780632dfdf0b5146102c2578063318aee3d146102e5578063381fef6d1461034d575f5ffd5b806315064c96146102135780632072f6c51461024157806322e95f2c14610257578063240ff3781461028e575b5f5ffd5b34801561021e575f5ffd5b5060685461022c9060ff1681565b60405190151581526020015b60405180910390f35b34801561024c575f5ffd5b506102556106e0565b005b348015610262575f5ffd5b50610276610271366004612ea6565b610715565b6040516001600160a01b039091168152602001610238565b61025561029c366004612f2d565b61077f565b3480156102ac575f5ffd5b506102b5610808565b6040516102389190612fef565b3480156102cd575f5ffd5b506102d760535481565b604051908152602001610238565b3480156102f0575f5ffd5b506103296102ff366004613001565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610238565b348015610358575f5ffd5b506102767f000000000000000000000000750a9c3ab9334e28bdb05b121bde530351733bc281565b34801561038b575f5ffd5b50606d54610276906001600160a01b031681565b3480156103aa575f5ffd5b50606d546103c290600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610238565b3480156103e2575f5ffd5b506102d76103f136600461302a565b610894565b348015610401575f5ffd5b50606f54610276906001600160a01b031681565b348015610420575f5ffd5b506102d761093d565b348015610434575f5ffd5b506102b56040518060400160405280600981526020017f616c2d76302e332e30000000000000000000000000000000000000000000000081525081565b34801561047c575f5ffd5b5061027661048b3660046130a4565b6109bc565b34801561049b575f5ffd5b506102556109e7565b3480156104af575f5ffd5b506102766104be3660046130ea565b606a6020525f90815260409020546001600160a01b031681565b3480156104e3575f5ffd5b506102b5610a08565b3480156104f7575f5ffd5b506102d7610506366004613112565b610a91565b348015610516575f5ffd5b50606c54610276906001600160a01b031681565b348015610535575f5ffd5b50610276610544366004613213565b610b1e565b348015610554575f5ffd5b506102556105633660046132ae565b610c49565b348015610573575f5ffd5b506068546103c290610100900463ffffffff1681565b348015610594575f5ffd5b506068546103c290600160c81b900463ffffffff1681565b3480156105b7575f5ffd5b506102b56105c6366004613001565b610ce0565b3480156105d6575f5ffd5b5061022c6105e536600461332c565b610d25565b3480156105f5575f5ffd5b5061025561060436600461335d565b610dad565b61025561061736600461343c565b611203565b348015610627575f5ffd5b50606854610276906501000000000090046001600160a01b031681565b34801561064f575f5ffd5b506102556115d2565b348015610663575f5ffd5b506102d76106723660046130ea565b60696020525f908152604090205481565b34801561068e575f5ffd5b5061025561069d36600461335d565b611605565b3480156106ad575f5ffd5b506102556106bc3660046134cc565b61187e565b3480156106cc575f5ffd5b5061022c6106db36600461356f565b611b99565b606c546001600160a01b0316331461070b57604051631736745960e31b815260040160405180910390fd5b610713611bb2565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156107a357604051630bc011ff60e21b815260040160405180910390fd5b34158015906107bc5750606f546001600160a01b031615155b156107f3576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610801858534868686611c0d565b5050505050565b606e8054610815906135b4565b80601f0160208091040260200160405190810160405280929190818152602001828054610841906135b4565b801561088c5780601f106108635761010080835404028352916020019161088c565b820191905f5260205f20905b81548152906001019060200180831161086f57829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b60208110156109b3578083901c60011660010361098c5761098560338260208110610974576109746135ec565b0154855f9182526020526040902090565b935061099c565b5f84815260208390526040902093505b5f8281526020839052604090209150600101610947565b50919392505050565b5f6109dd84846109cb85611ce9565b6109d486611dd3565b61054487611eb4565b90505b9392505050565b605354606854600160c81b900463ffffffff16101561071357610713611f81565b60607f000000000000000000000000750a9c3ab9334e28bdb05b121bde530351733bc26001600160a01b03166383c43a556040518163ffffffff1660e01b81526004015f60405180830381865afa158015610a65573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610a8c919081019061362e565b905090565b5f83815b6020811015610b1557600163ffffffff8516821c81169003610ae157610ada858260208110610ac657610ac66135ec565b6020020135835f9182526020526040902090565b9150610b0d565b610b0a82868360208110610af757610af76135ec565b60200201355f9182526020526040902090565b91505b600101610a95565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b3083610b7d610a08565b898989604051602001610b9293929190613673565b60408051601f1981840301815290829052610bb092916020016136ab565b60405160208183030381529060405280519060200120604051602001610c2594939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c6d57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610caf576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f545f90610cc7906001600160a01b03168661202f565b9050610cd7878783878787611c0d565b50505050505050565b6060610ceb82611ce9565b610cf483611dd3565b610cfd84611eb4565b604051602001610d0f93929190613673565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610d4a575063ffffffff83166001145b15610d5c575063ffffffff8316610d84565b610d7164010000000063ffffffff85166136ed565b610d819063ffffffff8616613704565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610dd157604051630bc011ff60e21b815260040160405180910390fd5b610dd96120ac565b60685463ffffffff8681166101009092041614610e09576040516302caf51760e11b815260040160405180910390fd5b610e348c8c8c8c8c5f8d8d8d8d8d8d8d604051610e27929190613717565b6040518091039020612105565b6001600160a01b038616158015610e4f575063ffffffff8716155b15610f4657606f546001600160a01b0316610f2a575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e9c576020820181803683370190505b50604051610eaa9190613726565b5f6040518083038185875af1925050503d805f8114610ee4576040519150601f19603f3d011682016040523d82523d5f602084013e610ee9565b606091505b5050905080610f24576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611190565b606f54610f41906001600160a01b03168585612121565b611190565b606d546001600160a01b038781169116148015610f745750606d5463ffffffff888116600160a01b90920416145b15610f8b575f6001600160a01b0385168482610e72565b60685463ffffffff610100909104811690881603610fb757610f416001600160a01b0387168585612193565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b031680611182575f6110618386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061221492505050565b905061106e818888612121565b80606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a838888604051611174959493929190613769565b60405180910390a15061118d565b61118d818787612121565b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a16111f560018055565b505050505050505050505050565b60685460ff161561122757604051630bc011ff60e21b815260040160405180910390fd5b61122f6120ac565b60685463ffffffff610100909104811690881603611260576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b03881661135c578834146112ac576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff169450906112d9906135b4565b80601f0160208091040260200160405190810160405280929190818152602001828054611305906135b4565b80156113505780601f1061132757610100808354040283529160200191611350565b820191905f5260205f20905b81548152906001019060200180831161133357829003601f168201915b5050505050915061155a565b3415611394576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84156113a6576113a6888a8888612299565b606f546001600160a01b03908116908916036113cd576113c6888a61202f565b905061155a565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901515806114205750805163ffffffff1615155b156114425761142f898b61202f565b602082015182519096509450915061154d565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa158015611486573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114aa91906137a6565b90506114c16001600160a01b038b1633308e6125ff565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa158015611505573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061152991906137a6565b905061153582826137bd565b6068548c9850610100900463ffffffff169650935050505b61155689610ce0565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e86886053546040516115999897969594939291906137d0565b60405180910390a16115b75f84868e8e868880519060200120612650565b86156115c5576115c5611f81565b50505050610cd760018055565b606c546001600160a01b031633146115fd57604051631736745960e31b815260040160405180910390fd5b610713612667565b60685460ff161561162957604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614611659576040516302caf51760e11b815260040160405180910390fd5b6116788c8c8c8c8c60018d8d8d8d8d8d8d604051610e27929190613717565b606f545f906001600160a01b031661172b57846001600160a01b031684888a86866040516024016116ac9493929190613844565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b179052516116e19190613726565b5f6040518083038185875af1925050503d805f811461171b576040519150601f19603f3d011682016040523d82523d5f602084013e611720565b606091505b5050809150506117dc565b606f54611742906001600160a01b03168686612121565b846001600160a01b0316878985856040516024016117639493929190613844565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b179052516117989190613726565b5f604051808303815f865af19150503d805f81146117d1576040519150601f19603f3d011682016040523d82523d5f602084013e6117d6565b606091505b50909150505b80611813576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff161580801561189c57505f54600160ff909116105b806118b55750303b1580156118b557505f5460ff166001145b61192c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff19166001179055801561194d575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff19168583161790558616611a285763ffffffff851615611a23576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b44565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e611a7783826138c0565b50611b165f5f1b6012604051602001611b0291906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b604051602081830303815290604052612214565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611b4c6126d7565b8015610cd7575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611ba6868686610a91565b1490505b949350505050565b60685460ff1615611bd657604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611c3e576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611c929998979695949392919061397b565b60405180910390a1611cd36001606860019054906101000a900463ffffffff16338989898888604051611cc6929190613717565b6040518091039020612650565b8215611ce157611ce1611f81565b505050505050565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611d489190613726565b5f60405180830381855afa9150503d805f8114611d80576040519150601f19603f3d011682016040523d82523d5f602084013e611d85565b606091505b509150915081611dca576040518060400160405280600781526020017f4e4f5f4e414d4500000000000000000000000000000000000000000000000000815250611baa565b611baa81612749565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611e329190613726565b5f60405180830381855afa9150503d805f8114611e6a576040519150601f19603f3d011682016040523d82523d5f602084013e611e6f565b606091505b509150915081611dca576040518060400160405280600981526020017f4e4f5f53594d424f4c0000000000000000000000000000000000000000000000815250611baa565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b03861691611f129190613726565b5f60405180830381855afa9150503d805f8114611f4a576040519150601f19603f3d011682016040523d82523d5f602084013e611f4f565b606091505b5091509150818015611f62575080516020145b611f6d576012611baa565b80806020019051810190611baa91906139f1565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d611fe261093d565b6040518263ffffffff1660e01b815260040161200091815260200190565b5f604051808303815f87803b158015612017575f5ffd5b505af1158015612029573d5f5f3e3d5ffd5b50505050565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018290525f906001600160a01b03841690639dc29fac906044015f604051808303815f87803b15801561208f575f5ffd5b505af11580156120a1573d5f5f3e3d5ffd5b509395945050505050565b6002600154036120fe5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611923565b6002600155565b6111f58c8c8c8c8c61211c8d8d8d8d8d8d8d610894565b61290f565b6040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390528416906340c10f19906044015f604051808303815f87803b158015612181575f5ffd5b505af1158015610cd7573d5f5f3e3d5ffd5b6040516001600160a01b03831660248201526044810182905261220f9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612a79565b505050565b5f5f61221e610a08565b836040516020016122309291906136ab565b6040516020818303038152906040529050838151602083015ff591506001600160a01b03821661228c576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b60018055565b5f6122a76004828486613a0c565b6122b091613a33565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b0319821601612451575f8080808080806122f7896004818d613a0c565b8101906123049190613a68565b9650965096509650965096509650336001600160a01b0316876001600160a01b0316146123445760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038616301461236d5760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e16916124049190613726565b5f604051808303815f865af19150503d805f811461243d576040519150601f19603f3d011682016040523d82523d5f602084013e612442565b606091505b50505050505050505050610801565b6001600160e01b031981166323f2ebc360e21b1461249b576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806124b08a6004818e613a0c565b8101906124bd9190613ab7565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146124ff5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03871630146125285760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f16916125af9190613726565b5f604051808303815f865af19150503d805f81146125e8576040519150601f19603f3d011682016040523d82523d5f602084013e6125ed565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526120299085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016121d8565b610cd761266288888888888888610894565b612b5d565b60685460ff166126a3576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff166127415760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611923565b610713612c35565b606060408251106127685781806020019051810190610779919061362e565b81516020036128d1575f5b6020811080156127ba5750828181518110612790576127906135ec565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b156127d157806127c981613b35565b915050612773565b805f0361281357505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff81111561282d5761282d61314e565b6040519080825280601f01601f191660200182016040528015612857576020820181803683370190505b5090505f5b828110156128c957848181518110612876576128766135ec565b602001015160f81c60f81b828281518110612893576128936135ec565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060010161285c565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f906501000000000090046001600160a01b031663257b363261293e86865f9182526020526040902090565b6040518263ffffffff1660e01b815260040161295c91815260200190565b6020604051808303815f875af1158015612978573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061299c91906137a6565b9050805f036129d6576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8068010000000000000000871615612a1a578691506129f8848a8489611b99565b612a15576040516338105f3b60e21b815260040160405180910390fd5b612a64565b602087901c612a2a816001613b4d565b9150879250612a45612a3d868c86610a91565b8a8389611b99565b612a62576040516338105f3b60e21b815260040160405180910390fd5b505b612a6e8282612c9f565b505050505050505050565b5f612acd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612d5f9092919063ffffffff16565b80519091501561220f5780806020019051810190612aeb9190613b69565b61220f5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611923565b806001612b6c60206002613c67565b612b7691906137bd565b60535410612bb0576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f8154612bbf90613b35565b918290555090505f5b6020811015612c2c578082901c600116600103612bfb578260338260208110612bf357612bf36135ec565b015550505050565b612c2260338260208110612c1157612c116135ec565b0154845f9182526020526040902090565b9250600101612bc8565b5061220f613c72565b5f54610100900460ff166122935760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611923565b6068545f90610100900463ffffffff16158015612cc2575063ffffffff82166001145b15612cd4575063ffffffff8216612cfc565b612ce964010000000063ffffffff84166136ed565b612cf99063ffffffff8516613704565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003610cd7576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60606109dd84845f85855f5f866001600160a01b03168587604051612d849190613726565b5f6040518083038185875af1925050503d805f8114612dbe576040519150601f19603f3d011682016040523d82523d5f602084013e612dc3565b606091505b5091509150612dd487838387612ddf565b979650505050505050565b60608315612e4d5782515f03612e46576001600160a01b0385163b612e465760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611923565b5081611baa565b611baa8383815115612e625781518083602001fd5b8060405162461bcd60e51b81526004016119239190612fef565b803563ffffffff8116811461290a575f5ffd5b6001600160a01b0381168114612ea3575f5ffd5b50565b5f5f60408385031215612eb7575f5ffd5b612ec083612e7c565b91506020830135612ed081612e8f565b809150509250929050565b8015158114612ea3575f5ffd5b5f5f83601f840112612ef8575f5ffd5b50813567ffffffffffffffff811115612f0f575f5ffd5b602083019150836020828501011115612f26575f5ffd5b9250929050565b5f5f5f5f5f60808688031215612f41575f5ffd5b612f4a86612e7c565b94506020860135612f5a81612e8f565b93506040860135612f6a81612edb565b9250606086013567ffffffffffffffff811115612f85575f5ffd5b612f9188828901612ee8565b969995985093965092949392505050565b5f5b83811015612fbc578181015183820152602001612fa4565b50505f910152565b5f8151808452612fdb816020860160208601612fa2565b601f01601f19169290920160200192915050565b602081525f6109e06020830184612fc4565b5f60208284031215613011575f5ffd5b81356109e081612e8f565b60ff81168114612ea3575f5ffd5b5f5f5f5f5f5f5f60e0888a031215613040575f5ffd5b873561304b8161301c565b965061305960208901612e7c565b9550604088013561306981612e8f565b945061307760608901612e7c565b9350608088013561308781612e8f565b9699959850939692959460a0840135945060c09093013592915050565b5f5f5f606084860312156130b6575f5ffd5b6130bf84612e7c565b925060208401356130cf81612e8f565b915060408401356130df81612e8f565b809150509250925092565b5f602082840312156130fa575f5ffd5b5035919050565b806104008101831015610779575f5ffd5b5f5f5f6104408486031215613125575f5ffd5b833592506131368560208601613101565b91506131456104208501612e7c565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561318b5761318b61314e565b604052919050565b5f67ffffffffffffffff8211156131ac576131ac61314e565b50601f01601f191660200190565b5f6131cc6131c784613193565b613162565b90508281528383830111156131df575f5ffd5b828260208301375f602084830101529392505050565b5f82601f830112613204575f5ffd5b6109e0838335602085016131ba565b5f5f5f5f5f60a08688031215613227575f5ffd5b61323086612e7c565b9450602086013561324081612e8f565b9350604086013567ffffffffffffffff81111561325b575f5ffd5b613267888289016131f5565b935050606086013567ffffffffffffffff811115613283575f5ffd5b61328f888289016131f5565b92505060808601356132a08161301c565b809150509295509295909350565b5f5f5f5f5f5f60a087890312156132c3575f5ffd5b6132cc87612e7c565b955060208701356132dc81612e8f565b94506040870135935060608701356132f381612edb565b9250608087013567ffffffffffffffff81111561330e575f5ffd5b61331a89828a01612ee8565b979a9699509497509295939492505050565b5f5f6040838503121561333d575f5ffd5b61334683612e7c565b915061335460208401612e7c565b90509250929050565b5f5f5f5f5f5f5f5f5f5f5f5f6109208d8f031215613379575f5ffd5b6133838e8e613101565b9b506133938e6104008f01613101565b9a506108008d013599506108208d013598506108408d013597506133ba6108608e01612e7c565b96506133ca6108808e0135612e8f565b6108808d013595506133df6108a08e01612e7c565b94506108c08d01356133f081612e8f565b93506108e08d0135925067ffffffffffffffff6109008e01351115613413575f5ffd5b6134248e6109008f01358f01612ee8565b81935080925050509295989b509295989b509295989b565b5f5f5f5f5f5f5f60c0888a031215613452575f5ffd5b61345b88612e7c565b9650602088013561346b81612e8f565b955060408801359450606088013561348281612e8f565b9350608088013561349281612edb565b925060a088013567ffffffffffffffff8111156134ad575f5ffd5b6134b98a828b01612ee8565b989b979a50959850939692959293505050565b5f5f5f5f5f5f60c087890312156134e1575f5ffd5b6134ea87612e7c565b955060208701356134fa81612e8f565b945061350860408801612e7c565b9350606087013561351881612e8f565b9250608087013561352881612e8f565b915060a087013567ffffffffffffffff811115613543575f5ffd5b8701601f81018913613553575f5ffd5b613562898235602084016131ba565b9150509295509295509295565b5f5f5f5f6104608587031215613583575f5ffd5b843593506135948660208701613101565b92506135a36104208601612e7c565b939692955092936104400135925050565b600181811c908216806135c857607f821691505b6020821081036135e657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b5f61360d6131c784613193565b9050828152838383011115613620575f5ffd5b6109e0836020830184612fa2565b5f6020828403121561363e575f5ffd5b815167ffffffffffffffff811115613654575f5ffd5b8201601f81018413613664575f5ffd5b611baa84825160208401613600565b606081525f6136856060830186612fc4565b82810360208401526136978186612fc4565b91505060ff83166040830152949350505050565b5f83516136bc818460208801612fa2565b8351908301906136d0818360208801612fa2565b01949350505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610779576107796136d9565b80820180821115610779576107796136d9565b818382375f9101908152919050565b5f8251613737818460208701612fa2565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681526001600160a01b03851660208201526001600160a01b0384166040820152608060608201525f612dd4608083018486613741565b5f602082840312156137b6575f5ffd5b5051919050565b81810381811115610779576107796136d9565b60ff8916815263ffffffff881660208201526001600160a01b038716604082015263ffffffff861660608201526001600160a01b03851660808201528360a082015261010060c08201525f613829610100830185612fc4565b905063ffffffff831660e08301529998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f613872606083018486613741565b9695505050505050565b601f82111561220f57805f5260205f20601f840160051c810160208510156138a15750805b601f840160051c820191505b81811015610801575f81556001016138ad565b815167ffffffffffffffff8111156138da576138da61314e565b6138ee816138e884546135b4565b8461387c565b6020601f821160018114613920575f83156139095750848201515b5f19600385901b1c1916600184901b178455610801565b5f84815260208120601f198516915b8281101561394f578785015182556020948501946001909201910161392f565b508482101561396c57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b60ff8a16815263ffffffff891660208201526001600160a01b038816604082015263ffffffff871660608201526001600160a01b03861660808201528460a082015261010060c08201525f6139d561010083018587613741565b905063ffffffff831660e08301529a9950505050505050505050565b5f60208284031215613a01575f5ffd5b81516109e08161301c565b5f5f85851115613a1a575f5ffd5b83861115613a26575f5ffd5b5050820193919092039150565b80356001600160e01b0319811690600484101561228c576001600160e01b0319808560040360031b1b82161691505092915050565b5f5f5f5f5f5f5f60e0888a031215613a7e575f5ffd5b8735613a8981612e8f565b96506020880135613a9981612e8f565b9550604088013594506060880135935060808801356130878161301c565b5f5f5f5f5f5f5f5f610100898b031215613acf575f5ffd5b8835613ada81612e8f565b97506020890135613aea81612e8f565b965060408901359550606089013594506080890135613b0881612edb565b935060a0890135613b188161301c565b979a969950949793969295929450505060c08201359160e0013590565b5f60018201613b4657613b466136d9565b5060010190565b63ffffffff8181168382160190811115610779576107796136d9565b5f60208284031215613b79575f5ffd5b81516109e081612edb565b6001815b6001841115613bbf57808504811115613ba357613ba36136d9565b6001841615613bb157908102905b60019390931c928002613b88565b935093915050565b5f82613bd557506001610779565b81613be157505f610779565b8160018114613bf75760028114613c0157613c1d565b6001915050610779565b60ff841115613c1257613c126136d9565b50506001821b610779565b5060208310610133831016604e8410600b8410161715613c40575081810a610779565b613c4c5f198484613b84565b805f1904821115613c5f57613c5f6136d9565b029392505050565b5f6109e08383613bc7565b634e487b7160e01b5f52600160045260245ffdfea2646970667358221220849aaee1cc1978fd76e0346e23e1c9651b52ff9e7089a5e63e964925adf544c264736f6c634300081c0033" + }, + { + "contractName": "PolygonZkEVMBridgeV2 proxy", + "balance": "340282366920938463463374607431768211455", + "nonce": "1", + "address": "0x4B24266C13AFEf2bb60e2C69A4C08A482d81e3CA", + "bytecode": "0x60806040526004361061005d575f3560e01c80635c60da1b116100425780635c60da1b146100a65780638f283970146100e3578063f851a440146101025761006c565b80633659cfe6146100745780634f1ef286146100935761006c565b3661006c5761006a610116565b005b61006a610116565b34801561007f575f5ffd5b5061006a61008e366004610854565b610130565b61006a6100a136600461086d565b610178565b3480156100b1575f5ffd5b506100ba6101eb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ee575f5ffd5b5061006a6100fd366004610854565b610228565b34801561010d575f5ffd5b506100ba610255565b61011e610282565b61012e610129610359565b610362565b565b610138610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d8160405180602001604052805f8152505f6103bf565b50565b61016d610116565b610180610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101e3576101de8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250600192506103bf915050565b505050565b6101de610116565b5f6101f4610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610359565b905090565b610225610116565b90565b610230610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d816103e9565b5f61025e610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610380565b61028a610380565b73ffffffffffffffffffffffffffffffffffffffff16330361012e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b5f61021861044a565b365f5f375f5f365f845af43d5f5f3e80801561037c573d5ff35b3d5ffd5b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6103c883610471565b5f825111806103d45750805b156101de576103e383836104bd565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610412610380565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161016d816104e9565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103a3565b61047a816105f5565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606104e28383604051806060016040528060278152602001610979602791396106c0565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661058c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610350565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b73ffffffffffffffffffffffffffffffffffffffff81163b610699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610350565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105af565b60605f5f8573ffffffffffffffffffffffffffffffffffffffff16856040516106e9919061090d565b5f60405180830381855af49150503d805f8114610721576040519150601f19603f3d011682016040523d82523d5f602084013e610726565b606091505b509150915061073786838387610741565b9695505050505050565b606083156107d65782515f036107cf5773ffffffffffffffffffffffffffffffffffffffff85163b6107cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610350565b50816107e0565b6107e083836107e8565b949350505050565b8151156107f85781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103509190610928565b803573ffffffffffffffffffffffffffffffffffffffff8116811461084f575f5ffd5b919050565b5f60208284031215610864575f5ffd5b6104e28261082c565b5f5f5f6040848603121561087f575f5ffd5b6108888461082c565b9250602084013567ffffffffffffffff8111156108a3575f5ffd5b8401601f810186136108b3575f5ffd5b803567ffffffffffffffff8111156108c9575f5ffd5b8660208284010111156108da575f5ffd5b939660209190910195509293505050565b5f5b838110156109055781810151838201526020016108ed565b50505f910152565b5f825161091e8184602087016108eb565b9190910192915050565b602081525f82518060208401526109468160408501602087016108eb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b4314c6ef866fe81c59eeee5f2b9032aaf3dc70c6d4ab82137af7b26a764741664736f6c634300081c0033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000005de1783073a44e3bde977689a768b9cfa1ac58e7", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000a5a941061ef748466b31002415d6dcae831b015a" + } + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "address": "0x21BD2401BA404841c7feC1816F5a0AaAdbc486eF", + "bytecode": "0x608060405234801561000f575f5ffd5b506004361061004a575f3560e01c806301fd90441461004e578063257b36321461006a57806333d6247d14610089578063a3c573eb1461009e575b5f5ffd5b61005760015481565b6040519081526020015b60405180910390f35b61005761007836600461015e565b5f6020819052908152604090205481565b61009c61009736600461015e565b6100ea565b005b6100c57f0000000000000000000000004b24266c13afef2bb60e2c69a4c08a482d81e3ca81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610061565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004b24266c13afef2bb60e2c69a4c08a482d81e3ca1614610159576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b5f6020828403121561016e575f5ffd5b503591905056fea26469706673582212208915b6fcaffb67739719d531325bac93ba2790d8aec6a382f704b8d2db9769f964736f6c634300081c0033" + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "bytecode": "0x60806040523661001357610011610017565b005b6100115b61001f6101b7565b6001600160a01b0316336001600160a01b0316141561016f5760606001600160e01b031960003516631b2ce7f360e11b8114156100655761005e6101ea565b9150610167565b6001600160e01b0319811663278f794360e11b14156100865761005e610241565b6001600160e01b031981166308f2839760e41b14156100a75761005e610287565b6001600160e01b031981166303e1469160e61b14156100c85761005e6102b8565b6001600160e01b03198116635c60da1b60e01b14156100e95761005e6102f8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b61017761030c565b565b606061019e83836040518060600160405280602781526020016108576027913961031c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101f4610394565b600061020336600481846106a2565b81019061021091906106e8565b905061022d8160405180602001604052806000815250600061039f565b505060408051602081019091526000815290565b606060008061025336600481846106a2565b8101906102609190610719565b915091506102708282600161039f565b604051806020016040528060008152509250505090565b6060610291610394565b60006102a036600481846106a2565b8101906102ad91906106e8565b905061022d816103cb565b60606102c2610394565b60006102cc6101b7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b6060610302610394565b60006102cc610422565b610177610317610422565b610431565b6060600080856001600160a01b0316856040516103399190610807565b600060405180830381855af49150503d8060008114610374576040519150601f19603f3d011682016040523d82523d6000602084013e610379565b606091505b509150915061038a86838387610455565b9695505050505050565b341561017757600080fd5b6103a8836104d3565b6000825111806103b55750805b156103c6576103c48383610179565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103f46101b7565b604080516001600160a01b03928316815291841660208301520160405180910390a161041f81610513565b50565b600061042c6105bc565b905090565b3660008037600080366000845af43d6000803e808015610450573d6000f35b3d6000fd5b606083156104c15782516104ba576001600160a01b0385163b6104ba5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161015e565b50816104cb565b6104cb83836105e4565b949350505050565b6104dc8161060e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105785760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161015e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101db565b8151156105f45781518083602001fd5b8060405162461bcd60e51b815260040161015e9190610823565b6001600160a01b0381163b61067b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161015e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61059b565b600080858511156106b257600080fd5b838611156106bf57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106e357600080fd5b919050565b6000602082840312156106fa57600080fd5b61019e826106cc565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561072c57600080fd5b610735836106cc565b9150602083013567ffffffffffffffff8082111561075257600080fd5b818501915085601f83011261076657600080fd5b81358181111561077857610778610703565b604051601f8201601f19908116603f011681019083821181831017156107a0576107a0610703565b816040528281528860208487010111156107b957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107f65781810151838201526020016107de565b838111156103c45750506000910152565b600082516108198184602087016107db565b9190910192915050565b60208152600082518060208401526108428160408501602087016107db565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122012bb4f564f73959a03513dc74fc3c6e40e8386e6f02c16b78d6db00ce0aa16af64736f6c63430008090033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000005de1783073a44e3bde977689a768b9cfa1ac58e7", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000021bd2401ba404841c7fec1816f5a0aaadbc486ef" + } + }, + { + "contractName": "PolygonZkEVMTimelock", + "balance": "0", + "nonce": "1", + "address": "0x27284DBa79e6DF953Fbd232A9d8D87029F03BBf5", + "bytecode": "0x6080604052600436106101bd575f3560e01c806364d62353116100f2578063b1c5f42711610092578063d547741f11610062578063d547741f1461063a578063e38335e514610659578063f23a6e611461066c578063f27a0c92146106b0575f80fd5b8063b1c5f4271461058d578063bc197c81146105ac578063c4d252f5146105f0578063d45c44351461060f575f80fd5b80638f61f4f5116100cd5780638f61f4f5146104c557806391d14854146104f8578063a217fddf14610547578063b08e51c01461055a575f80fd5b806364d62353146104685780638065657f146104875780638f2a0bb0146104a6575f80fd5b8063248a9ca31161015d57806331d507501161013857806331d50750146103b357806336568abe146103d25780633a6aae72146103f1578063584b153e14610449575f80fd5b8063248a9ca3146103375780632ab0f529146103655780632f2ff15d14610394575f80fd5b80630d3cf6fc116101985780630d3cf6fc1461025e578063134008d31461029157806313bc9f20146102a4578063150b7a02146102c3575f80fd5b806301d5062a146101c857806301ffc9a7146101e957806307bd02651461021d575f80fd5b366101c457005b5f80fd5b3480156101d3575f80fd5b506101e76101e2366004611bf6565b6106c4565b005b3480156101f4575f80fd5b50610208610203366004611c65565b610757565b60405190151581526020015b60405180910390f35b348015610228575f80fd5b506102507fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610214565b348015610269575f80fd5b506102507f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101e761029f366004611ca4565b6107b2565b3480156102af575f80fd5b506102086102be366004611d0b565b6108a7565b3480156102ce575f80fd5b506103066102dd366004611e28565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610214565b348015610342575f80fd5b50610250610351366004611d0b565b5f9081526020819052604090206001015490565b348015610370575f80fd5b5061020861037f366004611d0b565b5f908152600160208190526040909120541490565b34801561039f575f80fd5b506101e76103ae366004611e8c565b6108cc565b3480156103be575f80fd5b506102086103cd366004611d0b565b6108f5565b3480156103dd575f80fd5b506101e76103ec366004611e8c565b61090d565b3480156103fc575f80fd5b506104247f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b348015610454575f80fd5b50610208610463366004611d0b565b6109c5565b348015610473575f80fd5b506101e7610482366004611d0b565b6109da565b348015610492575f80fd5b506102506104a1366004611ca4565b610aaa565b3480156104b1575f80fd5b506101e76104c0366004611ef7565b610ae8565b3480156104d0575f80fd5b506102507fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610503575f80fd5b50610208610512366004611e8c565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b348015610552575f80fd5b506102505f81565b348015610565575f80fd5b506102507ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b348015610598575f80fd5b506102506105a7366004611fa0565b610d18565b3480156105b7575f80fd5b506103066105c63660046120be565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b3480156105fb575f80fd5b506101e761060a366004611d0b565b610d5c565b34801561061a575f80fd5b50610250610629366004611d0b565b5f9081526001602052604090205490565b348015610645575f80fd5b506101e7610654366004611e8c565b610e56565b6101e7610667366004611fa0565b610e7a565b348015610677575f80fd5b50610306610686366004612161565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106bb575f80fd5b50610250611121565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16106ee81611200565b5f6106fd898989898989610aaa565b9050610709818461120d565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161074496959493929190612208565b60405180910390a3505050505050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107ac57506107ac82611359565b92915050565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661082e5761082e81336113ef565b5f61083d888888888888610aaa565b905061084981856114a6565b610855888888886115e2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a60405161088c9493929190612252565b60405180910390a361089d816116e2565b5050505050505050565b5f818152600160205260408120546001811180156108c55750428111155b9392505050565b5f828152602081905260409020600101546108e681611200565b6108f0838361178a565b505050565b5f8181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109c18282611878565b5050565b5f818152600160208190526040822054610906565b333014610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109ae565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b5f868686868686604051602001610ac696959493929190612208565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b1281611200565b888714610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b888514610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f610c418b8b8b8b8b8b8b8b610d18565b9050610c4d818461120d565b5f5b8a811015610d0a5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c8c57610c8c612291565b9050602002016020810190610ca191906122be565b8d8d86818110610cb357610cb3612291565b905060200201358c8c87818110610ccc57610ccc612291565b9050602002810190610cde91906122d7565b8c8b604051610cf296959493929190612208565b60405180910390a3610d0381612365565b9050610c4f565b505050505050505050505050565b5f8888888888888888604051602001610d38989796959493929190612447565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610d8681611200565b610d8f826109c5565b610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109ae565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610e7081611200565b6108f08383611878565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610ef657610ef681336113ef565b878614610f85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b878414611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f6110258a8a8a8a8a8a8a8a610d18565b905061103181856114a6565b5f5b8981101561110b575f8b8b8381811061104e5761104e612291565b905060200201602081019061106391906122be565b90505f8a8a8481811061107857611078612291565b905060200201359050365f8a8a8681811061109557611095612291565b90506020028101906110a791906122d7565b915091506110b7848484846115e2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516110ee9493929190612252565b60405180910390a3505050508061110490612365565b9050611033565b50611115816116e2565b50505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16158015906111ef57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ef919061250c565b156111f957505f90565b5060025490565b61120a81336113ef565b50565b611216826108f5565b156112a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109ae565b6112ab611121565b81101561133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109ae565b611344814261252b565b5f928352600160205260409092209190915550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ac57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ac565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c15761142c8161192d565b61143783602061194c565b604051602001611448929190612560565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109ae916004016125e0565b6114af826108a7565b61153b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b80158061155657505f81815260016020819052604090912054145b6109c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f8473ffffffffffffffffffffffffffffffffffffffff1684848460405161160b929190612630565b5f6040518083038185875af1925050503d805f8114611645576040519150601f19603f3d011682016040523d82523d5f602084013e61164a565b606091505b50509050806116db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109ae565b5050505050565b6116eb816108a7565b611777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b5f90815260016020819052604090912055565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561181a3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107ac73ffffffffffffffffffffffffffffffffffffffff831660145b60605f61195a83600261263f565b61196590600261252b565b67ffffffffffffffff81111561197d5761197d611d22565b6040519080825280601f01601f1916602001820160405280156119a7576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106119dd576119dd612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a3f57611a3f612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f611a7984600261263f565b611a8490600161252b565b90505b6001811115611b20577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611ac557611ac5612291565b1a60f81b828281518110611adb57611adb612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060049490941c93611b1981612656565b9050611a87565b5083156108c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109ae565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bac575f80fd5b919050565b5f8083601f840112611bc1575f80fd5b50813567ffffffffffffffff811115611bd8575f80fd5b602083019150836020828501011115611bef575f80fd5b9250929050565b5f805f805f805f60c0888a031215611c0c575f80fd5b611c1588611b89565b965060208801359550604088013567ffffffffffffffff811115611c37575f80fd5b611c438a828b01611bb1565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f60208284031215611c75575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108c5575f80fd5b5f805f805f8060a08789031215611cb9575f80fd5b611cc287611b89565b955060208701359450604087013567ffffffffffffffff811115611ce4575f80fd5b611cf089828a01611bb1565b979a9699509760608101359660809091013595509350505050565b5f60208284031215611d1b575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d9657611d96611d22565b604052919050565b5f82601f830112611dad575f80fd5b813567ffffffffffffffff811115611dc757611dc7611d22565b611df860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d4f565b818152846020838601011115611e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611e3b575f80fd5b611e4485611b89565b9350611e5260208601611b89565b925060408501359150606085013567ffffffffffffffff811115611e74575f80fd5b611e8087828801611d9e565b91505092959194509250565b5f8060408385031215611e9d575f80fd5b82359150611ead60208401611b89565b90509250929050565b5f8083601f840112611ec6575f80fd5b50813567ffffffffffffffff811115611edd575f80fd5b6020830191508360208260051b8501011115611bef575f80fd5b5f805f805f805f805f60c08a8c031215611f0f575f80fd5b893567ffffffffffffffff80821115611f26575f80fd5b611f328d838e01611eb6565b909b50995060208c0135915080821115611f4a575f80fd5b611f568d838e01611eb6565b909950975060408c0135915080821115611f6e575f80fd5b50611f7b8c828d01611eb6565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f805f805f805f8060a0898b031215611fb7575f80fd5b883567ffffffffffffffff80821115611fce575f80fd5b611fda8c838d01611eb6565b909a50985060208b0135915080821115611ff2575f80fd5b611ffe8c838d01611eb6565b909850965060408b0135915080821115612016575f80fd5b506120238b828c01611eb6565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112612050575f80fd5b8135602067ffffffffffffffff82111561206c5761206c611d22565b8160051b61207b828201611d4f565b9283528481018201928281019087851115612094575f80fd5b83870192505b848310156120b35782358252918301919083019061209a565b979650505050505050565b5f805f805f60a086880312156120d2575f80fd5b6120db86611b89565b94506120e960208701611b89565b9350604086013567ffffffffffffffff80821115612105575f80fd5b61211189838a01612041565b94506060880135915080821115612126575f80fd5b61213289838a01612041565b93506080880135915080821115612147575f80fd5b5061215488828901611d9e565b9150509295509295909350565b5f805f805f60a08688031215612175575f80fd5b61217e86611b89565b945061218c60208701611b89565b93506040860135925060608601359150608086013567ffffffffffffffff8111156121b5575f80fd5b61215488828901611d9e565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201525f61223d60a0830186886121c1565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201525f6122876060830184866121c1565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156122ce575f80fd5b6108c582611b89565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261230a575f80fd5b83018035915067ffffffffffffffff821115612324575f80fd5b602001915036819003821315611bef575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239557612395612338565b5060010190565b8183525f6020808501808196508560051b81019150845f5b8781101561243a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126123f2575f80fd5b8701858101903567ffffffffffffffff81111561240d575f80fd5b80360382131561241b575f80fd5b6124268682846121c1565b9a87019a95505050908401906001016123b4565b5091979650505050505050565b60a080825281018890525f8960c08301825b8b8110156124945773ffffffffffffffffffffffffffffffffffffffff61247f84611b89565b16825260209283019290910190600101612459565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8911156124cc575f80fd5b8860051b9150818a602083013701828103602090810160408501526124f4908201878961239c565b60608401959095525050608001529695505050505050565b5f6020828403121561251c575f80fd5b815180151581146108c5575f80fd5b808201808211156107ac576107ac612338565b5f5b83811015612558578181015183820152602001612540565b50505f910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161259781601785016020880161253e565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125d481602884016020880161253e565b01602801949350505050565b602081525f82518060208401526125fe81604085016020870161253e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b818382375f9101908152919050565b80820281158282048414176107ac576107ac612338565b5f8161266457612664612338565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea264697066735822122085c4cf030f76482828ded4e6c9cb7851ec61b401cf6380abe817d249dc4719fb64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x000000000000000000000000000000000000000000000000000000000000003c", + "0x73aec4d9eb3be1097d809826691104f0c28da74ebf68d903dc9c6f12562fd822": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x6b347b5397bd05b592ec00f3e3a28ac3cedc5d7ee6994c7533215f223a0cfe84": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x35fa115b92f0a8d03c972ada19f34c3fa238589ba573a59a419692abc6a91f1a": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0xc05edde0499e76380516353a6ad6ced0d360179c67da013977526f6fbac38774": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x3e92e57d702d5fdc47a588386c93df7f5578fb6af324e63318e76ec6cffcab32": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + } + }, + { + "accountName": "keyless Deployer", + "balance": "0", + "nonce": "1", + "address": "0xCBb32b7819EC30d41e1399b32dbE32dd5D47a55E" + }, + { + "accountName": "deployer", + "balance": "100000000000000000000000", + "nonce": "8", + "address": "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534" + } + ] +} \ No newline at end of file diff --git a/test-pp-op/config/test.node.config.toml b/test-pp-op/config/test.node.config.toml new file mode 100644 index 0000000000000..ac7d141e1c14c --- /dev/null +++ b/test-pp-op/config/test.node.config.toml @@ -0,0 +1,6 @@ +[Etherman] +URL = "http://l1-geth:8545" +ForkIDChunkSize = 100 +MultiGasProvider = false +[Etherscan] +ApiKey = "" \ No newline at end of file diff --git a/test-pp-op/config/test.poolmanager.toml b/test-pp-op/config/test.poolmanager.toml new file mode 100644 index 0000000000000..c7e4a2a41ee11 --- /dev/null +++ b/test-pp-op/config/test.poolmanager.toml @@ -0,0 +1,37 @@ +[Log] +Environment = "development" # "production" or "development" +Level = "info" +Outputs = ["stderr"] + +[Server] +Host = "0.0.0.0" +Port = 8545 +ReadTimeout = "60s" +WriteTimeout = "60s" +MaxRequestsPerIPAndSecond = 50000 +EnableHttpLog = true +BatchRequestsEnabled = false +BatchRequestsLimit = 20 + +[DB] +User = "pool_user" +Password = "pool_password" +Name = "pool_db" +Host = "xlayer-pool-db" +Port = "5432" +EnableLog = false +MaxConns = 200 + +[Sender] +SequencerURL = "http://xlayer-seq:8545" +ResendTxsCheckInterval = "1s" +Workers = 5 +QueueSize = 25 + +[Monitor] +L2NodeURL = "http://xlayer-seq:8545" +Workers = 5 +QueueSize = 25 +RetryWaitInterval = "3s" +InitialWaitInterval = "1s" +TxLifeTimeMax = "10s" \ No newline at end of file diff --git a/test-pp-op/config/xlayerconfig-mainnet-rpc.yaml b/test-pp-op/config/xlayerconfig-mainnet-rpc.yaml new file mode 100644 index 0000000000000..923419f1a8868 --- /dev/null +++ b/test-pp-op/config/xlayerconfig-mainnet-rpc.yaml @@ -0,0 +1,29 @@ +datadir: /home/erigon/data/ +chain: xlayer-mainnet +http: true +private.api.addr: localhost:9091 +zkevm.l2-chain-id: 196 +zkevm.l2-sequencer-rpc-url: https://rpc.xlayer.tech +zkevm.l2-datastreamer-url: stream.xlayer.tech:8800 +zkevm.l1-chain-id: 1 +zkevm.l1-rpc-url: https://rpc.ankr.com/eth +zkevm.increment-tree-always: true +zkevm.l1-cache-enabled: true + +zkevm.data-stream-host: "localhost" +zkevm.data-stream-port: 6900 + +zkevm.address-sequencer: "0xAF9d27ffe4d51eD54AC8eEc78f2785D7E11E5ab1" +zkevm.address-zkevm: "0x2B0ee28D4D51bC9aDde5E58E295873F61F4a0507" +zkevm.address-rollup: "0x5132A183E9F3CB7C848b0AAC5Ae0c4f0491B7aB2" +zkevm.address-ger-manager: "0x580bda1e7A0CFAe92Fa7F6c20A3794F169CE3CFb" + +zkevm.l1-rollup-id: 3 +zkevm.l1-first-block: 19218658 +zkevm.l1-block-range: 2000 +zkevm.l1-query-delay: 1000 +zkevm.datastream-version: 3 + +http.api: [eth, debug, net, trace, web3, erigon, zkevm] +http.addr: 0.0.0.0 +http.port: 8545 diff --git a/test-pp-op/config/xlayerconfig-mainnet.yaml b/test-pp-op/config/xlayerconfig-mainnet.yaml new file mode 100644 index 0000000000000..50c2d06e82a4d --- /dev/null +++ b/test-pp-op/config/xlayerconfig-mainnet.yaml @@ -0,0 +1,87 @@ +datadir: /home/erigon/data/ +chain: xlayer-mainnet +http: true +private.api.addr: localhost:9091 +zkevm.l2-chain-id: 196 +zkevm.l2-sequencer-rpc-url: https://rpc.xlayer.tech +zkevm.l2-datastreamer-url: stream.xlayer.tech:8800 +zkevm.l1-chain-id: 1 +# `zkevm.l1-rpc-url` must be changed before running. +# using a wrong default value so it can report and error and remind you to change this value. +zkevm.l1-rpc-url: https://rpc.ankr.com/eth/ +#zkevm.increment-tree-always: true + +#debug.limit: 8554110 + +zkevm.sequencer-block-seal-time: "1s" +zkevm.sequencer-max-block-seal-time: "3s" +zkevm.sequencer-batch-seal-time: "10s" +zkevm.sequencer-batch-sleep-duration: "0s" + +zkevm.data-stream-host: "localhost" +zkevm.data-stream-port: 6900 +zkevm.default-gas-price: 1 +zkevm.max-gas-price: 0 +zkevm.gas-price-factor: 0.000001 +zkevm.allow-free-transactions: true + +txpool.packbatchspeciallist : ["0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", "0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534", "0xa03666Fb51Aa9aD2DE70e0434072A007b3C91A9E"] +txpool.globalslots: 1000000 +txpool.globalbasefeeslots: 1000000 +txpool.globalqueue: 1000000 +txpool.commit.every: "10m" + +zkevm.address-sequencer: "0xAF9d27ffe4d51eD54AC8eEc78f2785D7E11E5ab1" +zkevm.address-zkevm: "0x2B0ee28D4D51bC9aDde5E58E295873F61F4a0507" +zkevm.address-rollup: "0x5132A183E9F3CB7C848b0AAC5Ae0c4f0491B7aB2" +zkevm.address-ger-manager: "0x580bda1e7A0CFAe92Fa7F6c20A3794F169CE3CFb" + +zkevm.l1-rollup-id: 3 +zkevm.l1-first-block: 19218658 +zkevm.l1-block-range: 2000 +zkevm.l1-query-delay: 1000 +zkevm.datastream-version: 3 + +http.api: [eth, debug, net, trace, web3, erigon, txpool, zkevm] +http.addr: 0.0.0.0 +http.port: 8545 + +gpo.type: "follower" +gpo.update-period: "300s" +gpo.factor: 0.01 +gpo.kafka-url: "0.0.0.0" +gpo.topic: "explorer" +gpo.group-id: "web3" +gpo.blocks: 3 +gpo.default-l1-coin-price: 2000 +gpo.default-l2-coin-price: 50 +gpo.gas-price-usdt: 0.000000476190476 +gpo.congestion-threshold: 0 + +pprof: true +pprof.port: 6060 +pprof.addr: 0.0.0.0 + +metrics: true +metrics.addr: "0.0.0.0" +metrics.port: 9095 + +yieldsize: 35 +zkevm.seal-batch-immediately-on-overflow: true +zkevm.sequencer-timeout-on-empty-tx-pool: 1ms +zkevm.pre-run-address-list: [""] +zkevm.block-info-concurrent: true +zkevm.standalone-smt-db: true +zkevm.enable-async-commit: true + +# to reduce lock race in stress test +txpool.enabletimsort: true +zkevm.bulk-add-txs: true +zkevm.enable-add-tx-notify: true + +#zkevm.verification-batch-delay: 2 +#zkevm.skip-analysis-group-api: true +# zkevm.analysis-group-nacos-urls: "url1:80,url2:80" +# zkevm.analysis-group-nacos-namespace: "ns-global" +# zkevm.analysis-group-service-name: "analysis-group" +# zkevm.analysis-group-api-path: "api/v1/196/validHeight" diff --git a/test-pp-op/contracts/OKBToken.sol b/test-pp-op/contracts/OKBToken.sol new file mode 100644 index 0000000000000..7e9344d091bb3 --- /dev/null +++ b/test-pp-op/contracts/OKBToken.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +interface IERC20 { + function totalSupply() external view returns (uint256); + function balanceOf(address account) external view returns (uint256); + function transfer(address to, uint256 amount) external returns (bool); + function allowance(address owner, address spender) external view returns (uint256); + function approve(address spender, uint256 amount) external returns (bool); + function transferFrom(address from, address to, uint256 amount) external returns (bool); + + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval(address indexed owner, address indexed spender, uint256 value); +} + +contract StandardERC20 is IERC20 { + string public name; + string public symbol; + uint8 public constant decimals = 18; + uint256 private _totalSupply; + + mapping(address => uint256) private _balances; + mapping(address => mapping(address => uint256)) private _allowances; + + constructor( + string memory _name, + string memory _symbol, + uint256 _initialSupply + ) { + name = _name; + symbol = _symbol; + _totalSupply = _initialSupply * 10**decimals; + _balances[msg.sender] = _totalSupply; + emit Transfer(address(0), msg.sender, _totalSupply); + } + + function totalSupply() public view override returns (uint256) { + return _totalSupply; + } + + function balanceOf(address account) public view override returns (uint256) { + return _balances[account]; + } + + function transfer(address to, uint256 amount) public override returns (bool) { + require(to != address(0), "ERC20: transfer to zero address"); + require(_balances[msg.sender] >= amount, "ERC20: insufficient balance"); + + _balances[msg.sender] -= amount; + _balances[to] += amount; + + emit Transfer(msg.sender, to, amount); + return true; + } + + function allowance(address owner, address spender) public view override returns (uint256) { + return _allowances[owner][spender]; + } + + function approve(address spender, uint256 amount) public override returns (bool) { + require(spender != address(0), "ERC20: approve to zero address"); + + _allowances[msg.sender][spender] = amount; + emit Approval(msg.sender, spender, amount); + return true; + } + + function transferFrom(address from, address to, uint256 amount) public override returns (bool) { + require(from != address(0), "ERC20: transfer from zero address"); + require(to != address(0), "ERC20: transfer to zero address"); + require(_balances[from] >= amount, "ERC20: insufficient balance"); + require(_allowances[from][msg.sender] >= amount, "ERC20: insufficient allowance"); + + _balances[from] -= amount; + _balances[to] += amount; + _allowances[from][msg.sender] -= amount; + + emit Transfer(from, to, amount); + return true; + } + + function mint(address to, uint256 amount) public { + require(to != address(0), "ERC20: mint to zero address"); + + _totalSupply += amount; + _balances[to] += amount; + emit Transfer(address(0), to, amount); + } + + function burn(uint256 amount) public { + require(_balances[msg.sender] >= amount, "ERC20: insufficient balance"); + + _balances[msg.sender] -= amount; + _totalSupply -= amount; + emit Transfer(msg.sender, address(0), amount); + } +} diff --git a/test-pp-op/contracts/Transactor.sol b/test-pp-op/contracts/Transactor.sol new file mode 100644 index 0000000000000..e193db31e024f --- /dev/null +++ b/test-pp-op/contracts/Transactor.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// Contracts +import { Owned } from "@rari-capital/solmate/src/auth/Owned.sol"; + +/// @title Transactor +/// @notice Transactor is a minimal contract that can send transactions. +contract Transactor is Owned { + /// @param _owner Initial contract owner. + constructor(address _owner) Owned(_owner) { } + + /// @notice Sends a CALL to a target address. + /// @param _target Address to call. + /// @param _data Data to send with the call. + /// @param _value ETH value to send with the call. + /// @return success_ Boolean success value. + /// @return data_ Bytes data returned by the call. + function CALL( + address _target, + bytes memory _data, + uint256 _value + ) + external + payable + onlyOwner + returns (bool success_, bytes memory data_) + { + (success_, data_) = _target.call{ value: _value }(_data); + require(success_, "Transactor: CALL failed"); + } + + /// @notice Sends a DELEGATECALL to a target address. + /// @param _target Address to call. + /// @param _data Data to send with the call. + /// @return success_ Boolean success value. + /// @return data_ Bytes data returned by the call. + function DELEGATECALL( + address _target, + bytes memory _data + ) + external + payable + onlyOwner + returns (bool success_, bytes memory data_) + { + // slither-disable-next-line controlled-delegatecall + (success_, data_) = _target.delegatecall(_data); + require(success_, "Transactor: DELEGATECALL failed"); + } +} diff --git a/test-pp-op/contracts/foundry.toml b/test-pp-op/contracts/foundry.toml new file mode 100644 index 0000000000000..27db5c056c5a9 --- /dev/null +++ b/test-pp-op/contracts/foundry.toml @@ -0,0 +1,9 @@ +[profile.default] +src = "." +out = "../tmp/OKB/out" +cache_path = "../tmp/OKB/cache" +libs = ["lib"] +solc_version = "0.8.19" + +[rpc_endpoints] +local = "http://127.0.0.1:8545" diff --git a/test-pp-op/docker-compose-local.yml b/test-pp-op/docker-compose-local.yml new file mode 100644 index 0000000000000..34f1d842c85e5 --- /dev/null +++ b/test-pp-op/docker-compose-local.yml @@ -0,0 +1,925 @@ +networks: + default: + name: pp-op + +services: + l1-geth-remove-db: + image: "alpine:3.19.0" + container_name: l1-geth-remove-db + command: rm -rf /execution/geth + volumes: + - ./l1-geth/execution:/execution + + l1-beacon-remove-db: + image: "alpine:3.19.0" + container_name: l1-beacon-remove-db + command: rm -rf /consensus/beacondata /consensus/validatordata /consensus/genesis.ssz + volumes: + - ./l1-geth/consensus:/consensus + + l1-create-beacon-chain-genesis: + image: "gcr.io/prysmaticlabs/prysm/cmd/prysmctl:v5.1.2" + container_name: l1-create-beacon-chain-genesis + command: + - testnet + - generate-genesis + - --fork=deneb + - --num-validators=4 + - --genesis-time-delay=0 + - --output-ssz=/consensus/genesis.ssz + - --chain-config-file=/consensus/config.yml + - --geth-genesis-json-in=/execution/genesis-raw.json + - --geth-genesis-json-out=/execution/genesis.json + volumes: + - ./l1-geth/consensus:/consensus + - ./l1-geth/execution:/execution + depends_on: + l1-beacon-remove-db: + condition: service_completed_successfully + + l1-fix-genesis-fork-times: + image: "alpine:3.19.0" + container_name: l1-fix-genesis-fork-times + command: + - /bin/sh + - -c + - | + apk add --no-cache jq + echo "Fixing genesis.json fork times..." + sed -i 's/"shanghaiTime": [0-9]*/"shanghaiTime": 0/g' /execution/genesis.json + sed -i 's/"cancunTime": [0-9]*/"cancunTime": 0/g' /execution/genesis.json + echo "Adding blobSchedule for Cancun..." + jq '.config.blobSchedule = {"cancun": {"target": 3, "max": 6, "baseFeeUpdateFraction": 3338477}}' /execution/genesis.json > /tmp/genesis.json && mv /tmp/genesis.json /execution/genesis.json + echo "Removing terminalTotalDifficultyPassed for op-node compatibility..." + jq 'del(.config.terminalTotalDifficultyPassed)' /execution/genesis.json > /tmp/genesis.json && mv /tmp/genesis.json /execution/genesis.json + echo "Genesis.json: shanghai=0, cancun=0 (MCOPY enabled), blobSchedule added, terminalTotalDifficultyPassed removed" + cat /execution/genesis.json | jq '.config | {shanghaiTime, cancunTime, terminalTotalDifficulty, blobSchedule}' + volumes: + - ./l1-geth/execution:/execution + depends_on: + l1-create-beacon-chain-genesis: + condition: service_completed_successfully + + l1-geth-genesis: + image: "ethereum/client-go:v1.15.11" + container_name: l1-geth-genesis + command: --datadir=/execution --gcmode=archive init --state.scheme=hash /execution/genesis.json + volumes: + - ./l1-geth/execution:/execution + - ./l1-geth/execution/genesis.json:/execution/genesis.json + depends_on: + l1-fix-genesis-fork-times: + condition: service_completed_successfully + l1-geth-remove-db: + condition: service_completed_successfully + + l1-geth: + image: "ethereum/client-go:v1.15.11" + container_name: l1-geth + command: + - --http + - --http.api=eth,net,web3,debug,admin + - --http.addr=0.0.0.0 + - --http.corsdomain=* + - --http.vhosts=* + - --ws + - --ws.api=eth,net,web3,debug + - --ws.addr=0.0.0.0 + - --ws.origins=* + - --authrpc.vhosts=* + - --authrpc.addr=0.0.0.0 + - --authrpc.jwtsecret=/execution/jwtsecret + - --datadir=/execution + - --allow-insecure-unlock + - --unlock=0x123463a4b065722e99115d6c222f267d9cabb524 + - --password=/execution/geth_password.txt + - --nodiscover + - --syncmode=full + - --gcmode=archive + - --ipcdisable + - --rpc.allow-unprotected-txs + - --verbosity=3 + ports: + - 8551:8551 + - 8545:8545 + - 8546:8546 + depends_on: + l1-geth-genesis: + condition: service_completed_successfully + volumes: + - ./l1-geth/execution:/execution + - ./l1-geth/execution/jwtsecret:/execution/jwtsecret + - ./l1-geth/execution/geth_password.txt:/execution/geth_password.txt + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8545"] + interval: 10s + timeout: 5s + retries: 5 + + l1-beacon-chain: + image: "gcr.io/prysmaticlabs/prysm/beacon-chain:v5.1.2" + container_name: l1-beacon-chain + command: + - --datadir=/consensus/beacondata + - --min-sync-peers=0 + - --genesis-state=/consensus/genesis.ssz + - --bootstrap-node= + - --interop-eth1data-votes + - --chain-config-file=/consensus/config.yml + - --contract-deployment-block=0 + - --chain-id=${CHAIN_ID:-1337} + - --rpc-host=0.0.0.0 + - --grpc-gateway-host=0.0.0.0 + - --execution-endpoint=http://l1-geth:8551 + - --accept-terms-of-use + - --jwt-secret=/execution/jwtsecret + - --suggested-fee-recipient=0x123463a4b065722e99115d6c222f267d9cabb524 + - --minimum-peers-per-subnet=0 + - --enable-debug-rpc-endpoints + - --verbosity=info + depends_on: + l1-create-beacon-chain-genesis: + condition: service_completed_successfully + l1-geth: + condition: service_healthy + ports: + - 4000:4000 + - 3500:3500 + - 18080:8080 + - 6060:6060 + - 19090:9090 + volumes: + - ./l1-geth/consensus:/consensus + - ./l1-geth/execution:/execution + - ./l1-geth/execution/jwtsecret:/execution/jwtsecret + + l1-validator: + image: "gcr.io/prysmaticlabs/prysm/validator:v5.1.2" + container_name: l1-validator + command: + - --beacon-rpc-provider=l1-beacon-chain:4000 + - --datadir=/consensus/validatordata + - --accept-terms-of-use + - --interop-num-validators=4 + - --interop-start-index=0 + - --chain-config-file=/consensus/config.yml + - --verbosity=info + depends_on: + l1-beacon-chain: + condition: service_started + volumes: + - ./l1-geth/consensus:/consensus + + xlayer-approve: + container_name: xlayer-approve + image: hermeznetwork/zkevm-node:v0.6.6 + volumes: + - ./keystore/sequencer.keystore:/pk/keystore + - ./config/test.node.config.toml:/app/config.toml + - ./config/test.genesis.config.json:/app/genesis.json + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-node approve --network custom --custom-network-file /app/genesis.json --key-store-path /pk/keystore --pw testonly --am 115792089237316195423570985008687907853269984665640564039457584007913129639935 -y --cfg /app/config.toml" + + xlayer-seq: + container_name: xlayer-seq + image: cdk-erigon + environment: + - CDK_ERIGON_SEQUENCER=1 + - WRITE_MAP=true + ports: + - 6062:6060 + - 8123:8545 + - 6900:6900 + - 9092:9095 + volumes: + - ./data/seq/:/home/erigon/data/ + - ./config/test.erigon.seq.config.yaml:/usr/src/app/config.yaml + - ./config/first-batch-config.json:/usr/src/app/first-batch-config.json + - ./config/dynamic-mynetwork-allocs.json:/usr/src/app/dynamic-mynetwork-allocs.json + - ./config/dynamic-mynetwork-chainspec.json:/usr/src/app/dynamic-mynetwork-chainspec.json + - ./config/dynamic-mynetwork-conf.json:/usr/src/app/dynamic-mynetwork-conf.json + command: > + cdk-erigon --http.vhosts=* --http.corsdomain=* --ws --config=/usr/src/app/config.yaml + + xlayer-mainnet-seq: + container_name: xlayer-seq + image: cdk-erigon + environment: + - CDK_ERIGON_SEQUENCER=1 + - WRITE_MAP=true + ports: + - 6062:6060 + - 8123:8545 + - 6900:6900 + - 9092:9095 + volumes: + - ./mainnet/seq:/home/erigon/data/ + - ./config/xlayerconfig-mainnet.yaml:/usr/src/app/config.yaml + command: > + cdk-erigon --http.vhosts=* --http.corsdomain=* --ws --config=/usr/src/app/config.yaml + + xlayer-bridge-db: + container_name: xlayer-bridge-db + image: postgres:15 + deploy: + resources: + limits: + memory: 2G + reservations: + memory: 1G + ports: + - 5439:5432 + environment: + - POSTGRES_USER=test_user + - POSTGRES_PASSWORD=test_password + - POSTGRES_DB=test_db + command: [ "postgres", "-N", "500" ] + + xlayer-bridge-service: + container_name: xlayer-bridge-service + image: ${XLAYER_BRIDGE_SERVICE_IMAGE_TAG} + ports: + - 8080:8080 + - 9090:9090 + environment: + - ZKEVM_BRIDGE_DATABASE_USER=test_user + - ZKEVM_BRIDGE_DATABASE_PASSWORD=test_password + - ZKEVM_BRIDGE_DATABASE_NAME=test_db + - ZKEVM_BRIDGE_DATABASE_HOST=xlayer-bridge-db + - ZKEVM_BRIDGE_DATABASE_PORT=5432 + volumes: + - ./keystore/sequencer.keystore:/pk/keystore.claimtxmanager + - ./config/test.bridge.config.toml:/app/config.toml + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-bridge run --cfg /app/config.toml" + + xlayer-bridge-ui: + container_name: xlayer-bridge-ui + image: hermeznetwork/zkevm-bridge-ui:latest + ports: + - 8090:80 + environment: + - ETHEREUM_RPC_URL=http://127.0.0.1:8545 + - ETHEREUM_EXPLORER_URL=http://127.0.0.1:4000 + - ETHEREUM_ROLLUP_MANAGER_ADDRESS=0xE96dBF374555C6993618906629988d39184716B3 + - ETHEREUM_BRIDGE_CONTRACT_ADDRESS=0xb2fAc1CE54bb9BF77A7FE106fA69F81453b72851 + - ETHEREUM_FORCE_UPDATE_GLOBAL_EXIT_ROOT=true + - ETHEREUM_PROOF_OF_EFFICIENCY_CONTRACT_ADDRESS=0xE45CCD0757670580a4a3600DE5cef1e45F0Ec2bd + - POLYGON_ZK_EVM_RPC_URL=http://127.0.0.1:8123 + - POLYGON_ZK_EVM_EXPLORER_URL=http://127.0.0.1:4001 + - POLYGON_ZK_EVM_BRIDGE_CONTRACT_ADDRESS=0xb2fAc1CE54bb9BF77A7FE106fA69F81453b72851 + - POLYGON_ZK_EVM_NETWORK_ID=1 + - BRIDGE_API_URL=http://127.0.0.1:8080 + - ENABLE_FIAT_EXCHANGE_RATES=false + - ENABLE_OUTDATED_NETWORK_MODAL=false + - ENABLE_DEPOSIT_WARNING=false + - ENABLE_REPORT_FORM=false + - RESOLVE_RELATIVE_URLS=false + + xlayer-pool-db: + container_name: xlayer-pool-db + image: postgres:15 + ports: + - 5440:5432 + volumes: + - /var/lib/postgresql/data + environment: + - POSTGRES_USER=pool_user + - POSTGRES_PASSWORD=pool_password + - POSTGRES_DB=pool_db + command: + - "postgres" + - "-N" + - "500" + + xlayer-pool-manager: + container_name: xlayer-pool-manager + image: hermeznetwork/zkevm-pool-manager:v0.1.2 + deploy: + resources: + limits: + memory: 1G + reservations: + memory: 512M + ports: + - 8125:8545 + volumes: + - ./config/test.poolmanager.toml:/app/poolmanager.toml + command: + - "/bin/sh" + - "-c" + - "/app/zkevm-pool-manager run --cfg /app/poolmanager.toml" + + xlayer-agg-sender: + container_name: xlayer-agg-sender + image: aggkit:local + restart: on-failure + volumes: + - ./data/cdk-node:/tmp + - ./keystore/aggregator.keystore:/etc/aggkit/aggregator.keystore + - ./keystore/sequencer.keystore:/etc/aggkit/sequencer.keystore + - ./config/aggkit.toml:/etc/aggkit/aggkit.toml + - ./config/test.genesis.config.json:/etc/aggkit/genesis.json + ports: + - 5576:5576 + command: ["run", "--cfg=/etc/aggkit/aggkit.toml", "--components=aggsender"] + + xlayer-agglayer: + container_name: xlayer-agglayer + image: zjg555543/agglayer:upstream-v0.3.3 + ports: + - 4443:4443 + - 4444:4444 + - 4446:4446 + - 9094:9092 + volumes: + - ./keystore/agglayer.keystore:/etc/zkevm/agglayer.keystore + - ./config/agglayer-config.toml:/etc/zkevm/agglayer-config.toml + - ./data/agglayer/storage:/etc/zkevm/storage/ + - ./data/agglayer/backups:/etc/zkevm/backups/ + command: + - "/bin/sh" + - "-c" + - "/usr/local/bin/agglayer run --cfg /etc/zkevm/agglayer-config.toml" + + xlayer-agglayer-prover: + container_name: xlayer-agglayer-prover + image: zjg555543/agglayer:upstream-v0.3.3 + volumes: + - ./config/agglayer-prover-config.toml:/etc/zkevm/agglayer-prover-config.toml + ports: + - 4445:4445 + - 9093:9093 + command: + - "/bin/sh" + - "-c" + - "/usr/local/bin/agglayer prover --cfg /etc/zkevm/agglayer-prover-config.toml" + + xlayer-agg-db: + container_name: xlayer-agg-db + image: postgres:15 + deploy: + resources: + limits: + memory: 2G + reservations: + memory: 1G + ports: + - 5434:5432 + environment: + - POSTGRES_USER=aggregator_user + - POSTGRES_PASSWORD=aggregator_password + - POSTGRES_DB=aggregator_db + command: + - "postgres" + - "-N" + - "500" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U aggregator_user -d aggregator_db"] + interval: 5s + timeout: 5s + retries: 5 + start_period: 5s + + xlayer-rpc: + container_name: xlayer-rpc + image: cdk-erigon + environment: + - CDK_ERIGON_SEQUENCER=0 + - WRITE_MAP=true + ports: + - 16061:6060 + - 18124:8545 + - 16901:6900 + - 19091:9095 + volumes: + - ./data/rpc/:/home/erigon/data/ + - ./config/test.erigon.rpc.config.yaml:/usr/src/app/config.yaml + - ./config/first-batch-config.json:/usr/src/app/first-batch-config.json + - ./config/dynamic-mynetwork-allocs.json:/usr/src/app/dynamic-mynetwork-allocs.json + - ./config/dynamic-mynetwork-chainspec.json:/usr/src/app/dynamic-mynetwork-chainspec.json + - ./config/dynamic-mynetwork-conf.json:/usr/src/app/dynamic-mynetwork-conf.json + command: > + cdk-erigon --http.vhosts=* --http.corsdomain=* --ws --config=/usr/src/app/config.yaml + xlayer-oracle: + container_name: xlayer-oracle + image: aggkit:local + volumes: + - ./data/oracle:/tmp + - ./keystore/aggoracle.keystore:/etc/aggkit/aggoracle.keystore + - ./config-op/aggkit.toml:/etc/aggkit/aggkit.toml + - ./config/test.genesis.config.json:/etc/aggkit/genesis.json + ports: + - 15576:5576 + command: ["run", "--cfg=/etc/aggkit/aggkit.toml", "--components=aggoracle"] + op-geth-seq: + image: "${OP_GETH_IMAGE_TAG}" + container_name: op-geth-seq + entrypoint: geth + volumes: + - ./data/op-geth-seq:/datadir + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/test.seq.config.toml:/config.toml + ports: + - "8123:8545" + - "7546:7546" + - "8552:8552" + - "30303:30303" + - "30303:30303/udp" + - "9090:9090" # pprof port + command: + - --verbosity=3 + - --datadir=/datadir + - --db.engine=${DB_ENGINE} + - --config=/config.toml + - --gcmode=archive + - --rollup.disabletxpoolgossip=false + - --pp-rpc-legacy-header-sync-rate-limit=10000 + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-geth-rpc: + image: "${OP_GETH_IMAGE_TAG}" + container_name: op-geth-rpc + entrypoint: geth + volumes: + - ./data/op-geth-rpc:/datadir + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/test.rpc.config.toml:/config.toml + ports: + - "8124:8545" + - "30304:30303" + - "30304:30303/udp" + command: + - --verbosity=3 + - --datadir=/datadir + - --db.engine=${DB_ENGINE} + - --config=/config.toml + - --gcmode=archive + # - --rollup.sequencerhttp=http://op-geth-seq:8545 + - --rollup.enabletxpooladmission + - --pp-rpc-legacy-header-sync-rate-limit=10000 + + op-seq: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-seq + volumes: + - ./config-op/rollup.json:/rollup.json + - ./config-op/jwt.txt:/jwt.txt + - ./data/op-seq:/data + - ./l1-geth/execution/:/l1/ + ports: + - "9545:9545" + - "7070:7070" + - "9223:9223" + - "9223:9223/udp" + - "9091:9091" # pprof port + command: + - /app/op-node/bin/op-node + - --log.level=debug + - --l2=http://op-geth-seq:8552 + - --l2.jwt-secret=/jwt.txt + - --sequencer.enabled + - --sequencer.l1-confs=5 + - --verifier.l1-confs=1 + - --rollup.config=/rollup.json + - --rpc.addr=0.0.0.0 + - --p2p.listen.tcp=9223 + - --p2p.listen.udp=9223 + - --p2p.priv.raw=e054b5748fb29a82994ea170af9e6094a163a0d11308dea91a38744c4e7c94da + - --p2p.peerstore.path=/data/p2p/opnode_peerstore_db + - --p2p.discovery.path=/data/p2p/opnode_discovery_db + - --p2p.no-discovery + - --rpc.enable-admin + - --p2p.sequencer.key=${SEQUENCER_P2P_KEY} + - --l1=${L1_RPC_URL_IN_DOCKER} + - --l1.beacon=${L1_BEACON_URL_IN_DOCKER} + - --l1.rpckind=standard + - --rollup.l1-chain-config=/l1/genesis.json + - --safedb.path=/data/safedb + - --conductor.enabled=${CONDUCTOR_ENABLED:-false} # ้ป˜่ฎคๅ…ณ้—ญ + - --conductor.rpc=http://op-conductor:8547 + - --pprof.enabled + - --pprof.addr=0.0.0.0 + - --pprof.port=9091 + depends_on: + op-geth-seq: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-rpc: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-rpc + volumes: + - ./data/op-rpc:/data + - ./config-op/rollup.json:/rollup.json + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/oprpc_p2p_priv.txt:/opnode_p2p_priv.txt + - ./l1-geth/execution/:/l1 + ports: + - "9555:9545" + command: + - /app/op-node/bin/op-node + - --log.level=debug + - --l2=http://op-geth-rpc:8552 + - --l2.jwt-secret=/jwt.txt + - --sequencer.enabled=false + - --verifier.l1-confs=1 + - --rollup.config=/rollup.json + - --rpc.addr=0.0.0.0 + - --rpc.port=9545 + - --p2p.listen.tcp=9223 + - --p2p.listen.udp=9223 + - --p2p.priv.raw=604557d042fbea9ed42f46c0c95c346a932b6a5ef0c0dd07a00dbf95801a2510 + - --p2p.peerstore.path=/data/p2p/opnode_peerstore_db + - --p2p.discovery.path=/data/p2p/opnode_discovery_db + - --p2p.static=/dns4/op-seq/tcp/9223/p2p/16Uiu2HAkzHdkbmS2VrCsccLibsu7MvGHpmFUMJnMTkKifrtS5m65 + - --p2p.no-discovery + - --rpc.enable-admin=true + - --l1=${L1_RPC_URL_IN_DOCKER} + - --l1.beacon=${L1_BEACON_URL_IN_DOCKER} + - --l1.rpckind=standard + - --rollup.l1-chain-config=/l1/genesis.json + - --safedb.path=/data/safedb + - --pp-rpc-url=${PP_RPC_URL} + depends_on: + - op-geth-rpc + + op-conductor: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-conductor + volumes: + - ./data/op-conductor:/data + - ./config-op/rollup.json:/rollup.json + ports: + - "8547:8547" # RPC port +# - "50050:50050" # Consensus port + command: + - /app/op-conductor/bin/op-conductor + - --log.level=debug + # already existed service + - --node.rpc=http://op-seq:9545 + - --execution.rpc=http://op-geth-seq:8545 + # Raft Config + - --raft.server.id=conductor-1 + - --raft.storage.dir=/data/raft + - --raft.bootstrap=true + - --consensus.addr=0.0.0.0 + - --consensus.port=50050 + - --consensus.advertised=op-conductor:50050 + # RPC Config + - --rpc.addr=0.0.0.0 + - --rpc.port=8547 + - --rpc.enable-proxy=true + # Healthcheck Config + - --healthcheck.interval=1 + - --healthcheck.unsafe-interval=3 + - --healthcheck.min-peer-count=1 + - --rollup.config=/rollup.json + depends_on: + op-seq: + condition: service_healthy + op-geth-seq: + condition: service_healthy + + op-batcher: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-batcher + command: + - /app/op-batcher/bin/op-batcher + - --log.level=debug + - --l2-eth-rpc=${OP_BATCHER_L2_ETH_RPC:-http://op-geth-seq:8545} + - --rollup-rpc=${OP_BATCHER_ROLLUP_RPC:-http://op-seq:9545} + - --wait-node-sync=true + - --check-recent-txs-depth=5 + - --poll-interval=5s + - --batch-type=1 + - --compression-algo=brotli-11 + - --data-availability-type=auto + - --max-channel-duration=30 + - --target-num-frames=5 + - --sub-safety-margin=6 + - --num-confirmations=4 + - --network-timeout=10s + - --safe-abort-nonce-too-low-count=3 + - --max-pending-tx=10 + - --resubmission-timeout=30s + - --rpc.addr=0.0.0.0 + - --rpc.port=8548 + - --rpc.enable-admin + - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} + - --private-key=${OP_BATCHER_PRIVATE_KEY} + - --throttle.block-size-upper-limit=1300000 + - --active-sequencer-check-duration=5s + + op-proposer: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-proposer + environment: + - DISPUTE_GAME_FACTORY_ADDRESS=${DISPUTE_GAME_FACTORY_ADDRESS} + command: + - /app/op-proposer/bin/op-proposer + - --log.level=debug + - --poll-interval=20s + - --wait-node-sync=true + - --allow-non-finalized=false + - --num-confirmations=1 + - --safe-abort-nonce-too-low-count=3 + - --resubmission-timeout=30s + - --rpc.port=8560 + - --rollup-rpc=http://op-rpc:9545 + - --game-factory-address=${DISPUTE_GAME_FACTORY_ADDRESS} + - --proposal-interval=1m + - --private-key=${OP_PROPOSER_PRIVATE_KEY} + - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} + - --game-type=${GAME_TYPE:-0} + - --allow-non-finalized + - --genesis-height=${FORK_BLOCK} + depends_on: + - op-batcher + + op-challenger: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-challenger + environment: + - L1_RPC_URL_IN_DOCKER=${L1_RPC_URL_IN_DOCKER} + - L1_BEACON_URL_IN_DOCKER=${L1_BEACON_URL_IN_DOCKER} + - DISPUTE_GAME_FACTORY_ADDRESS=${DISPUTE_GAME_FACTORY_ADDRESS} + volumes: + - ./data/cannon-data:/data + - ./config-op/rollup.json:/rollup.json + - ./config-op/genesis.json:/l2-genesis.json + depends_on: + - op-seq + command: + - /app/op-challenger/bin/op-challenger + - --log.level=debug + - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} + - --l1-beacon=${L1_BEACON_URL_IN_DOCKER} + - --l2-eth-rpc=http://op-geth-rpc:8545 + - --rollup-rpc=http://op-rpc:9545 + - --game-factory-address=${DISPUTE_GAME_FACTORY_ADDRESS} + - --cannon-bin=/app/cannon/bin/cannon + - --cannon-server=/data/op-program + - --cannon-prestate=/data/prestate-mt64.bin.gz + - --cannon-rollup-config=/rollup.json + - --cannon-l2-genesis=/l2-genesis.json + - --private-key=${OP_PROPOSER_PRIVATE_KEY} + - --trace-type=cannon,permissioned + - --datadir=/data + - --game-window=${GAME_WINDOW}s + + op-dispute-mon: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-dispute-mon + depends_on: + - op-challenger + - op-proposer + command: + - /app/op-dispute-mon/bin/op-dispute-mon + - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} + - --rollup-rpc=http://op-rpc:9545 + - --game-factory-address=${DISPUTE_GAME_FACTORY_ADDRESS} + - --game-window=${GAME_WINDOW}s + - --honest-actors=${PROPOSER_ADDRESS} + + op-geth-seq2: + image: "${OP_GETH_IMAGE_TAG}" + container_name: op-geth-seq2 + entrypoint: geth + volumes: + - ./data/op-geth-seq2:/datadir + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/test.seq.config.toml:/config.toml + ports: + - "8223:8545" + - "30305:30303" + - "30305:30303/udp" + command: + - --verbosity=3 + - --datadir=/datadir + - --db.engine=${DB_ENGINE} + - --config=/config.toml + - --gcmode=archive + - --rollup.disabletxpoolgossip=false + - --pp-rpc-legacy-header-sync-rate-limit=10000 + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-seq2: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-seq2 + volumes: + - ./config-op/rollup.json:/rollup.json + - ./config-op/jwt.txt:/jwt.txt + - ./data/op-seq2:/data + - ./l1-geth/execution/:/l1/ + ports: + - "9546:9545" + # - "7070:7070" + - "9224:9223" + - "9224:9223/udp" + command: + - /app/op-node/bin/op-node + - --log.level=info + - --l2=http://op-geth-seq2:8552 + - --l2.jwt-secret=/jwt.txt + - --sequencer.enabled + - --sequencer.stopped + - --sequencer.l1-confs=5 + - --verifier.l1-confs=1 + - --rollup.config=/rollup.json + - --rpc.addr=0.0.0.0 + - --p2p.listen.tcp=9223 + - --p2p.listen.udp=9223 + - --p2p.priv.raw=cff9dac7588f5e6755a72d1e5b5001da3d0f8c06c4242b27d67eb5df4216bd93 + - --p2p.peerstore.path=/data/p2p/opnode_peerstore_db + - --p2p.discovery.path=/data/p2p/opnode_discovery_db + - --p2p.static=/dns4/op-seq/tcp/9223/p2p/16Uiu2HAkzHdkbmS2VrCsccLibsu7MvGHpmFUMJnMTkKifrtS5m65,/dns4/op-seq3/tcp/9223/p2p/16Uiu2HAmRDGMm3UUrP8CfQ3YQo9aaXEXFXA7LeFNztdPMNK5moyD + - --p2p.no-discovery + - --rpc.enable-admin + - --p2p.sequencer.key=${SEQUENCER_P2P_KEY} + - --l1=${L1_RPC_URL_IN_DOCKER} + - --l1.beacon=${L1_BEACON_URL_IN_DOCKER} + - --l1.rpckind=standard + - --rollup.l1-chain-config=/l1/genesis.json + - --safedb.path=/data/safedb + - --conductor.enabled=${CONDUCTOR_ENABLED:-false} + - --conductor.rpc=http://op-conductor2:8547 + depends_on: + op-geth-seq2: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-conductor2: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-conductor2 + volumes: + - ./data/op-conductor2:/data + - ./config-op/rollup.json:/rollup.json + ports: + - "8548:8547" # RPC port +# - "50051:50050" # Consensus port + command: + - /app/op-conductor/bin/op-conductor + - --log.level=debug + # already existed service + - --node.rpc=http://op-seq2:9545 + - --execution.rpc=http://op-geth-seq2:8545 + # Raft Config + - --raft.server.id=conductor-2 + - --raft.storage.dir=/data/raft + - --raft.bootstrap=false + - --consensus.addr=0.0.0.0 + - --consensus.port=50050 + - --consensus.advertised=op-conductor2:50050 + # RPC Config + - --rpc.addr=0.0.0.0 + - --rpc.port=8547 + - --rpc.enable-proxy=true + # Healthcheck Config + - --healthcheck.interval=1 + - --healthcheck.unsafe-interval=3 + - --healthcheck.min-peer-count=1 + - --rollup.config=/rollup.json + depends_on: + op-seq2: + condition: service_healthy + op-geth-seq2: + condition: service_healthy + + op-geth-seq3: + image: "${OP_GETH_IMAGE_TAG}" + container_name: op-geth-seq3 + entrypoint: geth + volumes: + - ./data/op-geth-seq3:/datadir + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/test.seq.config.toml:/config.toml + ports: + - "8323:8545" + - "30306:30303" + - "30306:30303/udp" + command: + - --verbosity=3 + - --datadir=/datadir + - --db.engine=${DB_ENGINE} + - --config=/config.toml + - --gcmode=archive + - --rollup.disabletxpoolgossip=false + - --pp-rpc-legacy-header-sync-rate-limit=10000 + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-seq3: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-seq3 + volumes: + - ./config-op/rollup.json:/rollup.json + - ./config-op/jwt.txt:/jwt.txt + - ./data/op-seq3:/data + - ./l1-geth/execution/:/l1/ + ports: + - "9547:9545" + # - "7070:7070" + - "9225:9223" + - "9225:9223/udp" + command: + - /app/op-node/bin/op-node + - --log.level=info + - --l2=http://op-geth-seq3:8552 + - --l2.jwt-secret=/jwt.txt + - --sequencer.enabled + - --sequencer.stopped + - --sequencer.l1-confs=5 + - --verifier.l1-confs=1 + - --rollup.config=/rollup.json + - --rpc.addr=0.0.0.0 + - --p2p.listen.tcp=9223 + - --p2p.listen.udp=9223 + - --p2p.priv.raw=10785157e7c98628e5e47c3d9b8ebbd12525c45f1554b4a39652b5ce02bb29dc + - --p2p.peerstore.path=/data/p2p/opnode_peerstore_db + - --p2p.discovery.path=/data/p2p/opnode_discovery_db + - --p2p.static=/dns4/op-seq/tcp/9223/p2p/16Uiu2HAkzHdkbmS2VrCsccLibsu7MvGHpmFUMJnMTkKifrtS5m65,/dns4/op-seq2/tcp/9223/p2p/16Uiu2HAmDTjVuEF6V9DccV1JhrHg7DYc5SKm3bw2T75kAFPsGuSp + - --p2p.no-discovery + - --rpc.enable-admin + - --p2p.sequencer.key=${SEQUENCER_P2P_KEY} + - --l1=${L1_RPC_URL_IN_DOCKER} + - --l1.beacon=${L1_BEACON_URL_IN_DOCKER} + - --l1.rpckind=standard + - --rollup.l1-chain-config=/l1/genesis.json + - --safedb.path=/data/safedb + - --conductor.enabled=${CONDUCTOR_ENABLED:-false} + - --conductor.rpc=http://op-conductor3:8547 + depends_on: + op-geth-seq3: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-conductor3: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-conductor3 + volumes: + - ./data/op-conductor3:/data + - ./config-op/rollup.json:/rollup.json + ports: + - "8549:8547" # RPC port +# - "50052:50050" # Consensus port + command: + - /app/op-conductor/bin/op-conductor + - --log.level=debug + # already existed service + - --node.rpc=http://op-seq3:9545 + - --execution.rpc=http://op-geth-seq3:8545 + # Raft Config + - --raft.server.id=conductor-3 + - --raft.storage.dir=/data/raft + - --raft.bootstrap=false + - --consensus.addr=0.0.0.0 + - --consensus.port=50050 + - --consensus.advertised=op-conductor3:50050 + # RPC Config + - --rpc.addr=0.0.0.0 + - --rpc.port=8547 + - --rpc.enable-proxy=true + # Healthcheck Config + - --healthcheck.interval=1 + - --healthcheck.unsafe-interval=3 + - --healthcheck.min-peer-count=1 + - --rollup.config=/rollup.json + depends_on: + op-seq3: + condition: service_healthy + op-geth-seq3: + condition: service_healthy diff --git a/test-pp-op/docker-compose.yml b/test-pp-op/docker-compose.yml new file mode 100644 index 0000000000000..a14ed53ce1a9b --- /dev/null +++ b/test-pp-op/docker-compose.yml @@ -0,0 +1,663 @@ +networks: + default: + name: ${DOCKER_NETWORK:-dev-op} + +services: + l1-geth-remove-db: + image: "alpine:3.19.0" + container_name: l1-geth-remove-db + command: rm -rf /execution/geth + volumes: + - ./l1-geth/execution:/execution + + l1-beacon-remove-db: + image: "alpine:3.19.0" + container_name: l1-beacon-remove-db + command: rm -rf /consensus/beacondata /consensus/validatordata /consensus/genesis.ssz + volumes: + - ./l1-geth/consensus:/consensus + + l1-create-beacon-chain-genesis: + image: "gcr.io/prysmaticlabs/prysm/cmd/prysmctl:v5.1.2" + container_name: l1-create-beacon-chain-genesis + command: + - testnet + - generate-genesis + - --fork=deneb + - --num-validators=4 + - --genesis-time-delay=0 + - --output-ssz=/consensus/genesis.ssz + - --chain-config-file=/consensus/config.yml + - --geth-genesis-json-in=/execution/genesis-raw.json + - --geth-genesis-json-out=/execution/genesis.json + volumes: + - ./l1-geth/consensus:/consensus + - ./l1-geth/execution:/execution + depends_on: + l1-beacon-remove-db: + condition: service_completed_successfully + + l1-fix-genesis-fork-times: + image: "alpine:3.19.0" + container_name: l1-fix-genesis-fork-times + command: + - /bin/sh + - -c + - | + apk add --no-cache jq + echo "Fixing genesis.json fork times..." + sed -i 's/"shanghaiTime": [0-9]*/"shanghaiTime": 0/g' /execution/genesis.json + sed -i 's/"cancunTime": [0-9]*/"cancunTime": 0/g' /execution/genesis.json + echo "Adding blobSchedule for Cancun..." + jq '.config.blobSchedule = {"cancun": {"target": 3, "max": 6, "baseFeeUpdateFraction": 3338477}}' /execution/genesis.json > /tmp/genesis.json && mv /tmp/genesis.json /execution/genesis.json + echo "Removing terminalTotalDifficultyPassed for op-node compatibility..." + jq 'del(.config.terminalTotalDifficultyPassed)' /execution/genesis.json > /tmp/genesis.json && mv /tmp/genesis.json /execution/genesis.json + echo "Genesis.json: shanghai=0, cancun=0 (MCOPY enabled), blobSchedule added, terminalTotalDifficultyPassed removed" + cat /execution/genesis.json | jq '.config | {shanghaiTime, cancunTime, terminalTotalDifficulty, blobSchedule}' + volumes: + - ./l1-geth/execution:/execution + depends_on: + l1-create-beacon-chain-genesis: + condition: service_completed_successfully + + l1-geth-genesis: + image: "ethereum/client-go:v1.15.11" + container_name: l1-geth-genesis + command: --datadir=/execution --gcmode=archive init --state.scheme=hash /execution/genesis.json + volumes: + - ./l1-geth/execution:/execution + - ./l1-geth/execution/genesis.json:/execution/genesis.json + depends_on: + l1-fix-genesis-fork-times: + condition: service_completed_successfully + l1-geth-remove-db: + condition: service_completed_successfully + + l1-geth: + image: "ethereum/client-go:v1.15.11" + container_name: l1-geth + command: + - --http + - --http.api=eth,net,web3,debug,admin + - --http.addr=0.0.0.0 + - --http.corsdomain=* + - --http.vhosts=* + - --ws + - --ws.api=eth,net,web3,debug + - --ws.addr=0.0.0.0 + - --ws.origins=* + - --authrpc.vhosts=* + - --authrpc.addr=0.0.0.0 + - --authrpc.jwtsecret=/execution/jwtsecret + - --datadir=/execution + - --allow-insecure-unlock + - --unlock=0x123463a4b065722e99115d6c222f267d9cabb524 + - --password=/execution/geth_password.txt + - --nodiscover + - --syncmode=full + - --gcmode=archive + - --ipcdisable + - --rpc.allow-unprotected-txs + - --verbosity=3 + ports: + - 8551:8551 + - 8545:8545 + - 8546:8546 + depends_on: + l1-geth-genesis: + condition: service_completed_successfully + volumes: + - ./l1-geth/execution:/execution + - ./l1-geth/execution/jwtsecret:/execution/jwtsecret + - ./l1-geth/execution/geth_password.txt:/execution/geth_password.txt + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8545"] + interval: 10s + timeout: 5s + retries: 5 + + l1-beacon-chain: + image: "gcr.io/prysmaticlabs/prysm/beacon-chain:v5.1.2" + container_name: l1-beacon-chain + command: + - --datadir=/consensus/beacondata + - --min-sync-peers=0 + - --genesis-state=/consensus/genesis.ssz + - --bootstrap-node= + - --interop-eth1data-votes + - --chain-config-file=/consensus/config.yml + - --contract-deployment-block=0 + - --chain-id=${CHAIN_ID:-1337} + - --rpc-host=0.0.0.0 + - --grpc-gateway-host=0.0.0.0 + - --execution-endpoint=http://l1-geth:8551 + - --accept-terms-of-use + - --jwt-secret=/execution/jwtsecret + - --suggested-fee-recipient=0x123463a4b065722e99115d6c222f267d9cabb524 + - --minimum-peers-per-subnet=0 + - --enable-debug-rpc-endpoints + - --verbosity=info + depends_on: + l1-create-beacon-chain-genesis: + condition: service_completed_successfully + l1-geth: + condition: service_healthy + ports: + - 4000:4000 + - 3500:3500 + - 18080:8080 + - 6060:6060 + - 19090:9090 + volumes: + - ./l1-geth/consensus:/consensus + - ./l1-geth/execution:/execution + - ./l1-geth/execution/jwtsecret:/execution/jwtsecret + + l1-validator: + image: "gcr.io/prysmaticlabs/prysm/validator:v5.1.2" + container_name: l1-validator + command: + - --beacon-rpc-provider=l1-beacon-chain:4000 + - --datadir=/consensus/validatordata + - --accept-terms-of-use + - --interop-num-validators=4 + - --interop-start-index=0 + - --chain-config-file=/consensus/config.yml + - --verbosity=info + depends_on: + l1-beacon-chain: + condition: service_started + volumes: + - ./l1-geth/consensus:/consensus + + op-geth-seq: + image: "${OP_GETH_IMAGE_TAG}" + container_name: op-geth-seq + entrypoint: geth + volumes: + - ./data/op-geth-seq:/datadir + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/test.seq.config.toml:/config.toml + ports: + - "8123:8545" + - "7546:7546" + - "8552:8552" + - "30303:30303" + - "30303:30303/udp" + - "9090:9090" # pprof port + command: + - --verbosity=3 + - --datadir=/datadir + - --db.engine=${DB_ENGINE} + - --config=/config.toml + - --gcmode=archive + - --rollup.disabletxpoolgossip=false + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-geth-rpc: + image: "${OP_GETH_IMAGE_TAG}" + container_name: op-geth-rpc + entrypoint: geth + volumes: + - ./data/op-geth-rpc:/datadir + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/test.rpc.config.toml:/config.toml + ports: + - "8124:8545" + - "30304:30303" + - "30304:30303/udp" + command: + - --verbosity=3 + - --datadir=/datadir + - --db.engine=${DB_ENGINE} + - --config=/config.toml + - --gcmode=archive + # - --rollup.sequencerhttp=http://op-geth-seq:8545 + - --rollup.enabletxpooladmission + + op-seq: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-seq + volumes: + - ./config-op/rollup.json:/rollup.json + - ./config-op/jwt.txt:/jwt.txt + - ./data/op-seq:/data + - ./l1-geth/execution/:/l1/ + ports: + - "9545:9545" + - "7070:7070" + - "9223:9223" + - "9223:9223/udp" + - "9091:9091" # pprof port + command: + - /app/op-node/bin/op-node + - --log.level=debug + - --l2=http://op-geth-seq:8552 + - --l2.jwt-secret=/jwt.txt + - --sequencer.enabled + - --sequencer.l1-confs=5 + - --verifier.l1-confs=1 + - --rollup.config=/rollup.json + - --rpc.addr=0.0.0.0 + - --p2p.listen.tcp=9223 + - --p2p.listen.udp=9223 + - --p2p.priv.raw=e054b5748fb29a82994ea170af9e6094a163a0d11308dea91a38744c4e7c94da + - --p2p.peerstore.path=/data/p2p/opnode_peerstore_db + - --p2p.discovery.path=/data/p2p/opnode_discovery_db + - --p2p.no-discovery + - --rpc.enable-admin + - --p2p.sequencer.key=${SEQUENCER_P2P_KEY} + - --l1=${L1_RPC_URL_IN_DOCKER} + - --l1.beacon=${L1_BEACON_URL_IN_DOCKER} + - --l1.rpckind=standard + - --rollup.l1-chain-config=/l1/genesis.json + - --safedb.path=/data/safedb + - --conductor.enabled=${CONDUCTOR_ENABLED:-false} # ้ป˜่ฎคๅ…ณ้—ญ + - --conductor.rpc=http://op-conductor:8547 + - --pprof.enabled + - --pprof.addr=0.0.0.0 + - --pprof.port=9091 + depends_on: + op-geth-seq: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-rpc: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-rpc + volumes: + - ./data/op-rpc:/data + - ./config-op/rollup.json:/rollup.json + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/oprpc_p2p_priv.txt:/opnode_p2p_priv.txt + - ./l1-geth/execution/genesis.json:/l1-genesis.json + ports: + - "9555:9545" + command: + - /app/op-node/bin/op-node + - --log.level=debug + - --l2=http://op-geth-rpc:8552 + - --l2.jwt-secret=/jwt.txt + - --sequencer.enabled=false + - --verifier.l1-confs=1 + - --rollup.config=/rollup.json + - --rpc.addr=0.0.0.0 + - --rpc.port=9545 + - --p2p.listen.tcp=9223 + - --p2p.listen.udp=9223 + - --p2p.priv.raw=604557d042fbea9ed42f46c0c95c346a932b6a5ef0c0dd07a00dbf95801a2510 + - --p2p.peerstore.path=/data/p2p/opnode_peerstore_db + - --p2p.discovery.path=/data/p2p/opnode_discovery_db + - --p2p.static=/dns4/op-seq/tcp/9223/p2p/16Uiu2HAkzHdkbmS2VrCsccLibsu7MvGHpmFUMJnMTkKifrtS5m65 + - --p2p.no-discovery + - --rpc.enable-admin=true + - --l1=${L1_RPC_URL_IN_DOCKER} + - --l1.beacon=${L1_BEACON_URL_IN_DOCKER} + - --l1.rpckind=standard + - --rollup.l1-chain-config=/l1-genesis.json + - --safedb.path=/data/safedb + depends_on: + - op-geth-rpc + + op-conductor: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-conductor + volumes: + - ./data/op-conductor:/data + - ./config-op/rollup.json:/rollup.json + ports: + - "8547:8547" # RPC port + - "50050:50050" # Consensus port + command: + - /app/op-conductor/bin/op-conductor + - --log.level=debug + # already existed service + - --node.rpc=http://op-seq:9545 + - --execution.rpc=http://op-geth-seq:8545 + # Raft Config + - --raft.server.id=conductor-1 + - --raft.storage.dir=/data/raft + - --raft.bootstrap=true + - --consensus.addr=0.0.0.0 + - --consensus.port=50050 + - --consensus.advertised=op-conductor:50050 + # RPC Config + - --rpc.addr=0.0.0.0 + - --rpc.port=8547 + - --rpc.enable-proxy=true + # Healthcheck Config + - --healthcheck.interval=1 + - --healthcheck.unsafe-interval=3 + - --healthcheck.min-peer-count=1 + - --rollup.config=/rollup.json + depends_on: + op-seq: + condition: service_healthy + op-geth-seq: + condition: service_healthy + + op-batcher: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-batcher + command: + - /app/op-batcher/bin/op-batcher + - --log.level=debug + - --l2-eth-rpc=http://op-geth-seq:8545 + - --rollup-rpc=http://op-seq:9545 + - --poll-interval=1s + - --sub-safety-margin=6 + - --num-confirmations=1 + - --safe-abort-nonce-too-low-count=3 + - --resubmission-timeout=30s + - --rpc.addr=0.0.0.0 + - --rpc.port=8548 + - --rpc.enable-admin + - --max-channel-duration=25 + - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} + - --private-key=${OP_BATCHER_PRIVATE_KEY} + - --throttle.block-size-upper-limit=1300000 + - -data-availability-type=auto + depends_on: + - op-seq + + op-proposer: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-proposer + environment: + - DISPUTE_GAME_FACTORY_ADDRESS=${DISPUTE_GAME_FACTORY_ADDRESS} + command: + - /app/op-proposer/bin/op-proposer + - --log.level=debug + - --poll-interval=2s + - --rpc.port=8560 + - --rollup-rpc=http://op-seq:9545 + - --game-factory-address=${DISPUTE_GAME_FACTORY_ADDRESS} + - --proposal-interval=1m + - --private-key=${OP_PROPOSER_PRIVATE_KEY} + - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} + - --game-type=${GAME_TYPE:-0} + - --allow-non-finalized + - --genesis-height=${FORK_BLOCK} + depends_on: + - op-batcher + + op-challenger: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-challenger + environment: + - L1_RPC_URL_IN_DOCKER=${L1_RPC_URL_IN_DOCKER} + - L1_BEACON_URL_IN_DOCKER=${L1_BEACON_URL_IN_DOCKER} + - DISPUTE_GAME_FACTORY_ADDRESS=${DISPUTE_GAME_FACTORY_ADDRESS} + volumes: + - ./data/cannon-data:/data + - ./config-op/rollup.json:/rollup.json + - ./config-op/genesis.json:/l2-genesis.json + depends_on: + - op-seq + command: + - /app/op-challenger/bin/op-challenger + - --log.level=debug + - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} + - --l1-beacon=${L1_BEACON_URL_IN_DOCKER} + - --l2-eth-rpc=http://op-geth-seq:8545 + - --rollup-rpc=http://op-seq:9545 + - --game-factory-address=${DISPUTE_GAME_FACTORY_ADDRESS} + - --cannon-bin=/app/cannon/bin/cannon + - --cannon-server=/data/op-program + - --cannon-prestate=/data/prestate-mt64.bin.gz + - --cannon-rollup-config=/rollup.json + - --cannon-l2-genesis=/l2-genesis.json + - --private-key=${OP_PROPOSER_PRIVATE_KEY} + - --trace-type=cannon,permissioned + - --datadir=/data + - --game-window=${GAME_WINDOW}s + + op-dispute-mon: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-dispute-mon + depends_on: + - op-challenger + - op-proposer + command: + - /app/op-dispute-mon/bin/op-dispute-mon + - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} + - --rollup-rpc=http://op-seq:9545 + - --game-factory-address=${DISPUTE_GAME_FACTORY_ADDRESS} + - --game-window=${GAME_WINDOW}s + - --honest-actors=${PROPOSER_ADDRESS} + + op-geth-seq2: + image: "${OP_GETH_IMAGE_TAG}" + container_name: op-geth-seq2 + entrypoint: geth + volumes: + - ./data/op-geth-seq2:/datadir + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/test.seq.config.toml:/config.toml + ports: + - "8223:8545" + - "30305:30303" + - "30305:30303/udp" + command: + - --verbosity=3 + - --datadir=/datadir + - --db.engine=${DB_ENGINE} + - --config=/config.toml + - --gcmode=archive + - --rollup.disabletxpoolgossip=false + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-seq2: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-seq2 + volumes: + - ./config-op/rollup.json:/rollup.json + - ./config-op/jwt.txt:/jwt.txt + - ./data/op-seq2:/data + - ./l1-geth/execution/genesis.json:/l1-genesis.json + ports: + - "9546:9545" +# - "7070:7070" + - "9224:9223" + - "9224:9223/udp" + command: + - /app/op-node/bin/op-node + - --log.level=info + - --l2=http://op-geth-seq2:8552 + - --l2.jwt-secret=/jwt.txt + - --sequencer.enabled + - --sequencer.stopped + - --sequencer.l1-confs=5 + - --verifier.l1-confs=1 + - --rollup.config=/rollup.json + - --rpc.addr=0.0.0.0 + - --p2p.listen.tcp=9223 + - --p2p.listen.udp=9223 + - --p2p.priv.raw=cff9dac7588f5e6755a72d1e5b5001da3d0f8c06c4242b27d67eb5df4216bd93 + - --p2p.peerstore.path=/data/p2p/opnode_peerstore_db + - --p2p.discovery.path=/data/p2p/opnode_discovery_db + - --p2p.static=/dns4/op-seq/tcp/9223/p2p/16Uiu2HAkzHdkbmS2VrCsccLibsu7MvGHpmFUMJnMTkKifrtS5m65,/dns4/op-seq3/tcp/9223/p2p/16Uiu2HAmRDGMm3UUrP8CfQ3YQo9aaXEXFXA7LeFNztdPMNK5moyD + - --p2p.no-discovery + - --rpc.enable-admin + - --p2p.sequencer.key=${SEQUENCER_P2P_KEY} + - --l1=${L1_RPC_URL_IN_DOCKER} + - --l1.beacon=${L1_BEACON_URL_IN_DOCKER} + - --l1.rpckind=standard + - --rollup.l1-chain-config=/l1-genesis.json + - --safedb.path=/data/safedb + - --conductor.enabled=${CONDUCTOR_ENABLED:-false} + - --conductor.rpc=http://op-conductor2:8547 + depends_on: + op-geth-seq2: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-conductor2: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-conductor2 + volumes: + - ./data/op-conductor2:/data + - ./config-op/rollup.json:/rollup.json + ports: + - "8548:8547" # RPC port + - "50051:50050" # Consensus port + command: + - /app/op-conductor/bin/op-conductor + - --log.level=debug + # already existed service + - --node.rpc=http://op-seq2:9545 + - --execution.rpc=http://op-geth-seq2:8545 + # Raft Config + - --raft.server.id=conductor-2 + - --raft.storage.dir=/data/raft + - --raft.bootstrap=false + - --consensus.addr=0.0.0.0 + - --consensus.port=50050 + - --consensus.advertised=op-conductor2:50050 + # RPC Config + - --rpc.addr=0.0.0.0 + - --rpc.port=8547 + - --rpc.enable-proxy=true + # Healthcheck Config + - --healthcheck.interval=1 + - --healthcheck.unsafe-interval=3 + - --healthcheck.min-peer-count=1 + - --rollup.config=/rollup.json + depends_on: + op-seq2: + condition: service_healthy + op-geth-seq2: + condition: service_healthy + + op-geth-seq3: + image: "${OP_GETH_IMAGE_TAG}" + container_name: op-geth-seq3 + entrypoint: geth + volumes: + - ./data/op-geth-seq3:/datadir + - ./config-op/jwt.txt:/jwt.txt + - ./config-op/test.seq.config.toml:/config.toml + ports: + - "8323:8545" + - "30306:30303" + - "30306:30303/udp" + command: + - --verbosity=3 + - --datadir=/datadir + - --db.engine=${DB_ENGINE} + - --config=/config.toml + - --gcmode=archive + - --rollup.disabletxpoolgossip=false + healthcheck: + test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:8545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-seq3: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-seq3 + volumes: + - ./config-op/rollup.json:/rollup.json + - ./config-op/jwt.txt:/jwt.txt + - ./data/op-seq3:/data + - ./l1-geth/execution/genesis.json:/l1-genesis.json + ports: + - "9547:9545" +# - "7070:7070" + - "9225:9223" + - "9225:9223/udp" + command: + - /app/op-node/bin/op-node + - --log.level=info + - --l2=http://op-geth-seq3:8552 + - --l2.jwt-secret=/jwt.txt + - --sequencer.enabled + - --sequencer.stopped + - --sequencer.l1-confs=5 + - --verifier.l1-confs=1 + - --rollup.config=/rollup.json + - --rpc.addr=0.0.0.0 + - --p2p.listen.tcp=9223 + - --p2p.listen.udp=9223 + - --p2p.priv.raw=10785157e7c98628e5e47c3d9b8ebbd12525c45f1554b4a39652b5ce02bb29dc + - --p2p.peerstore.path=/data/p2p/opnode_peerstore_db + - --p2p.discovery.path=/data/p2p/opnode_discovery_db + - --p2p.static=/dns4/op-seq/tcp/9223/p2p/16Uiu2HAkzHdkbmS2VrCsccLibsu7MvGHpmFUMJnMTkKifrtS5m65,/dns4/op-seq2/tcp/9223/p2p/16Uiu2HAmDTjVuEF6V9DccV1JhrHg7DYc5SKm3bw2T75kAFPsGuSp + - --p2p.no-discovery + - --rpc.enable-admin + - --p2p.sequencer.key=${SEQUENCER_P2P_KEY} + - --l1=${L1_RPC_URL_IN_DOCKER} + - --l1.beacon=${L1_BEACON_URL_IN_DOCKER} + - --l1.rpckind=standard + - --rollup.l1-chain-config=/l1-genesis.json + - --safedb.path=/data/safedb + - --conductor.enabled=${CONDUCTOR_ENABLED:-false} + - --conductor.rpc=http://op-conductor3:8547 + depends_on: + op-geth-seq3: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9545"] + interval: 3s + timeout: 3s + retries: 10 + start_period: 3s + + op-conductor3: + image: "${OP_STACK_IMAGE_TAG}" + container_name: op-conductor3 + volumes: + - ./data/op-conductor3:/data + - ./config-op/rollup.json:/rollup.json + ports: + - "8549:8547" # RPC port + - "50052:50050" # Consensus port + command: + - /app/op-conductor/bin/op-conductor + - --log.level=debug + # already existed service + - --node.rpc=http://op-seq3:9545 + - --execution.rpc=http://op-geth-seq3:8545 + # Raft Config + - --raft.server.id=conductor-3 + - --raft.storage.dir=/data/raft + - --raft.bootstrap=false + - --consensus.addr=0.0.0.0 + - --consensus.port=50050 + - --consensus.advertised=op-conductor3:50050 + # RPC Config + - --rpc.addr=0.0.0.0 + - --rpc.port=8547 + - --rpc.enable-proxy=true + # Healthcheck Config + - --healthcheck.interval=1 + - --healthcheck.unsafe-interval=3 + - --healthcheck.min-peer-count=1 + - --rollup.config=/rollup.json + depends_on: + op-seq3: + condition: service_healthy + op-geth-seq3: + condition: service_healthy diff --git a/test-pp-op/dockerfile/Dockerfile-cdk-erigon b/test-pp-op/dockerfile/Dockerfile-cdk-erigon new file mode 100644 index 0000000000000..34996601bce97 --- /dev/null +++ b/test-pp-op/dockerfile/Dockerfile-cdk-erigon @@ -0,0 +1,87 @@ +# syntax = docker/dockerfile:1.2 +FROM docker.io/library/golang:1.24-alpine3.21 AS builder + +RUN apk --no-cache add build-base linux-headers git bash ca-certificates libstdc++ + +WORKDIR /app +ADD go.mod go.mod +ADD go.sum go.sum +ADD erigon-lib/go.mod erigon-lib/go.mod +ADD erigon-lib/go.sum erigon-lib/go.sum + +RUN go mod download +ADD . . + +RUN --mount=type=cache,target=/root/.cache \ + --mount=type=cache,target=/tmp/go-build \ + --mount=type=cache,target=/go/pkg/mod \ + make BUILD_TAGS=nosqlite,noboltdb,nosilkworm cdk-erigon + +RUN --mount=type=cache,target=/root/.cache \ + --mount=type=cache,target=/tmp/go-build \ + --mount=type=cache,target=/go/pkg/mod \ + make smt-db-split + +FROM docker.io/library/golang:1.24-alpine3.21 AS tools-builder +RUN apk --no-cache add build-base linux-headers git bash ca-certificates libstdc++ +WORKDIR /app + +ADD Makefile Makefile +ADD tools.go tools.go +ADD go.mod go.mod +ADD go.sum go.sum +ADD erigon-lib/go.mod erigon-lib/go.mod +ADD erigon-lib/go.sum erigon-lib/go.sum + +RUN mkdir -p /app/build/bin + +RUN --mount=type=cache,target=/root/.cache \ + --mount=type=cache,target=/tmp/go-build \ + --mount=type=cache,target=/go/pkg/mod \ + make db-tools + +FROM docker.io/library/alpine:3.17 + +# install required runtime libs, along with some helpers for debugging +RUN apk add --no-cache ca-certificates libstdc++ tzdata +RUN apk add --no-cache curl jq bind-tools +RUN apk add --no-cache perl perl-utils +RUN apk add --no-cache build-base git && \ + git clone https://github.com/hoytech/vmtouch.git && \ + cd vmtouch && \ + make && \ + install -m 755 vmtouch /usr/local/bin/ + +RUN mkdir -p ~/.local/share/erigon +WORKDIR /home/erigon + +## then give each binary its own layer +COPY --from=tools-builder /app/build/bin/mdbx_copy /usr/local/bin/mdbx_copy +COPY --from=builder /app/build/bin/cdk-erigon /usr/local/bin/cdk-erigon +COPY --from=builder /app/build/bin/smt-db-split /usr/local/bin/smt-db-split +COPY --from=builder /app/cmd/smt-db-split/prepare-db-split.sh /usr/local/bin/prepare-db-split.sh + +EXPOSE 8545 \ + 8551 \ + 8546 \ + 30303 \ + 30303/udp \ + 42069 \ + 42069/udp \ + 8080 \ + 9090 \ + 6060 + +# https://github.com/opencontainers/image-spec/blob/main/annotations.md +ARG BUILD_DATE +ARG VCS_REF +ARG VERSION +LABEL org.label-schema.build-date=$BUILD_DATE \ + org.label-schema.description="Erigon ZKEVM Client" \ + org.label-schema.name="ZKEVM Erigon" \ + org.label-schema.schema-version="1.0" \ + org.label-schema.url="https://torquem.ch" \ + org.label-schema.vcs-ref=$VCS_REF \ + org.label-schema.vcs-url="https://github.com/0xPolygonHermez/cdk-erigon.git" \ + org.label-schema.vendor="Torquem" \ + org.label-schema.version=$VERSION diff --git a/test-pp-op/dockerfile/Dockerfile.migrate b/test-pp-op/dockerfile/Dockerfile.migrate new file mode 100644 index 0000000000000..0a22581ecfef8 --- /dev/null +++ b/test-pp-op/dockerfile/Dockerfile.migrate @@ -0,0 +1,27 @@ +# Support setting various labels on the final image +ARG COMMIT="" +ARG VERSION="" +ARG BUILDNUM="" + +# Build Geth in a stock Go builder container +FROM golang:1.24-alpine AS builder + +RUN go env -w CGO_ENABLED=1 +RUN apk add --no-cache make gcc musl-dev linux-headers git + +WORKDIR /app + +COPY tmp/op-geth op-geth +RUN cd op-geth && make geth + +COPY . test-pp-op +RUN rm -rf test-pp-op/tmp + +FROM alpine:latest + +RUN apk add --no-cache jq bash ca-certificates libgcc libstdc++ + +COPY --from=builder /app/op-geth/build/bin/geth /usr/local/bin/geth +COPY --from=builder /app/test-pp-op /app/test-pp-op + +WORKDIR /app diff --git a/test-pp-op/dockerfile/Dockerfile.repro b/test-pp-op/dockerfile/Dockerfile.repro new file mode 100644 index 0000000000000..a092b7609d85e --- /dev/null +++ b/test-pp-op/dockerfile/Dockerfile.repro @@ -0,0 +1,60 @@ +ARG GO_VERSION=1.23.8-alpine3.21 +ARG EXPORT_TARGET=current +# we need a separate stage for src so we can build a service provides prestates for unnanounced chains +FROM golang:${GO_VERSION} AS builder +#FROM src AS builder +ARG EXPORT_TARGET +# We avoid copying the full .git dir into the build for just some metadata. +# Instead, specify: +# --build-arg GIT_COMMIT=$(git rev-parse HEAD) +# --build-arg GIT_DATE=$(git show -s --format='%ct') +ARG GIT_COMMIT +ARG GIT_DATE + +ARG CANNON_VERSION=v0.0.0 +ARG OP_PROGRAM_VERSION=v0.0.0 + +ARG TARGETOS TARGETARCH + +WORKDIR /app +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build just \ + -d /app/op-program \ + -f /app/op-program/repro.justfile \ + GOOS="$TARGETOS" \ + GOARCH="$TARGETARCH" \ + GIT_COMMIT="$GIT_COMMIT" \ + GIT_DATE="$GIT_DATE" \ + CANNON_VERSION="$CANNON_VERSION" \ + OP_PROGRAM_VERSION="$OP_PROGRAM_VERSION" \ + "build-${EXPORT_TARGET}" + + +FROM scratch AS export-current +# Cannon64 files +COPY --from=builder /app/op-program/bin/op-program-client64.elf . +COPY --from=builder /app/op-program/bin/meta-mt64.json . +COPY --from=builder /app/op-program/bin/prestate-mt64.bin.gz . +COPY --from=builder /app/op-program/bin/prestate-proof-mt64.json . +# Interop files +COPY --from=builder ./app/op-program/bin/op-program-client-interop.elf . +COPY --from=builder /app/op-program/bin/meta-interop.json . +COPY --from=builder /app/op-program/bin/prestate-interop.bin.gz . +COPY --from=builder /app/op-program/bin/prestate-proof-interop.json . + +FROM scratch AS export-next +# Cannon64 Next VM files +COPY --from=builder /app/op-program/bin/op-program-client64.elf ./op-program-client-next64.elf +COPY --from=builder /app/op-program/bin/meta-mt64Next.json . +COPY --from=builder /app/op-program/bin/prestate-mt64Next.bin.gz . +COPY --from=builder /app/op-program/bin/prestate-proof-mt64Next.json . +# Interop Next files +COPY --from=builder ./app/op-program/bin/op-program-client-interop.elf ./op-program-client-interopNext.elf +COPY --from=builder /app/op-program/bin/meta-interopNext.json . +COPY --from=builder /app/op-program/bin/prestate-interopNext.bin.gz . +COPY --from=builder /app/op-program/bin/prestate-proof-interopNext.json . + +# Exports files to the specified output location. +# Writing files to host requires buildkit to be enabled. +# e.g. `BUILDKIT=1 docker build ...` +# Final export stage โ€” dynamically selected +FROM export-${EXPORT_TARGET} AS export-stage diff --git a/test-pp-op/dockerfile/Dockerfile.repro-builder b/test-pp-op/dockerfile/Dockerfile.repro-builder new file mode 100644 index 0000000000000..22d89a1417034 --- /dev/null +++ b/test-pp-op/dockerfile/Dockerfile.repro-builder @@ -0,0 +1,19 @@ +# For caching deps to build reproducible prestate images on ECS. +ARG GO_VERSION=1.23.8-alpine3.21 +ARG EXPORT_TARGET=current +FROM golang:${GO_VERSION} AS src + +RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash just + +COPY ./go.mod /app/go.mod +COPY ./go.sum /app/go.sum +COPY ./op-geth /app/op-geth + +WORKDIR /app + +RUN echo "go mod cache: $(go env GOMODCACHE)" +RUN echo "go build cache: $(go env GOCACHE)" + +RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build go mod download + +COPY . /app diff --git a/test-pp-op/init-erigon.sh b/test-pp-op/init-erigon.sh new file mode 100755 index 0000000000000..a4b7fd3e90c19 --- /dev/null +++ b/test-pp-op/init-erigon.sh @@ -0,0 +1,213 @@ +#!/bin/bash +set -e +set -x + +# ============================================================================= +# Init Erigon Chain +# ============================================================================= +# The script is a comprehensive initialization script for setting up a local XLayer Erigon +# development environment. It handles contract deployment, configuration generation, and system setup for a ZK-EVM rollup test environment. +# + + + +source .env +source utils.sh + +git checkout config/* + +if [ ! -d "tmp/xlayer-erigon" ]; then + echo "ERROR: tmp/xlayer-erigon directory does not exist!" + echo "Please ensure the xlayer-erigon directory is present before running this script." + echo "the hack cmd is required" + exit 1 +fi + +mkdir -p $TMP_DIR +cd $TMP_DIR +if [ -d "./xlayer-contracts" ]; then + cd xlayer-contracts + current_branch=$(git branch --show-current) + if [ "$current_branch" != "zjg/v11.0.0-rc.0-op-v1" ]; then + echo "Switching to correct branch: zjg/v11.0.0-rc.0-op-v1" + git fetch origin + git checkout zjg/v11.0.0-rc.0-op-v1 + git pull origin zjg/v11.0.0-rc.0-op-v1 + else + echo "Updating existing repository..." + git pull origin zjg/v11.0.0-rc.0-op-v1 + fi + echo "Cleaning contract repository (selective)..." + rm -rf artifacts cache .openzeppelin node_modules + rm -f deployment/v2/deploy_output.json deployment/v2/create_rollup_output_*.json deployment/v2/genesis.json .env + cd .. +else + echo "Cloning contract repository..." + git clone -b zjg/v11.0.0-rc.0-op-v1 https://github.com/okx/xlayer-contracts.git +fi + +cd $TMP_DIR/xlayer-contracts + +echo "Creating .env file..." +cat > .env << EOF +MNEMONIC="$DEPLOYER_MNEMONIC" +INFURA_PROJECT_ID="000" +ETHERSCAN_API_KEY="000" +EOF + +cd deployment/v2 + +echo "Creating create_rollup_parameters.json..." +cat > create_rollup_parameters.json << EOF +{ + "adminZkEVM": "$DEPLOYER_ADDRESS", + "chainID": 195, + "consensusContract": "PolygonPessimisticConsensus", + "dataAvailabilityProtocol": "PolygonDataCommittee", + "deployerPvtKey": "", + "description": "description", + "forkID": 13, + "gasTokenAddress":"$L1_OKB_ADDRESS", + "maxFeePerGas": "", + "maxPriorityFeePerGas": "", + "multiplierGas": "", + "networkName": "xlayer", + "realVerifier": false, + "trustedSequencer": "$SEQUENCER_ADDRESS", + "trustedSequencerURL": "$L2_PP_SEQ_URL_IN_DOCKER", + "trustedAggregator":"$AGGREGATOR_ADDRESS", + "programVKey": "$PP_VKEY" +} +EOF + +echo "Creating deploy_parameters.json..." +cat > deploy_parameters.json << EOF +{ + "admin": "$DEPLOYER_ADDRESS", + "deployerPvtKey": "", + "emergencyCouncilAddress": "$DEPLOYER_ADDRESS", + "initialZkEVMDeployerOwner": "$DEPLOYER_ADDRESS", + "maxFeePerGas": "", + "maxPriorityFeePerGas": "", + "minDelayTimelock": 60, + "multiplierGas": "", + "description": "description", + "pendingStateTimeout": 604799, + "polTokenAddress": "$L1_OKB_ADDRESS", + "salt": "0x0000000000000000000000000000000000000000000000000000000000000001", + "timelockAdminAddress": "$DEPLOYER_ADDRESS", + "trustedSequencer": "$SEQUENCER_ADDRESS", + "trustedSequencerURL": "$L2_PP_SEQ_URL_IN_DOCKER", + "trustedAggregator": "$AGGREGATOR_ADDRESS", + "trustedAggregatorTimeout": 604799, + "forkID": 13, + "test": true, + "ppVKey": "$PP_VKEY", + "ppVKeySelector": "0x00000001", + "realVerifier": false, + "defaultAdminAddress": "$DEPLOYER_ADDRESS", + "aggchainDefaultVKeyRoleAddress": "$DEPLOYER_ADDRESS", + "addRouteRoleAddress": "$DEPLOYER_ADDRESS", + "freezeRouteRoleAddress": "$DEPLOYER_ADDRESS", + "zkEVMDeployerAddress": "$DEPLOYER_ADDRESS" +} +EOF + +echo "Compiling contracts..." +cd ../../ +npm i +npm run deploy:v2:localhost + +cd "$ROOT_DIR" +mkdir -p $TMP_DIR/pp-deployed +ROLLUP_OUTPUT_PATH=$(find $TMP_DIR/xlayer-contracts/deployment/v2 -name "create_rollup_output_*.json" | sort -r | head -n 1) +cp -rf $ROLLUP_OUTPUT_PATH $TMP_DIR/pp-deployed/create_rollup_output.json +cp -rf $TMP_DIR/xlayer-contracts/deployment/v2/create_rollup_parameters.json $TMP_DIR/pp-deployed/ +cp -rf $TMP_DIR/xlayer-contracts/deployment/v2/deploy_parameters.json $TMP_DIR/pp-deployed/ +cp -rf $TMP_DIR/xlayer-contracts/deployment/v2/deploy_output.json $TMP_DIR/pp-deployed/ +cp -rf $TMP_DIR/xlayer-contracts/deployment/v2/genesis.json $TMP_DIR/pp-deployed/ +ROLLUP_OUTPUT_PATH="$TMP_DIR/pp-deployed/create_rollup_output.json" +DEPLOY_OUTPUT_PATH="$TMP_DIR/pp-deployed/deploy_output.json" + +# echo "Transferring ERC20 token to Sequencer..." +# cast send --legacy --from $SEQUENCER_ADDRESS --private-key $SEQUENCER_PRIVATE_KEY $TOKEN_ADDRESS "transfer(address,uint256)" $SEQUENCER_ADDRESS 1000 + +echo "Setting Trusted Sequencer URL..." +POE_ADDRESS=$(cat $ROLLUP_OUTPUT_PATH | grep -o '"rollupAddress": "[^"]*"' | cut -d'"' -f4) +BRIDGE_ADDRESS=$(cat $DEPLOY_OUTPUT_PATH | grep -o '"polygonZkEVMBridgeAddress": "[^"]*"' | cut -d'"' -f4) +GENESIS_VALUE=$(cat $ROLLUP_OUTPUT_PATH | grep -o '"genesis": "[^"]*"' | cut -d'"' -f4) +TIMESTAMP_VALUE=$(cat $ROLLUP_OUTPUT_PATH | grep -o '"timestamp": [0-9]*' | cut -d' ' -f2) +L1_FIRST_BLOCK=$(cat $DEPLOY_OUTPUT_PATH | grep -o '"upgradeToULxLyBlockNumber": [0-9]*' | cut -d' ' -f2) +L1_SECOND_BLOCK=$(cat $ROLLUP_OUTPUT_PATH | grep -o '"createRollupBlockNumber": [0-9]*' | cut -d' ' -f2) +ROLLUP_MANAGER_ADDRESS=$(grep -o '"polygonRollupManagerAddress": "[^"]*"' "$DEPLOY_OUTPUT_PATH" | cut -d'"' -f4) +GLOBAL_EXIT_ROOT_ADDRESS=$(grep -o '"polygonZkEVMGlobalExitRootAddress": "[^"]*"' "$DEPLOY_OUTPUT_PATH" | cut -d'"' -f4) +echo "Poe address from JSON: $POE_ADDRESS" +echo "Bridge address from JSON: $BRIDGE_ADDRESS" +echo "Genesis value from JSON: $GENESIS_VALUE" +echo "Timestamp value from JSON: $TIMESTAMP_VALUE" +echo "L1FirstBlock value from JSON: $L1_FIRST_BLOCK" +echo "L1SecondBlock value from JSON: $L1_SECOND_BLOCK" +echo "RollupManagerAddress value from JSON: $ROLLUP_MANAGER_ADDRESS" +echo "GlobalExitRootAddress value from JSON: $GLOBAL_EXIT_ROOT_ADDRESS" + +echo "Using POE address from JSON: $POE_ADDRESS" +cast send --legacy --from $DEPLOYER_ADDRESS --private-key $DEPLOYER_PRIVATE_KEY $POE_ADDRESS "setTrustedSequencerURL(string)" "$L2_PP_RPC_URL_IN_DOCKER" + +cast send --legacy --from $DEPLOYER_ADDRESS --private-key $DEPLOYER_PRIVATE_KEY $BRIDGE_ADDRESS 'function bridgeAsset(uint32 destinationNetwork, address destinationAddress, uint256 amount, address token, bool forceUpdateGlobalExitRoot, bytes permitData) returns()' 7 0x0000000000000000000000000000000000000000 0 0x0000000000000000000000000000000000000000 true 0x + +echo "Generating configuration files..." + +cd "${PWD_DIR}/tmp/xlayer-erigon" +go install ./cmd/hack/allocs +cd ${PWD_DIR} +GO_PATH=$(go env GOPATH) +#TODO: make this adapt to multi environment, mac, linux +${GO_PATH}/bin/allocs $TMP_DIR/xlayer-contracts/deployment/v2/genesis.json +mv allocs.json $PWD_DIR/config/dynamic-mynetwork-allocs.json + +cat > $PWD_DIR/config/dynamic-mynetwork-conf.json << EOF +{ + "root": "$GENESIS_VALUE", + "timestamp": $TIMESTAMP_VALUE, + "gasLimit": 0, + "difficulty": 0 +} +EOF +echo "dynamic-mynetwork-conf.json file updated" + +echo "Updating test.erigon.seq.config.yaml file..." +ERIGON_SEQ_CONFIG_FILE="${PWD_DIR}/config/test.erigon.seq.config.yaml" +sed_inplace "s|zkevm.address-zkevm: \"[^\"]*\"|zkevm.address-zkevm: \"$POE_ADDRESS\"|g" "$ERIGON_SEQ_CONFIG_FILE" +sed_inplace "s|zkevm.address-rollup: \"[^\"]*\"|zkevm.address-rollup: \"$ROLLUP_MANAGER_ADDRESS\"|g" "$ERIGON_SEQ_CONFIG_FILE" +sed_inplace "s|zkevm.address-ger-manager: \"[^\"]*\"|zkevm.address-ger-manager: \"$GLOBAL_EXIT_ROOT_ADDRESS\"|g" "$ERIGON_SEQ_CONFIG_FILE" +sed_inplace "s|zkevm.l1-first-block: [0-9]*|zkevm.l1-first-block: $L1_FIRST_BLOCK|g" "$ERIGON_SEQ_CONFIG_FILE" + +mkdir -p "$PWD_DIR/config" +jq '.firstBatchData' "$ROLLUP_OUTPUT_PATH" > "$PWD_DIR/config/first-batch-config.json" +echo "Successfully exported firstBatchData to $PWD_DIR/config/first-batch-config.json" + +echo "Updating parameter in aggkit.toml..." +CONFIG_FILE="${PWD_DIR}/config/aggkit.toml" +sed_inplace "s|polygonBridgeAddr = \"[^\"]*\"|polygonBridgeAddr = \"$BRIDGE_ADDRESS\"|" "$CONFIG_FILE" +sed_inplace "s|BridgeAddr = \"[^\"]*\"|BridgeAddr = \"$BRIDGE_ADDRESS\"|" "$CONFIG_FILE" +sed_inplace "s|BridgeAddrL2 = \"[^\"]*\"|BridgeAddrL2 = \"$BRIDGE_ADDRESS\"|" "$CONFIG_FILE" +sed_inplace "s|rollupCreationBlockNumber = \"[^\"]*\"|rollupCreationBlockNumber = \"$L1_FIRST_BLOCK\"|" "$CONFIG_FILE" +sed_inplace "s|rollupManagerCreationBlockNumber = \"[^\"]*\"|rollupManagerCreationBlockNumber = \"$L1_SECOND_BLOCK\"|" "$CONFIG_FILE" +sed_inplace "s|genesisBlockNumber = \"[^\"]*\"|genesisBlockNumber = \"$L1_FIRST_BLOCK\"|" "$CONFIG_FILE" +sed_inplace "s|polygonRollupManagerAddress = \"[^\"]*\"|polygonRollupManagerAddress = \"$ROLLUP_MANAGER_ADDRESS\"|" "$CONFIG_FILE" +sed_inplace "s|polygonZkEVMGlobalExitRootAddress = \"[^\"]*\"|polygonZkEVMGlobalExitRootAddress = \"$GLOBAL_EXIT_ROOT_ADDRESS\"|" "$CONFIG_FILE" +sed_inplace "s|polygonZkEVMAddress = \"[^\"]*\"|polygonZkEVMAddress = \"$POE_ADDRESS\"|" "$CONFIG_FILE" +echo "Successfully updated contract address parameters in aggkit.toml" + +echo "Updating contract address parameters in agglayer-config.toml..." +AGGLAYER_CONFIG_FILE="${PWD_DIR}/config/agglayer-config.toml" +sed_inplace "s|rollup-manager-contract = \"[^\"]*\"|rollup-manager-contract = \"$ROLLUP_MANAGER_ADDRESS\"|" "$AGGLAYER_CONFIG_FILE" +sed_inplace "s|polygon-zkevm-global-exit-root-v2-contract = \"[^\"]*\"|polygon-zkevm-global-exit-root-v2-contract = \"$GLOBAL_EXIT_ROOT_ADDRESS\"|" "$AGGLAYER_CONFIG_FILE" +GENESIS_CONFIG_FILE="${PWD_DIR}/config/test.genesis.config.json" +sed_inplace "s|\"genesisBlockNumber\": [0-9]*|\"genesisBlockNumber\": $L1_FIRST_BLOCK|" "$GENESIS_CONFIG_FILE" +sed_inplace "s|\"rollupCreationBlockNumber\": [0-9]*|\"rollupCreationBlockNumber\": $L1_SECOND_BLOCK|" "$GENESIS_CONFIG_FILE" +sed_inplace "s|\"rollupManagerCreationBlockNumber\": [0-9]*|\"rollupManagerCreationBlockNumber\": $L1_FIRST_BLOCK|" "$GENESIS_CONFIG_FILE" +AGGLAYER_CONFIG_FILE="${PWD_DIR}/config/agglayer-config.toml" +sed_inplace "s|polygon-zkevm-global-exit-root-v2-contract = \"[^\"]*\"|polygon-zkevm-global-exit-root-v2-contract = \"$GLOBAL_EXIT_ROOT_ADDRESS\"|" "$AGGLAYER_CONFIG_FILE" + +echo "Initialization script completed!" diff --git a/test-pp-op/l1-geth/consensus/config.yml b/test-pp-op/l1-geth/consensus/config.yml new file mode 100644 index 0000000000000..cf6c353b902cd --- /dev/null +++ b/test-pp-op/l1-geth/consensus/config.yml @@ -0,0 +1,34 @@ +CONFIG_NAME: interop +PRESET_BASE: interop + +# Genesis +GENESIS_FORK_VERSION: 0x20000089 + +# Altair +ALTAIR_FORK_EPOCH: 0 +ALTAIR_FORK_VERSION: 0x20000090 + +# Merge +BELLATRIX_FORK_EPOCH: 0 +BELLATRIX_FORK_VERSION: 0x20000091 +TERMINAL_TOTAL_DIFFICULTY: 0 + +# Capella +CAPELLA_FORK_EPOCH: 0 +CAPELLA_FORK_VERSION: 0x20000092 +MAX_WITHDRAWALS_PER_PAYLOAD: 16 + +# Deneb +DENEB_FORK_EPOCH: 0 +DENEB_FORK_VERSION: 0x20000093 + +# Electra +# ELECTRA_FORK_EPOCH: 0 +ELECTRA_FORK_VERSION: 0x15000000 + +# Time parameters +SECONDS_PER_SLOT: 2 +SLOTS_PER_EPOCH: 6 + +# Deposit contract +DEPOSIT_CONTRACT_ADDRESS: 0x4242424242424242424242424242424242424242 diff --git a/test-pp-op/l1-geth/execution/genesis-raw.json b/test-pp-op/l1-geth/execution/genesis-raw.json new file mode 100644 index 0000000000000..4f0447ea58cab --- /dev/null +++ b/test-pp-op/l1-geth/execution/genesis-raw.json @@ -0,0 +1,119 @@ +{ + "config": { + "chainId": 1337, + "homesteadBlock": 0, + "daoForkSupport": true, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "arrowGlacierBlock": 0, + "grayGlacierBlock": 0, + "shanghaiTime": 0, + "cancunTime": 0, + "terminalTotalDifficulty": 0, + "terminalTotalDifficultyPassed": true, + "blobSchedule": { + "cancun": { + "target": 3, + "max": 6, + "baseFeeUpdateFraction": 3338477 + } + } + }, + "nonce": "0x0", + "timestamp": "0x68621d8d", + "extraData": "0x0000000000000000000000000000000000000000000000000000000000000000123463a4b065722e99115d6c222f267d9cabb5240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": "0x1c9c380", + "difficulty": "0x1", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "123463a4b065722e99115d6c222f267d9cabb524": { + "balance": "0x43c33c1937564800000" + }, + "14dc79964da2c08b23698b3d3cc7ca32193d9955": { + "balance": "0x21e19e0c9bab2400000" + }, + "15d34aaf54267db7d7c367839aaf71a00a2c6a65": { + "balance": "0x21e19e0c9bab2400000" + }, + "1cbd3b2770909d4e10f157cabc84c7264073c9ec": { + "balance": "0x21e19e0c9bab2400000" + }, + "23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f": { + "balance": "0x21e19e0c9bab2400000" + }, + "2546bcd3c84621e976d8185a91a922ae77ecec30": { + "balance": "0x21e19e0c9bab2400000" + }, + "3c44cdddb6a900fa2b585dd299e03d12fa4293bc": { + "balance": "0x21e19e0c9bab2400000" + }, + "4242424242424242424242424242424242424242": { + "code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100b6578063621fd130146101e3578063c5f2892f14610273575b600080fd5b34801561005057600080fd5b5061009c6004803603602081101561006757600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061029e565b604051808215151515815260200191505060405180910390f35b6101e1600480360360808110156100cc57600080fd5b81019080803590602001906401000000008111156100e957600080fd5b8201836020820111156100fb57600080fd5b8035906020019184600183028401116401000000008311171561011d57600080fd5b90919293919293908035906020019064010000000081111561013e57600080fd5b82018360208201111561015057600080fd5b8035906020019184600183028401116401000000008311171561017257600080fd5b90919293919293908035906020019064010000000081111561019357600080fd5b8201836020820111156101a557600080fd5b803590602001918460018302840111640100000000831117156101c757600080fd5b909192939192939080359060200190929190505050610370565b005b3480156101ef57600080fd5b506101f8610fd0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561023857808201518184015260208101905061021d565b50505050905090810190601f1680156102655780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561027f57600080fd5b50610288610fe2565b6040518082815260200191505060405180910390f35b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061036957507f85640907000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b603087879050146103cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806116ec6026913960400191505060405180910390fd5b60208585905014610428576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806116836036913960400191505060405180910390fd5b60608383905014610484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061175f6029913960400191505060405180910390fd5b670de0b6b3a76400003410156104e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806117396026913960400191505060405180910390fd5b6000633b9aca0034816104f457fe5b061461054b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806116b96033913960400191505060405180910390fd5b6000633b9aca00348161055a57fe5b04905067ffffffffffffffff80168111156105c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806117126027913960400191505060405180910390fd5b60606105cb82611314565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a610600602054611314565b60405180806020018060200180602001806020018060200186810386528e8e82818152602001925080828437600081840152601f19601f82011690508083019250505086810385528c8c82818152602001925080828437600081840152601f19601f82011690508083019250505086810384528a818151815260200191508051906020019080838360005b838110156106a657808201518184015260208101905061068b565b50505050905090810190601f1680156106d35780820380516001836020036101000a031916815260200191505b508681038352898982818152602001925080828437600081840152601f19601f820116905080830192505050868103825287818151815260200191508051906020019080838360005b8381101561073757808201518184015260208101905061071c565b50505050905090810190601f1680156107645780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b6040516020018084848082843780830192505050826fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260100193505050506040516020818303038152906040526040518082805190602001908083835b6020831061080e57805182526020820191506020810190506020830392506107eb565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610850573d6000803e3d6000fd5b5050506040513d602081101561086557600080fd5b8101908080519060200190929190505050905060006002808888600090604092610891939291906115da565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108eb57805182526020820191506020810190506020830392506108c8565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561092d573d6000803e3d6000fd5b5050506040513d602081101561094257600080fd5b8101908080519060200190929190505050600289896040908092610968939291906115da565b6000801b604051602001808484808284378083019250505082815260200193505050506040516020818303038152906040526040518082805190602001908083835b602083106109cd57805182526020820191506020810190506020830392506109aa565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610a0f573d6000803e3d6000fd5b5050506040513d6020811015610a2457600080fd5b810190808051906020019092919050505060405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610a8e5780518252602082019150602081019050602083039250610a6b565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610ad0573d6000803e3d6000fd5b5050506040513d6020811015610ae557600080fd5b810190808051906020019092919050505090506000600280848c8c604051602001808481526020018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610b615780518252602082019150602081019050602083039250610b3e565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610ba3573d6000803e3d6000fd5b5050506040513d6020811015610bb857600080fd5b8101908080519060200190929190505050600286600060401b866040516020018084805190602001908083835b60208310610c085780518252602082019150602081019050602083039250610be5565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610c935780518252602082019150602081019050602083039250610c70565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610cd5573d6000803e3d6000fd5b5050506040513d6020811015610cea57600080fd5b810190808051906020019092919050505060405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610d545780518252602082019150602081019050602083039250610d31565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610d96573d6000803e3d6000fd5b5050506040513d6020811015610dab57600080fd5b81019080805190602001909291905050509050858114610e16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252605481526020018061162f6054913960600191505060405180910390fd5b6001602060020a0360205410610e77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061160e6021913960400191505060405180910390fd5b60016020600082825401925050819055506000602054905060008090505b6020811015610fb75760018083161415610ec8578260008260208110610eb757fe5b018190555050505050505050610fc7565b600260008260208110610ed757fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610f335780518252602082019150602081019050602083039250610f10565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610f75573d6000803e3d6000fd5b5050506040513d6020811015610f8a57600080fd5b8101908080519060200190929190505050925060028281610fa757fe5b0491508080600101915050610e95565b506000610fc057fe5b5050505050505b50505050505050565b6060610fdd602054611314565b905090565b6000806000602054905060008090505b60208110156111d057600180831614156110e05760026000826020811061101557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310611071578051825260208201915060208101905060208303925061104e565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156110b3573d6000803e3d6000fd5b5050506040513d60208110156110c857600080fd5b810190808051906020019092919050505092506111b6565b600283602183602081106110f057fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061114b5780518252602082019150602081019050602083039250611128565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561118d573d6000803e3d6000fd5b5050506040513d60208110156111a257600080fd5b810190808051906020019092919050505092505b600282816111c057fe5b0491508080600101915050610ff2565b506002826111df602054611314565b600060401b6040516020018084815260200183805190602001908083835b6020831061122057805182526020820191506020810190506020830392506111fd565b6001836020036101000a0380198251168184511680821785525050505050509050018267ffffffffffffffff191667ffffffffffffffff1916815260180193505050506040516020818303038152906040526040518082805190602001908083835b602083106112a55780518252602082019150602081019050602083039250611282565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156112e7573d6000803e3d6000fd5b5050506040513d60208110156112fc57600080fd5b81019080805190602001909291905050509250505090565b6060600867ffffffffffffffff8111801561132e57600080fd5b506040519080825280601f01601f1916602001820160405280156113615781602001600182028036833780820191505090505b50905060008260c01b90508060076008811061137957fe5b1a60f81b8260008151811061138a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806006600881106113c657fe5b1a60f81b826001815181106113d757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060056008811061141357fe5b1a60f81b8260028151811061142457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060046008811061146057fe5b1a60f81b8260038151811061147157fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806003600881106114ad57fe5b1a60f81b826004815181106114be57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806002600881106114fa57fe5b1a60f81b8260058151811061150b57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060016008811061154757fe5b1a60f81b8260068151811061155857fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060006008811061159457fe5b1a60f81b826007815181106115a557fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b600080858511156115ea57600080fd5b838611156115f757600080fd5b600185028301915084860390509450949250505056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220230afd4b6e3551329e50f1239e08fa3ab7907b77403c4f237d9adf679e8e43cf64736f6c634300060b0033", + "balance": "0x0" + }, + "4e59b44847b379578588920ca78fbf26c0b4956c": { + "code": "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3", + "balance": "0x0" + }, + "5678e9e827b3be0e3d4b910126a64a697a148267": { + "balance": "0x43c33c1937564800000" + }, + "70997970c51812dc3a010c7d01b50e0d17dc79c8": { + "balance": "0x21e19e0c9bab2400000" + }, + "71be63f3384f5fb98995898a86b02fb2426c5788": { + "balance": "0x21e19e0c9bab2400000" + }, + "8626f6940e2eb28930efb4cef49b2d1f2c9c1199": { + "balance": "0x21e19e0c9bab2400000" + }, + "90f79bf6eb2c4f870365e785982e1f101e93b906": { + "balance": "0x21e19e0c9bab2400000" + }, + "976ea74026e726554db657fa54763abd0c3a0aa9": { + "balance": "0x21e19e0c9bab2400000" + }, + "9965507d1a55bcc2695c58ba16fb37d819b0a4dc": { + "balance": "0x21e19e0c9bab2400000" + }, + "a0ee7a142d267c1f36714e4a8f75612f20a79720": { + "balance": "0x21e19e0c9bab2400000" + }, + "bcd4042de499d14e55001ccbb24a551f3b954096": { + "balance": "0x21e19e0c9bab2400000" + }, + "bda5747bfd65f08deb54cb465eb87d40e51b197e": { + "balance": "0x21e19e0c9bab2400000" + }, + "cd3b766ccdd6ae721141f452c550ca635964ce71": { + "balance": "0x21e19e0c9bab2400000" + }, + "dd2fd4581271e230360230f9337d5c0430bf44c0": { + "balance": "0x21e19e0c9bab2400000" + }, + "df3e18d64bc6a983f673ab319ccae4f1a57c7097": { + "balance": "0x21e19e0c9bab2400000" + }, + "f39fd6e51aad88f6f4ce6ab8827279cfffb92266": { + "balance": "0x21e19e0c9bab2400000" + }, + "fabb0ac9d68b0b445fb7357272ff202c5651694a": { + "balance": "0x21e19e0c9bab2400000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": null, + "excessBlobGas": null, + "blobGasUsed": null +} diff --git a/test-pp-op/l1-geth/execution/geth_password.txt b/test-pp-op/l1-geth/execution/geth_password.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/test-pp-op/l1-geth/execution/jwtsecret b/test-pp-op/l1-geth/execution/jwtsecret new file mode 100755 index 0000000000000..c4454fe4fa342 --- /dev/null +++ b/test-pp-op/l1-geth/execution/jwtsecret @@ -0,0 +1 @@ +0xfad2709d0bb03bf0e8ba3c99bea194575d3e98863133d1af638ed056d1d59345 \ No newline at end of file diff --git a/test-pp-op/l1-geth/execution/keystore/UTC--2022-08-19T17-38-31.257380510Z--123463a4b065722e99115d6c222f267d9cabb524 b/test-pp-op/l1-geth/execution/keystore/UTC--2022-08-19T17-38-31.257380510Z--123463a4b065722e99115d6c222f267d9cabb524 new file mode 100644 index 0000000000000..4794e82c2ba30 --- /dev/null +++ b/test-pp-op/l1-geth/execution/keystore/UTC--2022-08-19T17-38-31.257380510Z--123463a4b065722e99115d6c222f267d9cabb524 @@ -0,0 +1 @@ +{"address":"123463a4b065722e99115d6c222f267d9cabb524","crypto":{"cipher":"aes-128-ctr","ciphertext":"93b90389b855889b9f91c89fd15b9bd2ae95b06fe8e2314009fc88859fc6fde9","cipherparams":{"iv":"9dc2eff7967505f0e6a40264d1511742"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"c07503bb1b66083c37527cd8f06f8c7c1443d4c724767f625743bd47ae6179a4"},"mac":"6d359be5d6c432d5bbb859484009a4bf1bd71b76e89420c380bd0593ce25a817"},"id":"622df904-0bb1-4236-b254-f1b8dfdff1ec","version":3} \ No newline at end of file diff --git a/test-pp-op/l1-geth/execution/sk.json b/test-pp-op/l1-geth/execution/sk.json new file mode 100644 index 0000000000000..8fe79fab50958 --- /dev/null +++ b/test-pp-op/l1-geth/execution/sk.json @@ -0,0 +1 @@ +2e0834786285daccd064ca17f1654f67b4aef298acbb82cef9ec422fb4975622 diff --git a/test-pp-op/local.env b/test-pp-op/local.env new file mode 100644 index 0000000000000..a8f2dfc4453e7 --- /dev/null +++ b/test-pp-op/local.env @@ -0,0 +1,126 @@ +ENV=local + +CONDUCTOR_ENABLED=true +OWNER_TYPE=transactor # transactor or safe +CGT_ENABLED=true + +CHAIN_ID=195 + +DOCKER_NETWORK=pp-op +CONFIG_DIR=config-op + +# Images +OP_GETH_MIGRATION_IMAGE_TAG=op-geth-migrate:latest +OP_GETH_IMAGE_TAG=op-geth:latest +OP_STACK_IMAGE_TAG=op-stack:latest +OP_CONTRACTS_IMAGE_TAG=op-contract:latest +XLAYER_BRIDGE_SERVICE_IMAGE_TAG=hermeznetwork/zkevm-bridge-service:v0.6.0-RC16-patch +CDK_ERIGON_IMAGE_TAG=cdk-erigon:latest + +OP_GETH_DATADIR=./data/op-geth-seq +OP_GETH_DATADIR2=./data/op-geth-seq2 +OP_GETH_DATADIR3=./data/op-geth-seq3 +OP_GETH_RPC_DATADIR=./data/op-geth-rpc + +# RPC endpoints +L1_RPC_URL=http://127.0.0.1:8545 +L2_RPC_URL=http://127.0.0.1:8124 +L2_ERIGON_RPC_URL=http://127.0.0.1:18124 +L2_OP_SEQ_WS_URL=ws://localhost:7546 +L1_RPC_URL_IN_DOCKER=http://l1-geth:8545 +L2_PP_SEQ_URL_IN_DOCKER=http://xlayer-seq:8545 +L2_PP_RPC_URL_IN_DOCKER=http://xlayer-rpc:8545 +L2_OP_RPC_URL_IN_DOCKER=http://op-geth-rpc:8545 +L1_BEACON_URL_IN_DOCKER=http://l1-beacon-chain:3500 +BRIDGE_SERVICE=http://127.0.0.1:8080 + +# Common addresses & keys + +L1_OKB_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3 + +RICH_ADDRESS=0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 +RICH_PRIVATE_KEY=0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356 + +DEPLOYER_ADDRESS=0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534 +DEPLOYER_PRIVATE_KEY=0x815405dddb0e2a99b12af775fd2929e526704e1d1aea6a0b4e74dc33e2f7fcd2 +DEPLOYER_MNEMONIC="moment wine false celery win galaxy glide thumb tail setup choose city" + +SEQUENCER_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +SEQUENCER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +SEQUENCER_P2P_KEY=0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba + +# PP addresses & keys +AGGREGATOR_ADDRESS=0x70997970C51812dc3A010C7d01b50e0d17dc79C8 +AGGREGATOR_PRIVATE_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d + +PP_VKEY=0x00d6e4bdab9cac75a50d58262bb4e60b3107a6b61131ccdff649576c624b6fb7 + +ORACLE_ADDRESS=0x70997970c51812dc3a010c7d01b50e0d17dc79c8 + +## Predeployed in PP +TIME_LOCK_ADDRESS=0x27284DBa79e6DF953Fbd232A9d8D87029F03BBf5 +GER_MANAGER_ADDRESS=0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa +BRIDGE_ADDRESS=0xb2fAc1CE54bb9BF77A7FE106fA69F81453b72851 + +L1_ETH_ADDRESS=0x0000000000000000000000000000000000000000 +L2_WETH=0xd80e5a44dc9628fae9b432eac67873238504ea29 + +# OP addresses & keys + +BATCHER_ADDRESS=0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC +OP_BATCHER_PRIVATE_KEY=0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a + +## Same as aggregator +PROPOSER_ADDRESS=0x70997970C51812dc3A010C7d01b50e0d17dc79C8 +OP_PROPOSER_PRIVATE_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d + +OPTIMISM_PORTAL_PROXY_ADDRESS=0xc8e8b7b181db301f27aef90ed285787a3ce179e9 + +CHALLENGER_ADDRESS=0x7d18a1b858253b5588f61fb5739d52e4b84e2cda +OP_CHALLENGER_PRIVATE_KEY=0x8b3a350cf5c34c9194ca9aa3f146b2b9afed22cd83d3c5f6a3f2f243ce220c01 + +ADMIN_OWNER_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 +ADMIN_OWNER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + +# Deployed and modified in 2-deploy-op-contracts.sh +TRANSACTOR=0x0000000000000000000000000000000000000000 +SAFE_ADDRESS=0x0000000000000000000000000000000000000000 +L2OO_ADDRESS=0x0000000000000000000000000000000000000000 +DISPUTE_GAME_FACTORY_ADDRESS=0x3281215007aad854b44b6dbdb0f429e81577497f +OPCM_IMPL_ADDRESS=0x3bc5388bd43977644f73fb75c7d8d6015be71e59 +SYSTEM_CONFIG_PROXY_ADDRESS=0xabd433c36f6b2809ce238044afeb2fc48f6e6ff0 +PROXY_ADMIN=0x88c87adaf76a638cd81286b23b5830a7d6ffb80d + +# Upgrade l2 ger contract +TIME_LOCK_DELAY=70 + +# First game only for update anchor root +TEMP_MAX_CLOCK_DURATION=40 +TEMP_CLOCK_EXTENSION=5 +TEMP_GAME_WINDOW=60 + +# proof config +PROOF_MATURITY_DELAY_SECONDS=1800 + +# Game config +MAX_CLOCK_DURATION=1800 +CLOCK_EXTENSION=600 +GAME_WINDOW=10800 + +# AnchorStateRegistry config +DISPUTE_GAME_FINALITY_DELAY_SECONDS=5 + +# PreimageOracle config +CHALLENGE_PERIOD_SECONDS=30 + +# WETH config +WITHDRAWAL_DELAY_SECONDS=$MAX_CLOCK_DURATION + +# pebble by default +# if panic, try leveldb +DB_ENGINE="pebble" + +# Modified in in 5-2-migrate-op.sh +FORK_BLOCK=0 +PARENT_HASH=0x0000000000000000000000000000000000000000000000000000000000000000 +PP_RPC_URL=http://xlayer-rpc:8124 diff --git a/test-pp-op/notes.txt b/test-pp-op/notes.txt new file mode 100644 index 0000000000000..e5ade6a866676 --- /dev/null +++ b/test-pp-op/notes.txt @@ -0,0 +1,28 @@ +# op node +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"opp2p_self","params":[],"id":1}' http://localhost:9545 + +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"opp2p_peerStats","params":[],"id":1}' http://localhost:9545 + +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"admin_sequencerActive","params":[],"id":1}' http://localhost:9545 + +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"admin_stopSequencer","params":[],"id":1}' http://localhost:9545 + +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"admin_overrideLeader","params":[],"id":1}' http://localhost:9545 + + + +# op conductor +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_leader","params":[],"id":1}' http://localhost:8547 + +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_sequencerHealthy","params":[],"id":1}' http://localhost:8547 + +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_paused","params":[],"id":1}' http://localhost:8547 + +curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_resume","params":[],"id":1}' http://localhost:8547 + + + + + + + diff --git a/test-pp-op/patch/op-geth-0001-support-load-genesis-at-a-given-number.patch b/test-pp-op/patch/op-geth-0001-support-load-genesis-at-a-given-number.patch new file mode 100644 index 0000000000000..c44e001aa0fb7 --- /dev/null +++ b/test-pp-op/patch/op-geth-0001-support-load-genesis-at-a-given-number.patch @@ -0,0 +1,187 @@ +From c0308891304462768e9b1f662c35e77b614a427e Mon Sep 17 00:00:00 2001 +From: JimmyShi +Date: Tue, 8 Jul 2025 14:29:46 +0800 +Subject: [PATCH] support load genesis at a given number + +--- + core/blockchain_reader.go | 7 ++++++- + core/genesis.go | 13 ++++++++++--- + core/rawdb/accessors_chain.go | 17 +++++++++++++++++ + core/rawdb/chain_freezer.go | 6 ++++-- + core/rawdb/database.go | 36 ++++++++++++++++++++++++++++++----- + 5 files changed, 68 insertions(+), 11 deletions(-) + +diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go +index f53ddfa4c..1aa3caf90 100644 +--- a/core/blockchain_reader.go ++++ b/core/blockchain_reader.go +@@ -424,7 +424,12 @@ func (bc *BlockChain) TxIndexProgress() (TxIndexProgress, error) { + func (bc *BlockChain) HistoryPruningCutoff() (uint64, common.Hash) { + pt := bc.historyPrunePoint.Load() + if pt == nil { +- return 0, bc.genesisBlock.Hash() ++ // get genesis block number ++ genesisHash := rawdb.ReadCanonicalHash(bc.db, 0) ++ genesisHeader := rawdb.ReadHeader(bc.db, genesisHash, 0) ++ genesisBlockNumber := genesisHeader.Number.Uint64() ++ ++ return genesisBlockNumber, genesisHash + } + return pt.BlockNumber, pt.BlockHash + } +diff --git a/core/genesis.go b/core/genesis.go +index 5db5c9813..33a0f1291 100644 +--- a/core/genesis.go ++++ b/core/genesis.go +@@ -683,9 +683,9 @@ func (g *Genesis) toBlockWithRoot(stateRoot, storageRootMessagePasser common.Has + // Commit writes the block and state of a genesis specification to the database. + // The block is committed as the canonical head block. + func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Block, error) { +- if g.Number != 0 { +- return nil, errors.New("can't commit genesis block with number > 0") +- } ++ // if g.Number != 0 { ++ // return nil, errors.New("can't commit genesis block with number > 0") ++ // } + config := g.Config + if config == nil { + return nil, errors.New("invalid genesis without chain config") +@@ -727,6 +727,13 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *triedb.Database) (*types.Blo + rawdb.WriteHeadFastBlockHash(batch, block.Hash()) + rawdb.WriteHeadHeaderHash(batch, block.Hash()) + rawdb.WriteChainConfig(batch, block.Hash(), config) ++ ++ if block.NumberU64() != 0 { ++ // Also write the genesis block as number 0 ++ rawdb.WriteCanonicalHash(batch, block.Hash(), 0) ++ rawdb.WriteGenesisHeader(batch, block.Header()) ++ } ++ + return block, batch.Write() + } + +diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go +index 59c73aa99..e77733f78 100644 +--- a/core/rawdb/accessors_chain.go ++++ b/core/rawdb/accessors_chain.go +@@ -404,6 +404,23 @@ func WriteHeader(db ethdb.KeyValueWriter, header *types.Header) { + } + } + ++func WriteGenesisHeader(db ethdb.KeyValueWriter, header *types.Header) { ++ var ( ++ hash = header.Hash() ++ number = uint64(0) ++ ) ++ ++ // Write the encoded header ++ data, err := rlp.EncodeToBytes(header) ++ if err != nil { ++ log.Crit("Failed to RLP encode header", "err", err) ++ } ++ key := headerKey(number, hash) ++ if err := db.Put(key, data); err != nil { ++ log.Crit("Failed to store header", "err", err) ++ } ++} ++ + // DeleteHeader removes all block header data associated with a hash. + func DeleteHeader(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { + deleteHeaderWithoutNumber(db, hash, number) +diff --git a/core/rawdb/chain_freezer.go b/core/rawdb/chain_freezer.go +index f3c671f45..ebebc9c95 100644 +--- a/core/rawdb/chain_freezer.go ++++ b/core/rawdb/chain_freezer.go +@@ -212,7 +212,8 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) { + batch := db.NewBatch() + for i := 0; i < len(ancients); i++ { + // Always keep the genesis block in active database +- if first+uint64(i) != 0 { ++ trueGenesisNumber := getGenesisBlockNumber(db) ++ if first+uint64(i) != trueGenesisNumber { + DeleteBlockWithoutNumber(batch, ancients[i], first+uint64(i)) + DeleteCanonicalHash(batch, first+uint64(i)) + } +@@ -225,9 +226,10 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) { + // Wipe out side chains also and track dangling side chains + var dangling []common.Hash + frozen, _ = f.Ancients() // Needs reload after during freezeRange ++ trueGenesisNumber := getGenesisBlockNumber(db) + for number := first; number < frozen; number++ { + // Always keep the genesis block in active database +- if number != 0 { ++ if number != trueGenesisNumber { + dangling = ReadAllHashes(db, number) + for _, hash := range dangling { + log.Trace("Deleting side chain", "number", number, "hash", hash) +diff --git a/core/rawdb/database.go b/core/rawdb/database.go +index 7ab6dbdc6..835df8167 100644 +--- a/core/rawdb/database.go ++++ b/core/rawdb/database.go +@@ -28,10 +28,12 @@ import ( + "time" + + "github.com/ethereum/go-ethereum/common" ++ "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/ethdb/memorydb" + "github.com/ethereum/go-ethereum/log" ++ "github.com/ethereum/go-ethereum/rlp" + "github.com/olekukonko/tablewriter" + ) + +@@ -265,17 +267,19 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st + // store deletion, but that's fine). + } else { + // If the freezer is empty, ensure nothing was moved yet from the key-value +- // store, otherwise we'll end up missing data. We check block #1 to decide +- // if we froze anything previously or not, but do take care of databases with +- // only the genesis block. ++ // store, otherwise we'll end up missing data. We check the block after the ++ // true genesis block to decide if we froze anything previously or not. + if ReadHeadHeaderHash(db) != common.BytesToHash(kvgenesis) { + // Key-value store contains more data than the genesis block, make sure we + // didn't freeze anything yet. +- if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 { ++ trueGenesisNumber := getGenesisBlockNumber(db) ++ nextBlockNumber := trueGenesisNumber + 1 ++ ++ if kvblob, _ := db.Get(headerHashKey(nextBlockNumber)); len(kvblob) == 0 { + printChainMetadata(db) + return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path") + } +- // Block #1 is still in the database, we're allowed to init a new freezer ++ // Block after true genesis is still in the database, we're allowed to init a new freezer + } + // Otherwise, the head header is still the genesis, we're allowed to init a new + // freezer. +@@ -680,3 +684,25 @@ func SafeDeleteRange(db ethdb.KeyValueStore, start, end []byte, hashScheme bool, + } + return batch.Write() + } ++ ++// getGenesisBlockNumber returns the actual genesis block number from the database. ++// This is needed for custom genesis logic where the genesis block might not be at block 0. ++func getGenesisBlockNumber(db ethdb.KeyValueStore) uint64 { ++ // First check if there's a genesis block at block 0 ++ if genesisHashData, _ := db.Get(headerHashKey(0)); len(genesisHashData) > 0 { ++ genesisHash := common.BytesToHash(genesisHashData) ++ // Try to read the block header to get the number ++ if headerData, _ := db.Get(headerKey(0, genesisHash)); len(headerData) > 0 { ++ var header types.Header ++ if err := rlp.DecodeBytes(headerData, &header); err == nil { ++ // Check if this block has a custom number field ++ if header.Number.Uint64() != 0 { ++ return header.Number.Uint64() ++ } ++ } ++ } ++ } ++ ++ // If no custom number found, return 0 as default ++ return 0 ++} +-- +2.50.1 + diff --git a/test-pp-op/patch/optimism-0001-decompress-genesis.patch b/test-pp-op/patch/optimism-0001-decompress-genesis.patch new file mode 100644 index 0000000000000..9895f51016c6b --- /dev/null +++ b/test-pp-op/patch/optimism-0001-decompress-genesis.patch @@ -0,0 +1,65 @@ +From e4dc440f1d47b95d2609bbe22e06d9878bcaa59c Mon Sep 17 00:00:00 2001 +From: "xingqiang.yuan" +Date: Tue, 19 Aug 2025 22:18:30 +0800 +Subject: [PATCH] decompress genesis + +--- + op-program/chainconfig/chaincfg.go | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/op-program/chainconfig/chaincfg.go b/op-program/chainconfig/chaincfg.go +index b4ae0ff95..58fa20dbf 100644 +--- a/op-program/chainconfig/chaincfg.go ++++ b/op-program/chainconfig/chaincfg.go +@@ -1,10 +1,15 @@ + package chainconfig + + import ( ++ "bytes" ++ "compress/gzip" ++ "crypto/md5" + "embed" + "encoding/json" + "errors" + "fmt" ++ "github.com/ethereum/go-ethereum/log" ++ "io" + "os" + "strings" + +@@ -87,6 +92,20 @@ func ChainConfigByChainID(chainID eth.ChainID) (*params.ChainConfig, error) { + return chainConfigByChainID(chainID, customChainConfigFS) + } + ++func decompressGzip(data []byte) ([]byte, error) { ++ reader, err := gzip.NewReader(bytes.NewReader(data)) ++ if err != nil { ++ return nil, err ++ } ++ defer reader.Close() ++ ++ var uncompressedData bytes.Buffer ++ if _, err := io.Copy(&uncompressedData, reader); err != nil { ++ return nil, err ++ } ++ return uncompressedData.Bytes(), nil ++} ++ + func chainConfigByChainID(chainID eth.ChainID, customChainFS embed.FS) (*params.ChainConfig, error) { + // Load from custom chain configs from embed FS + data, err := customChainFS.ReadFile(fmt.Sprintf("configs/%v-genesis-l2.json", chainID)) +@@ -95,6 +114,11 @@ func chainConfigByChainID(chainID eth.ChainID, customChainFS embed.FS) (*params. + } else if err != nil { + return nil, fmt.Errorf("failed to get chain config for chain ID %v: %w", chainID, err) + } ++ data, err = decompressGzip(data) ++ if err != nil { ++ return nil, fmt.Errorf("failed to decompress for chain ID %v: %w", chainID, err) ++ } ++ log.Info("decompress genesis", "chain id", chainID, "md5 hash", md5.Sum(data)) + var genesis core.Genesis + err = json.Unmarshal(data, &genesis) + if err != nil { +-- +2.39.5 (Apple Git-154) + diff --git a/test-pp-op/patch/optimism-0001-support-regenesis-op-geth-prestate.patch b/test-pp-op/patch/optimism-0001-support-regenesis-op-geth-prestate.patch new file mode 100644 index 0000000000000..ad0dffc4ffc92 --- /dev/null +++ b/test-pp-op/patch/optimism-0001-support-regenesis-op-geth-prestate.patch @@ -0,0 +1,82 @@ +diff --git a/Makefile b/Makefile +index b7e2e8102c..76f87fc9cf 100644 +--- a/Makefile ++++ b/Makefile +@@ -13,7 +13,7 @@ help: ## Prints this help message + build: build-go build-contracts ## Builds Go components and contracts-bedrock + .PHONY: build + +-build-go: submodules op-node op-proposer op-batcher op-challenger op-dispute-mon op-program cannon ## Builds main Go components ++build-go: submodules op-node op-proposer op-batcher op-challenger op-dispute-mon op-program cannon withdrawal ## Builds main Go components + .PHONY: build-go + + build-contracts: +@@ -128,6 +128,10 @@ cannon: ## Builds cannon binary + make -C ./cannon cannon + .PHONY: cannon + ++withdrawal: ## Builds withdrawal binary ++ just $(JUSTFLAGS) ./op-chain-ops/withdrawal ++.PHONY: withdrawal ++ + reproducible-prestate: ## Builds reproducible-prestate binary + make -C ./op-program reproducible-prestate + .PHONY: reproducible-prestate +diff --git a/go.mod b/go.mod +index b09102566e..7a3fc16755 100644 +--- a/go.mod ++++ b/go.mod +@@ -304,9 +304,9 @@ require ( + rsc.io/tmplfunc v0.0.3 // indirect + ) + +-replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101511.1-dev.1.0.20250608235258-6005dd53e1b5 ++// replace github.com/ethereum/go-ethereum => github.com/ethereum-optimism/op-geth v1.101511.1-dev.1.0.20250608235258-6005dd53e1b5 + +-//replace github.com/ethereum/go-ethereum => ../op-geth ++replace github.com/ethereum/go-ethereum => ./op-geth + + // replace github.com/ethereum-optimism/superchain-registry/superchain => ../superchain-registry/superchain + +diff --git a/op-chain-ops/justfile b/op-chain-ops/justfile +index ee7efe7d6c..82ddb5467a 100644 +--- a/op-chain-ops/justfile ++++ b/op-chain-ops/justfile +@@ -12,9 +12,12 @@ _LDFLAGSSTRING := "'" + trim( + # Build ecotone-scalar binary + ecotone-scalar: (go_build "./bin/ecotone-scalar" "./cmd/ecotone-scalar" "-ldflags" _LDFLAGSSTRING) + +-# Build receipt-reference-builder binary ++# Build receipt-reference-builder binary + receipt-reference-builder: (go_build "./bin/receipt-reference-builder" "./cmd/receipt-reference-builder" "-ldflags" _LDFLAGSSTRING) + ++# Build withdrawal binary ++withdrawal: (go_build "./bin/withdrawal" "./cmd/withdrawal" "-ldflags" _LDFLAGSSTRING) ++ + # Run tests + test: (go_test "./...") + +diff --git a/op-program/Dockerfile.repro b/op-program/Dockerfile.repro +index 2f861f3b2f..b97057cd4e 100644 +--- a/op-program/Dockerfile.repro ++++ b/op-program/Dockerfile.repro +@@ -6,6 +6,7 @@ RUN apk add --no-cache make gcc musl-dev linux-headers git jq bash just + + COPY ./go.mod /app/go.mod + COPY ./go.sum /app/go.sum ++COPY ./op-geth /app/op-geth + + WORKDIR /app + +diff --git a/op-program/Dockerfile.repro.dockerignore b/op-program/Dockerfile.repro.dockerignore +index 15d6cf7638..2844c7a062 100644 +--- a/op-program/Dockerfile.repro.dockerignore ++++ b/op-program/Dockerfile.repro.dockerignore +@@ -5,6 +5,7 @@ + # internal dependencies + !cannon/ + !op-alt-da/ ++!op-geth/ + !op-node/ + !op-preimage/ + !op-program/ diff --git a/test-pp-op/patch/xlayer-bridge-service-0001-support-sync-L2-block-at-given-number.patch b/test-pp-op/patch/xlayer-bridge-service-0001-support-sync-L2-block-at-given-number.patch new file mode 100644 index 0000000000000..989533773b258 --- /dev/null +++ b/test-pp-op/patch/xlayer-bridge-service-0001-support-sync-L2-block-at-given-number.patch @@ -0,0 +1,70 @@ +From 8085cc9eae7a360862cf23472ed179cb14ab29c8 Mon Sep 17 00:00:00 2001 +From: JimmyShi +Date: Tue, 8 Jul 2025 14:27:45 +0800 +Subject: [PATCH] support sync L2 block at given number + +--- + cmd/run.go | 2 +- + config/network.go | 5 +++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/cmd/run.go b/cmd/run.go +index a49c802..da7cf69 100644 +--- a/cmd/run.go ++++ b/cmd/run.go +@@ -109,7 +109,7 @@ func start(ctx *cli.Context) error { + chSyncedL2 := make(chan uint32) + chsExitRootEvent = append(chsExitRootEvent, chExitRootEventL2) + chsSyncedL2 = append(chsSyncedL2, chSyncedL2) +- go runSynchronizer(ctx.Context, 0, bridgeController, l2EthermanClient, c.Synchronizer, storage, zkEVMClient, chExitRootEventL2, nil, chSyncedL2, []uint32{}, c.NetworkConfig.RequireSovereignChainSmcs[i]) ++ go runSynchronizer(ctx.Context, c.NetworkConfig.L2GenBlockNumber, bridgeController, l2EthermanClient, c.Synchronizer, storage, zkEVMClient, chExitRootEventL2, nil, chSyncedL2, []uint32{}, c.NetworkConfig.RequireSovereignChainSmcs[i]) + } + chSynced := make(chan uint32) + go runSynchronizer(ctx.Context, c.NetworkConfig.GenBlockNumber, bridgeController, l1Etherman, c.Synchronizer, storage, nil, nil, chsExitRootEvent, chSynced, networkIDs, false) +diff --git a/config/network.go b/config/network.go +index 4edeb4f..ae332f9 100644 +--- a/config/network.go ++++ b/config/network.go +@@ -8,6 +8,7 @@ import ( + // NetworkConfig is the configuration struct for the different environments. + type NetworkConfig struct { + GenBlockNumber uint64 ++ L2GenBlockNumber uint64 + PolygonBridgeAddress common.Address + PolygonZkEVMGlobalExitRootAddress common.Address + PolygonRollupManagerAddress common.Address +@@ -26,6 +27,7 @@ var ( + networkConfigs = map[string]NetworkConfig{ + defaultNetwork: { + GenBlockNumber: 16896718, ++ L2GenBlockNumber: 0, + PolygonBridgeAddress: common.HexToAddress("0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe"), + PolygonZkEVMGlobalExitRootAddress: common.HexToAddress("0x580bda1e7A0CFAe92Fa7F6c20A3794F169CE3CFb"), + PolygonRollupManagerAddress: common.HexToAddress("0x0000000000000000000000000000000000000000"), +@@ -37,6 +39,7 @@ var ( + + "testnet": { + GenBlockNumber: 8572995, ++ L2GenBlockNumber: 0, + PolygonBridgeAddress: common.HexToAddress("0xF6BEEeBB578e214CA9E23B0e9683454Ff88Ed2A7"), + PolygonZkEVMGlobalExitRootAddress: common.HexToAddress("0x4d9427DCA0406358445bC0a8F88C26b704004f74"), + PolygonRollupManagerAddress: common.HexToAddress("0x0000000000000000000000000000000000000000"), +@@ -47,6 +50,7 @@ var ( + }, + "internaltestnet": { + GenBlockNumber: 7674349, ++ L2GenBlockNumber: 0, + PolygonBridgeAddress: common.HexToAddress("0x47c1090bc966280000Fe4356a501f1D0887Ce840"), + PolygonZkEVMGlobalExitRootAddress: common.HexToAddress("0xA379Dd55Eb12e8FCdb467A814A15DE2b29677066"), + PolygonRollupManagerAddress: common.HexToAddress("0x0000000000000000000000000000000000000000"), +@@ -57,6 +61,7 @@ var ( + }, + "local": { + GenBlockNumber: 1, ++ L2GenBlockNumber: 0, + PolygonBridgeAddress: common.HexToAddress("0xFe12ABaa190Ef0c8638Ee0ba9F828BF41368Ca0E"), + PolygonZkEVMGlobalExitRootAddress: common.HexToAddress("0x8A791620dd6260079BF849Dc5567aDC3F2FdC318"), + PolygonRollupManagerAddress: common.HexToAddress("0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e"), +-- +2.39.5 (Apple Git-154) + diff --git a/test-pp-op/patch/xlayer-bridge-service-0002-skip-reorg-check-after-regenesis.patch b/test-pp-op/patch/xlayer-bridge-service-0002-skip-reorg-check-after-regenesis.patch new file mode 100644 index 0000000000000..c225790de1a45 --- /dev/null +++ b/test-pp-op/patch/xlayer-bridge-service-0002-skip-reorg-check-after-regenesis.patch @@ -0,0 +1,30 @@ +From 3e3c4fa34b5e51e2436ae81faaf1fad90c136d39 Mon Sep 17 00:00:00 2001 +From: KyrinCode +Date: Sat, 13 Sep 2025 00:50:53 +0800 +Subject: [PATCH 1/2] skip reorg check after regenesis + +--- + synchronizer/synchronizer.go | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go +index 5708756..96088b0 100644 +--- a/synchronizer/synchronizer.go ++++ b/synchronizer/synchronizer.go +@@ -602,6 +602,13 @@ hash and has parent. This operation has to be done until a match is found. + */ + func (s *ClientSynchronizer) checkReorg(latestStoredBlock etherman.Block, syncedBlock *etherman.Block) (*etherman.Block, error) { + // This function only needs to worry about reorgs if some of the reorganized blocks contained rollup info. ++ ++ // Skip reorg check after a regenesis ++ if latestStoredBlock.BlockNumber < s.genBlockNumber { ++ log.Debugf("NetworkID: %d, skipping reorg check after a regenesis. Latest stored block: %d, genesis block: %d", s.networkID, latestStoredBlock.BlockNumber, s.genBlockNumber) ++ return nil, nil ++ } ++ + latestStoredEthBlock := latestStoredBlock + reorgedBlock := latestStoredBlock + var depth uint64 +-- +2.39.5 (Apple Git-154) + diff --git a/test-pp-op/patch/xlayer-bridge-service-0003-skip-syncing-blocks-before-regenesis.patch b/test-pp-op/patch/xlayer-bridge-service-0003-skip-syncing-blocks-before-regenesis.patch new file mode 100644 index 0000000000000..2c105507b8897 --- /dev/null +++ b/test-pp-op/patch/xlayer-bridge-service-0003-skip-syncing-blocks-before-regenesis.patch @@ -0,0 +1,31 @@ +From 98e29ad0cf2625914c1d3b56b6ebd8648f647d49 Mon Sep 17 00:00:00 2001 +From: KyrinCode +Date: Sat, 13 Sep 2025 00:51:47 +0800 +Subject: [PATCH 2/2] skip syncing blocks before regenesis + +--- + synchronizer/synchronizer.go | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/synchronizer/synchronizer.go b/synchronizer/synchronizer.go +index 96088b0..69d8224 100644 +--- a/synchronizer/synchronizer.go ++++ b/synchronizer/synchronizer.go +@@ -128,6 +128,14 @@ func (s *ClientSynchronizer) Sync() error { + return err + } + } ++ if lastBlockSynced.BlockNumber < s.genBlockNumber { ++ log.Debugf("networkID: %d, latest stored block is before regenesis block. Setting regenesis block", s.networkID) ++ lastBlockSynced = ðerman.Block{ ++ BlockNumber: s.genBlockNumber, ++ NetworkID: s.networkID, ++ } ++ } ++ + metrics.InitializationTime(time.Since(startInitialization)) + log.Debugf("NetworkID: %d, initial lastBlockSynced: %+v", s.networkID, lastBlockSynced) + for { +-- +2.39.5 (Apple Git-154) + diff --git a/test-pp-op/scripts/active-sequencer.sh b/test-pp-op/scripts/active-sequencer.sh new file mode 100755 index 0000000000000..660143afeb01e --- /dev/null +++ b/test-pp-op/scripts/active-sequencer.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +# Function to detect leader conductor and set ports +detect_leader() { + echo "Detecting leader conductor..." + + # Check all three conductors to find the leader + for i in 1 2 3; do + CONDUCTOR_PORT=$((8546 + i)) # 8547, 8548, 8549 + SEQUENCER_PORT=$((9544 + i)) # 9545, 9546, 9547 + + IS_LEADER=$(curl -sS -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"conductor_leader","params":[],"id":1}' \ + http://localhost:$CONDUCTOR_PORT 2>/dev/null | jq -r '.result' 2>/dev/null) + + if [ "$IS_LEADER" = "true" ]; then + LEADER_CONDUCTOR_PORT=$CONDUCTOR_PORT + LEADER_SEQUENCER_PORT=$SEQUENCER_PORT + echo "Found leader: Conductor $i (conductor port: $LEADER_CONDUCTOR_PORT, sequencer port: $LEADER_SEQUENCER_PORT)" + return 0 + else + echo "Conductor $i (port $CONDUCTOR_PORT): not leader (result: $IS_LEADER)" + fi + done + + echo "Error: No leader conductor found!" + exit 1 +} + +# Detect leader conductor and set ports +detect_leader + +# 1. check connected peers +CONNECTED=$(curl -sS -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"opp2p_peerStats","params":[],"id":1}' http://localhost:$LEADER_SEQUENCER_PORT | jq .result.connected) +if (( CONNECTED < 2 )); then + echo "$CONNECTED peers connected, which is less than 2" + echo 1 +fi + +# 2. try to resume conductor if it is paused +PAUSED=$(curl -sS -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_paused","params":[],"id":1}' http://localhost:$LEADER_CONDUCTOR_PORT | jq -r .result) +if [ $PAUSED = "true" ]; then + curl -sS -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_resume","params":[],"id":1}' http://localhost:$LEADER_CONDUCTOR_PORT + PAUSED=$(curl -sS -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_paused","params":[],"id":1}' http://localhost:$LEADER_CONDUCTOR_PORT | jq -r .result) + if [ $PAUSED = "true" ]; then + echo "conductor is paused due to resume failure" + exit 1 + fi +fi + +# 3. try to start sequencer if it is stopped +ACTIVE=$(curl -sS -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"admin_sequencerActive","params":[],"id":1}' http://localhost:$LEADER_CONDUCTOR_PORT | jq -r .result) +if [ $ACTIVE = "false" ]; then + BLOCK_HASH=$(curl -sS -X POST -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",false],"id":1}' http://localhost:8123 | jq -r .result.hash) + if [ -z "$BLOCK_HASH" ] || [ "$BLOCK_HASH" = "null" ]; then + echo "Failed to get latest block hash" + exit 1 + fi + echo "Got latest block hash: $BLOCK_HASH" + + # 3. Start sequencer with the block hash + curl -sS -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"admin_startSequencer","params":["'"$BLOCK_HASH"'"],"id":1}' http://localhost:$LEADER_SEQUENCER_PORT + if [ $? -ne 0 ]; then + echo "Failed to start sequencer" + exit 1 + fi +fi + +# 4. verify sequencer is active +sleep 1 +ACTIVE=$(curl -sS -X POST -H 'Content-Type: application/json' --data '{"jsonrpc":"2.0","method":"admin_sequencerActive","params":[],"id":1}' http://localhost:$LEADER_SEQUENCER_PORT | jq -r .result) +if [ "$ACTIVE" != "true" ]; then + echo "Failed to activate sequencer" + exit 1 +fi + +echo "Sequencer successfully activated" + +# 5. try to add other two conductors to raft consensus cluster +SERVER_COUNT=$(curl -sS -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_clusterMembership","params":[],"id":1}' http://localhost:$LEADER_CONDUCTOR_PORT | jq '.result.servers | length') +if (( $SERVER_COUNT < 3 )); then + curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_addServerAsVoter","params":["conductor-2", "op-conductor2:50050", 0],"id":1}' http://localhost:$LEADER_CONDUCTOR_PORT + curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_addServerAsVoter","params":["conductor-3", "op-conductor3:50050", 0],"id":1}' http://localhost:$LEADER_CONDUCTOR_PORT + SERVER_COUNT=$(curl -sS -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_clusterMembership","params":[],"id":1}' http://localhost:$LEADER_CONDUCTOR_PORT | jq '.result.servers | length') + if (( $SERVER_COUNT != 3 )); then + echo "unexpected server count, expected: 3, real: $SERVER_COUNT" + exit 1 + fi + + echo "add 2 new voters to raft consensus cluster successfully!" +fi diff --git a/test-pp-op/scripts/add-game-type.sh b/test-pp-op/scripts/add-game-type.sh new file mode 100755 index 0000000000000..4ae3e209b6c6b --- /dev/null +++ b/test-pp-op/scripts/add-game-type.sh @@ -0,0 +1,192 @@ +#!/bin/bash + +set -e + +# Source environment variables +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ENV_FILE="$(dirname "$SCRIPT_DIR")/.env" +source "$ENV_FILE" + +# Function to set respected game type +set_respected_game_type() { + local GAME_TYPE=${1:-0} # Default to game type 0 + + echo "=== Setting Respected Game Type to $GAME_TYPE ===" + + # Get contract addresses + echo " ๐Ÿ“‹ Gathering contract addresses..." + DISPUTE_GAME_FACTORY_ADDR=$(cast call --rpc-url $L1_RPC_URL $SYSTEM_CONFIG_PROXY_ADDRESS 'disputeGameFactory()(address)') + OPTIMISM_PORTAL_ADDR=$(cast call --rpc-url $L1_RPC_URL $SYSTEM_CONFIG_PROXY_ADDRESS 'optimismPortal()(address)') + ANCHOR_STATE_REGISTRY_ADDR=$(cast call --rpc-url $L1_RPC_URL $OPTIMISM_PORTAL_ADDR 'anchorStateRegistry()(address)') + GAME_ADDR=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY_ADDR 'gameImpls(uint32)(address)' $GAME_TYPE) + + echo "Contract addresses:" + echo " Dispute Game Factory: $DISPUTE_GAME_FACTORY_ADDR" + echo " Optimism Portal: $OPTIMISM_PORTAL_ADDR" + echo " Anchor State Registry: $ANCHOR_STATE_REGISTRY_ADDR" + echo " Game Implementation ($GAME_TYPE): $GAME_ADDR" + echo "" + + # Execute transaction and capture output + echo "Setting respected game type to $GAME_TYPE..." + # Use --legacy to force Type 0 transactions, avoiding EIP-1559 gas estimation issues on local testnet + TX_OUTPUT=$(cast send \ + --json \ + --legacy \ + --rpc-url $L1_RPC_URL \ + --private-key $DEPLOYER_PRIVATE_KEY \ + --from $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY) \ + $ANCHOR_STATE_REGISTRY_ADDR \ + 'setRespectedGameType(uint32)' \ + $GAME_TYPE) + + # Extract transaction hash and status + TX_HASH=$(echo "$TX_OUTPUT" | jq -r '.transactionHash // empty') + TX_STATUS=$(echo "$TX_OUTPUT" | jq -r '.status // empty') + + echo "Transaction sent, TX_HASH: $TX_HASH" + + # Check if transaction was successful + if [ "$TX_STATUS" = "0x1" ] || [ "$TX_STATUS" = "1" ]; then + echo " โœ… setRespectedGameType completed successfully" + else + echo " โŒ Transaction failed with status: $TX_STATUS" + echo "Full output: $TX_OUTPUT" + exit 1 + fi +} + +# Function to add game type via Transactor +add_game_type_via_transactor() { + # Check parameter count + if [ $# -ne 5 ]; then + echo "Error: add_game_type_via_transactor requires exactly 5 parameters" + echo "Usage: add_game_type_via_transactor " + echo "Example: add_game_type_via_transactor 2 true 600 1800 0x..." + return 1 + fi + + local GAME_TYPE=$1 + local IS_PERMISSIONED=$2 + local CLOCK_EXTENSION_VAL=$3 + local MAX_CLOCK_DURATION_VAL=$4 + local ABSOLUTE_PRESTATE_VAL=$5 + + echo "=== Adding Game Type $GAME_TYPE via Transactor ===" + echo " Game Type: $GAME_TYPE" + echo " Is Permissioned: $IS_PERMISSIONED" + echo " Clock Extension: $CLOCK_EXTENSION_VAL" + echo " Max Clock Duration: $MAX_CLOCK_DURATION_VAL" + echo "" + + # Get dispute game factory address + DISPUTE_GAME_FACTORY=$(cast call --rpc-url $L1_RPC_URL $SYSTEM_CONFIG_PROXY_ADDRESS 'disputeGameFactory()(address)') + + echo "Debug Info:" + echo " State JSON: $STATE_JSON_PATH" + echo " Dispute Game Factory: $DISPUTE_GAME_FACTORY" + echo " System Config: $SYSTEM_CONFIG_PROXY_ADDRESS" + echo " Proxy Admin: $PROXY_ADMIN" + echo " OPCM: $OPCM_IMPL_ADDRESS" + echo " Transactor: $TRANSACTOR" + echo " RPC URL: $L1_RPC_URL" + echo " Sender: $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY)" + echo "" + + # Retrieve existing permissioned game implementation for parameters + echo "Retrieving permissioned game parameters..." + PERMISSIONED_GAME=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY 'gameImpls(uint32)(address)' 1) + echo "Permissioned Game Implementation: $PERMISSIONED_GAME" + + if [ "$PERMISSIONED_GAME" == "0x0000000000000000000000000000000000000000" ]; then + echo "Error: No permissioned game found. Cannot retrieve parameters." + exit 1 + fi + + # Retrieve parameters from existing permissioned game + ABSOLUTE_PRESTATE="$ABSOLUTE_PRESTATE_VAL" + MAX_GAME_DEPTH=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME 'maxGameDepth()') + SPLIT_DEPTH=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME 'splitDepth()') + VM=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME 'vm()(address)') + + echo "Retrieved parameters:" + echo " Absolute Prestate: $ABSOLUTE_PRESTATE" + echo " Max Game Depth: $MAX_GAME_DEPTH" + echo " Split Depth: $SPLIT_DEPTH" + echo " Clock Extension: $CLOCK_EXTENSION_VAL" + echo " Max Clock Duration: $MAX_CLOCK_DURATION_VAL" + echo " VM: $VM" + echo "" + + # Set constants + INITIAL_BOND='1000000000000000000' # 1 ETH in wei + SALT_MIXER='123' # Unique salt for game type + + echo "Creating addGameType calldata..." + + # Build game type parameters array (simplified) + GAME_PARAMS="[(\"$SALT_MIXER\",$SYSTEM_CONFIG_PROXY_ADDRESS,$PROXY_ADMIN,0x0000000000000000000000000000000000000000,$GAME_TYPE,$ABSOLUTE_PRESTATE,$MAX_GAME_DEPTH,$SPLIT_DEPTH,$CLOCK_EXTENSION_VAL,$MAX_CLOCK_DURATION_VAL,$INITIAL_BOND,$VM,$IS_PERMISSIONED)]" + + echo "Parameters prepared for addGameType" + + # Execute the transaction through Transactor + echo "Executing transaction via Transactor..." + echo "Target: $TRANSACTOR" + echo "From: $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY)" + + # Simplified DELEGATECALL - build calldata first, then call + ADDGAMETYPE_CALLDATA=$(cast calldata 'addGameType((string,address,address,address,uint32,bytes32,uint256,uint256,uint64,uint64,uint256,address,bool)[])' "$GAME_PARAMS") + + # Execute transaction and capture output + # Use --legacy to force Type 0 transactions, avoiding EIP-1559 gas estimation issues on local testnet + TX_OUTPUT=$(cast send \ + --json \ + --legacy \ + --rpc-url $L1_RPC_URL \ + --private-key $DEPLOYER_PRIVATE_KEY \ + --from $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY) \ + $TRANSACTOR \ + 'DELEGATECALL(address,bytes)' \ + $OPCM_IMPL_ADDRESS \ + $ADDGAMETYPE_CALLDATA) + + # Extract transaction hash and status + TX_HASH=$(echo "$TX_OUTPUT" | jq -r '.transactionHash // empty') + TX_STATUS=$(echo "$TX_OUTPUT" | jq -r '.status // empty') + + echo "" + echo "Transaction sent, TX_HASH: $TX_HASH" + + # Check if transaction was successful + if [ "$TX_STATUS" = "0x1" ] || [ "$TX_STATUS" = "1" ]; then + echo " โœ… Transaction successful!" + else + echo " โŒ Transaction failed with status: $TX_STATUS" + echo "Full output: $TX_OUTPUT" + exit 1 + fi + echo "" + + # Verify the new game type was added + echo "Verifying new game type was added..." + NEW_GAME_IMPL=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY 'gameImpls(uint32)(address)' $GAME_TYPE) + + if [ "$NEW_GAME_IMPL" != "0x0000000000000000000000000000000000000000" ]; then + echo " โœ… Success! New game type $GAME_TYPE added." + echo "Game Type $GAME_TYPE Implementation: $NEW_GAME_IMPL" + else + echo " โŒ Warning: Could not verify game type was added. Check transaction status." + fi + + echo " โœ… AddGameType operations completed successfully" + + # Set the newly added game type as respected + echo "" + set_respected_game_type "$GAME_TYPE" +} + +# Main execution +if [ "${BASH_SOURCE[0]}" == "${0}" ]; then + # Script is being executed directly - call the function + add_game_type_via_transactor "$@" +fi diff --git a/test-pp-op/scripts/deposit-from-banker.sh b/test-pp-op/scripts/deposit-from-banker.sh new file mode 100755 index 0000000000000..db1e6601efc9f --- /dev/null +++ b/test-pp-op/scripts/deposit-from-banker.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e +set -x + +BANKER_PRIVATE_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d +BANKER=$(cast wallet a $BANKER_PRIVATE_KEY) + +# Source environment variables +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ENV_FILE="$(dirname "$SCRIPT_DIR")/.env" +source "$ENV_FILE" + +TO_ADDRESS=0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534 +AMOUNT=1000000ether + +cast send $TO_ADDRESS --value $AMOUNT --legacy --rpc-url=$L2_RPC_URL --private-key=$BANKER_PRIVATE_KEY diff --git a/test-pp-op/scripts/deposit-from-l1.sh b/test-pp-op/scripts/deposit-from-l1.sh new file mode 100755 index 0000000000000..e8cd0edc996fc --- /dev/null +++ b/test-pp-op/scripts/deposit-from-l1.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -e + +# Source environment variables +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ENV_FILE="$(dirname "$SCRIPT_DIR")/.env" +source "$ENV_FILE" + +OP_PORTAL_ADDRESS=$(jq -r '.opChainDeployments[0].OptimismPortalProxy' config-op/state.json) +PRIVATE_KEY="0x815405dddb0e2a99b12af775fd2929e526704e1d1aea6a0b4e74dc33e2f7fcd2" +ADDRESS=$(cast wallet a $PRIVATE_KEY) #0x8f8E2d6cF621f30e9a11309D6A56A876281Fd534 +ETHER=1000000000000000000 +AMOUNT=$(python3 -c "print(3000 * $ETHER)") +AMOUNT_PLUS_FEE=$(python3 -c "print($AMOUNT + $ETHER)") + +cast send --private-key $RICH_L1_PRIVATE_KEY --value $AMOUNT_PLUS_FEE $ADDRESS --legacy --rpc-url $L1_RPC_URL + +PRE_BALANCE=$(cast balance $ADDRESS --rpc-url=$L2_RPC_URL) + +cast send \ + --legacy \ + --private-key $PRIVATE_KEY \ + --value $AMOUNT \ + $OP_PORTAL_ADDRESS \ + 'function depositTransaction(address _target, uint256 _value, uint64 _gasLimit, bool _isCreation, bytes _data)' \ + $ADDRESS $AMOUNT 100000 false 0x --rpc-url $L1_RPC_URL + +echo " ๐Ÿ“‹ Initial balance: $PRE_BALANCE" + +START_TIME=$(date +%s) + +while true; do + NEW_BALANCE=$(cast balance $ADDRESS --rpc-url=$L2_RPC_URL) + + if [ "$NEW_BALANCE" != "$PRE_BALANCE" ]; then + CURRENT_TIME=$(date +%s) + ELAPSED_TIME=$((CURRENT_TIME - START_TIME)) + echo " โœ… Balance changed!" + echo " ๐Ÿ“‹ Previous balance: $PRE_BALANCE" + echo " ๐Ÿ“‹ New balance: $NEW_BALANCE" + echo " โฑ๏ธ Total wait time: ${ELAPSED_TIME}s" + break + fi + + echo " โณ waiting for change..." + sleep 3 +done diff --git a/test-pp-op/scripts/docker-install-start.sh b/test-pp-op/scripts/docker-install-start.sh new file mode 100755 index 0000000000000..27177b7171ce4 --- /dev/null +++ b/test-pp-op/scripts/docker-install-start.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Install Docker in Docker and start Docker daemon + +# If default (rooted Docker) is used, just exit +if [ "$1" == "default" ]; then + exit 0 +fi + +# Otherwise (rootless Docker): remove docker.io, install and configure Docker in Docker +apt-get update +apt-get remove -y --purge docker.io + +curl -sSL https://get.docker.com/ | sh + +# The code below is taken from: https://github.com/moby/moby/blob/v26.0.1/hack/dind#L59 +# It is used to avoid the error: "docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: unable to apply cgroup configuration: cannot enter cgroupv2 "/sys/fs/cgroup/docker" with domain controllers -- it is in threaded mode: unknown." +# cgroup v2: enable nesting +if [ -f /sys/fs/cgroup/cgroup.controllers ]; then + # move the processes from the root group to the /init group, + # otherwise writing subtree_control fails with EBUSY. + # An error during moving non-existent process (i.e., "cat") is ignored. + mkdir -p /sys/fs/cgroup/init + xargs -rn1 < /sys/fs/cgroup/cgroup.procs > /sys/fs/cgroup/init/cgroup.procs || : + # enable controllers + sed -e 's/ / +/g' -e 's/^/+/' < /sys/fs/cgroup/cgroup.controllers \ + > /sys/fs/cgroup/cgroup.subtree_control +fi + +# Start Docker daemon +dockerd > /dockerd.log 2>&1 & diff --git a/test-pp-op/scripts/gray-upgrade-simulation.sh b/test-pp-op/scripts/gray-upgrade-simulation.sh new file mode 100755 index 0000000000000..8bdcb60ab32bb --- /dev/null +++ b/test-pp-op/scripts/gray-upgrade-simulation.sh @@ -0,0 +1,309 @@ +#!/bin/bash + +set -e + +BASE_CONDUCTOR_PORT=8547 +BASE_SEQUENCER_PORT=9545 +CURRENT_LEADER=0 +UPGRADED_SEQUENCER=0 + +# Function to check if a conductor is leader +check_leader() { + local conductor_id=$1 + local port=$((BASE_CONDUCTOR_PORT + conductor_id - 1)) + curl -s -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"conductor_leader","params":[],"id":1}' \ + http://localhost:$port | jq -r .result +} + +# Function to stop containers +stop_containers() { + local sequencer_id=$1 + echo "Stopping containers for sequencer-$sequencer_id..." + + # Handle sequencer 1 (no suffix) vs others (with suffix) + if [ "$sequencer_id" = "1" ]; then + docker stop op-seq op-geth-seq 2>/dev/null || true + echo "Containers stopped: op-seq, op-geth-seq" + else + docker stop op-seq$sequencer_id op-geth-seq$sequencer_id 2>/dev/null || true + echo "Containers stopped: op-seq$sequencer_id, op-geth-seq$sequencer_id" + fi +} + +# Function to start containers +start_containers() { + local sequencer_id=$1 + echo "Starting containers for sequencer-$sequencer_id..." + + # Handle sequencer 1 (no suffix) vs others (with suffix) + if [ "$sequencer_id" = "1" ]; then + docker start op-seq op-geth-seq 2>/dev/null || true + echo "Containers started: op-seq, op-geth-seq" + else + docker start op-seq$sequencer_id op-geth-seq$sequencer_id 2>/dev/null || true + echo "Containers started: op-seq$sequencer_id, op-geth-seq$sequencer_id" + fi +} + +# Function to wait for service to be ready +wait_for_service() { + local port=$1 + local service_name=$2 + local max_attempts=30 + local attempt=0 + + echo "Waiting for $service_name to be ready on port $port..." + while [ $attempt -lt $max_attempts ]; do + if curl -s http://localhost:$port > /dev/null 2>&1; then + echo "$service_name is ready" + return 0 + fi + sleep 1 + ((attempt++)) + done + echo "Warning: $service_name not ready after $max_attempts seconds" + return 1 +} + +# Function to find current leader +find_current_leader() { + for i in {0..2}; do + local port=$((BASE_CONDUCTOR_PORT + i)) + local is_leader=$(check_leader $((i+1))) + + if [ "$is_leader" = "true" ]; then + CURRENT_LEADER=$((i+1)) + echo "conductor-$CURRENT_LEADER is current leader (port $port)" + return 0 + fi + done + echo "No leader found!" + return 1 +} + +# Function to extract block info from sequencer logs +extract_last_block_info() { + local sequencer_id=$1 + + # Handle sequencer 1 (no suffix) vs others (with suffix) + local container_name + if [ "$sequencer_id" = "1" ]; then + container_name="op-seq" + else + container_name="op-seq$sequencer_id" + fi + + echo "Extracting last block info from $container_name..." >&2 + + # Get the last "Sequencer inserted block" log entry + local last_block_log=$(docker logs $container_name 2>&1 | grep "Sequencer inserted block" | tail -1) + + if [ -z "$last_block_log" ]; then + echo "โŒ No 'Sequencer inserted block' log found in $container_name" >&2 + return 1 + fi + + echo "Last block log: $last_block_log" >&2 + + # Extract block hash and number using regex + if [[ $last_block_log =~ block=([^[:space:]]+) ]]; then + local block_info="${BASH_REMATCH[1]}" + echo "Block info: $block_info" >&2 + + # Split block hash and number (format: hash:number) + if [[ $block_info =~ ^([^:]+):([0-9]+)$ ]]; then + local block_hash="${BASH_REMATCH[1]}" + local block_number="${BASH_REMATCH[2]}" + echo "Extracted - Block Hash: $block_hash, Block Number: $block_number" >&2 + echo "$block_hash:$block_number" + return 0 + else + echo "โŒ Failed to parse block info format: $block_info" >&2 + return 1 + fi + else + echo "โŒ Failed to extract block info from log: $last_block_log" >&2 + return 1 + fi +} + +# Function to check if new leader continues from previous block +check_block_continuity() { + local prev_sequencer_id=$1 + local new_sequencer_id=$2 + local prev_block_info=$3 + + echo "Checking block continuity from sequencer-$prev_sequencer_id to sequencer-$new_sequencer_id..." + echo "Previous block info: $prev_block_info" + + # Parse previous block info + local prev_block_hash=$(echo "$prev_block_info" | cut -d':' -f1) + local prev_block_number=$(echo "$prev_block_info" | cut -d':' -f2) + + echo "Looking for block with parent=$prev_block_hash:$prev_block_number in sequencer-$new_sequencer_id..." + + # Check if new sequencer has a block with the previous block as parent + local container_name + if [ "$new_sequencer_id" = "1" ]; then + container_name="op-seq" + else + container_name="op-seq$new_sequencer_id" + fi + local continuity_log=$(docker logs $container_name 2>&1 | grep "Sequencer inserted block" | grep "parent=$prev_block_hash:$prev_block_number" | tail -1) + + if [ -n "$continuity_log" ]; then + echo "โœ… Block continuity verified!" + echo "Continuity log: $continuity_log" + + # Extract the new block info + if [[ $continuity_log =~ block=([^[:space:]]+) ]]; then + local new_block_info="${BASH_REMATCH[1]}" + echo "New block info: $new_block_info" + return 0 + fi + else + echo "โŒ Block continuity check failed - no block found with parent=$prev_block_hash:$prev_block_number" + return 1 + fi +} + +# Function to transfer leadership +transfer_leadership() { + local from_conductor=$1 + local to_conductor=$2 + local from_port=$((BASE_CONDUCTOR_PORT + from_conductor - 1)) + + # Build target conductor address + local target_addr="op-conductor" + [ "$to_conductor" != "1" ] && target_addr="${target_addr}${to_conductor}" + target_addr="${target_addr}:50050" + + echo "Transferring leadership from conductor-$from_conductor to conductor-$to_conductor..." + curl -s -X POST -H "Content-Type: application/json" \ + --data "{\"jsonrpc\":\"2.0\",\"method\":\"conductor_transferLeaderToServer\",\"params\":[\"conductor-$to_conductor\", \"$target_addr\"],\"id\":1}" \ + http://localhost:$from_port > /dev/null + echo "Leadership transfer command sent" +} + +echo "=== Starting Gray Upgrade Simulation ===" + +# Step 1: Find current leader +echo "Step 1: Finding current leader..." +if ! find_current_leader; then + echo "Error: No leader found, exiting" + exit 1 +fi + +# Step 2: Select a follower sequencer for upgrade +echo "Step 2: Selecting a follower sequencer for upgrade..." +# Find a follower (non-leader) sequencer to upgrade +UPGRADED_SEQUENCER=0 +for i in {1..3}; do + if [ "$i" != "$CURRENT_LEADER" ]; then + UPGRADED_SEQUENCER=$i + echo "Selected sequencer-$UPGRADED_SEQUENCER for upgrade (current leader is sequencer-$CURRENT_LEADER)" + break + fi +done + +if [ "$UPGRADED_SEQUENCER" -eq 0 ]; then + echo "Error: No follower sequencer found for upgrade" + exit 1 +fi + +# Step 3: Stop containers for the selected follower sequencer +echo "Step 3: Stopping containers for sequencer-$UPGRADED_SEQUENCER (simulating shutdown for upgrade)..." +stop_containers $UPGRADED_SEQUENCER + +# Step 4: Wait 10 seconds (simulating upgrade time) +echo "Step 4: Waiting 10 seconds for upgrade simulation..." +sleep 10 + +# Step 5: Restart containers +echo "Step 5: Restarting containers for sequencer-$UPGRADED_SEQUENCER (simulating post-upgrade restart)..." +start_containers $UPGRADED_SEQUENCER + +# Step 6: Wait for services to be ready +echo "Step 6: Waiting for services to be ready..." +wait_for_service $((BASE_SEQUENCER_PORT + UPGRADED_SEQUENCER - 1)) "op-seq$UPGRADED_SEQUENCER" +wait_for_service $((BASE_CONDUCTOR_PORT + UPGRADED_SEQUENCER - 1)) "op-conductor$UPGRADED_SEQUENCER" + +# Step 7: Verify the upgraded sequencer is inactive +echo "Step 7: Verifying upgraded sequencer is inactive..." +sleep 5 # Give it time to sync +is_leader_after_restart=$(check_leader $UPGRADED_SEQUENCER) + +if [ "$is_leader_after_restart" = "false" ]; then + echo "โœ… Verified: Upgraded sequencer-$UPGRADED_SEQUENCER is inactive (not leader)" +else + echo "โŒ Error: Upgraded sequencer-$UPGRADED_SEQUENCER is unexpectedly still leader" + exit 1 +fi +# Step 8: Wait for the upgraded sequencer to sync with latest blocks +echo "Step 8: Waiting 30 seconds for upgraded sequencer to sync with latest blocks..." +sleep 30 + +# Step 9: Find current leader and transfer leadership +echo "Step 9: Finding current leader and transferring leadership to upgraded sequencer..." +if ! find_current_leader; then + echo "Error: No current leader found for transfer" + exit 1 +fi + +if [ "$CURRENT_LEADER" = "$UPGRADED_SEQUENCER" ]; then + echo "โœ… Upgraded sequencer-$UPGRADED_SEQUENCER is already the leader, no transfer needed" +else + echo "Current leader is conductor-$CURRENT_LEADER, transferring to conductor-$UPGRADED_SEQUENCER" + + # Transfer leadership to the upgraded sequencer + transfer_leadership $CURRENT_LEADER $UPGRADED_SEQUENCER + + # Verify the transfer was successful + sleep 2 + echo "Verifying leadership transfer..." + is_transfer_successful=$(check_leader $UPGRADED_SEQUENCER) + if [ "$is_transfer_successful" = "true" ]; then + echo "โœ… Leadership transfer successful: conductor-$CURRENT_LEADER -> conductor-$UPGRADED_SEQUENCER" + + # Extract block info from previous leader AFTER transfer is confirmed + echo "Extracting block info from previous leader (sequencer-$CURRENT_LEADER) after final transfer..." + if ! CURRENT_BLOCK_INFO=$(extract_last_block_info $CURRENT_LEADER); then + echo "Warning: Could not extract block info from sequencer-$CURRENT_LEADER, continuing without continuity check" + CURRENT_BLOCK_INFO="" + fi + + # Check block continuity if we have current block info + if [ -n "$CURRENT_BLOCK_INFO" ]; then + echo "Checking block continuity after leadership transfer..." + sleep 3 # Give some time for upgraded sequencer to produce blocks + if check_block_continuity $CURRENT_LEADER $UPGRADED_SEQUENCER "$CURRENT_BLOCK_INFO"; then + echo "โœ… Block continuity verified after leadership transfer" + else + echo "โš ๏ธ Block continuity check failed after transfer, but upgrade simulation continues" + fi + fi + else + echo "โŒ Leadership transfer failed, trying to find current leader..." + if find_current_leader; then + echo "Current leader is now conductor-$CURRENT_LEADER" + else + echo "Error: No leader found after transfer attempt" + exit 1 + fi + fi +fi + +# Step 10: Final verification +echo "Step 10: Final verification of upgraded sequencer leadership..." +sleep 1 + +is_leader_final=$(check_leader $UPGRADED_SEQUENCER) +if [ "$is_leader_final" = "true" ]; then + echo "โœ… SUCCESS: Upgraded sequencer-$UPGRADED_SEQUENCER is now the leader!" + echo "=== Gray Upgrade Simulation Completed Successfully ===" +else + echo "โŒ FAILED: Upgraded sequencer-$UPGRADED_SEQUENCER did not become leader" + echo "Final leader status: $is_leader_final" + exit 1 +fi diff --git a/test-pp-op/scripts/replace-genesis.sh b/test-pp-op/scripts/replace-genesis.sh new file mode 100755 index 0000000000000..e7817d13ae47f --- /dev/null +++ b/test-pp-op/scripts/replace-genesis.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -e + +sed_inplace() { + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "$@" + else + sed -i "$@" + fi +} + +ROOT_DIR=$(git rev-parse --show-toplevel) + +# TODO: change to the real location of genesis file +NEW_GENESIS_FILE="$ROOT_DIR/../genesis.json" + +TESTING_GENESIS_FILE="$ROOT_DIR/test/config-op/genesis.json" + +if [ -f ${TESTING_GENESIS_FILE} ]; then + mv ${TESTING_GENESIS_FILE} ${TESTING_GENESIS_FILE}.bak +fi + +cp ${NEW_GENESIS_FILE} ${TESTING_GENESIS_FILE} + +current_timestamp=$(date +%s) +hex_timestamp=$(printf "0x%x\n" "$current_timestamp") +echo "hex_timestamp: $hex_timestamp" + +sed_inplace "s/\"timestamp\": \"0x[0-9a-fA-F]*\"/\"timestamp\": \"$hex_timestamp\"/" ${TESTING_GENESIS_FILE} diff --git a/test-pp-op/scripts/show-dev-accounts.sh b/test-pp-op/scripts/show-dev-accounts.sh new file mode 100755 index 0000000000000..40f4346e5b25b --- /dev/null +++ b/test-pp-op/scripts/show-dev-accounts.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +echo "=== Optimism dev accounts ===" +echo "mnemonic: test test test test test test test test test test test junk" +echo "" + +for i in {0..29}; do + echo "path $i: m/44'/60'/0'/0/$i" + + private_key=$(cast wallet private-key --mnemonic "test test test test test test test test test test test junk" --mnemonic-derivation-path "m/44'/60'/0'/0/$i") + + address=$(cast wallet address --private-key "$private_key") + + echo "address: $address" + echo "private key: $private_key" + echo "---" +done diff --git a/test-pp-op/scripts/stop-leader-sequencer.sh b/test-pp-op/scripts/stop-leader-sequencer.sh new file mode 100755 index 0000000000000..99912e828fbaf --- /dev/null +++ b/test-pp-op/scripts/stop-leader-sequencer.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +BASE_PORT=8547 +LEADER_PORT=0 +OLD_LEADER=0 + +# Find current leader +for i in {0..2}; do + PORT=$((BASE_PORT + i)) + IS_LEADER=$(curl -s -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"conductor_leader","params":[],"id":1}' \ + http://localhost:$PORT | jq -r .result) + + if [ "$IS_LEADER" = "true" ]; then + LEADER_PORT=$PORT + OLD_LEADER=$((i+1)) + echo "conductor-$OLD_LEADER is current leader (port $PORT)" + break + fi +done + +# Stop leader's sequencer +if [ "$LEADER_PORT" != "0" ]; then + SEQUENCER_PORT=$((9545 + OLD_LEADER -1)) + curl -sS -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"admin_stopSequencer","params":[],"id":1}' http://localhost:$SEQUENCER_PORT > /dev/null + echo "sequencer stopped, waiting for leader transfer..." + + # Wait and check for leader change every second + echo "Waiting for leader transfer..." + MAX_SECONDS=10 + for ((second=1; second<=MAX_SECONDS; second++)); do + sleep 1 + NEW_LEADER=0 + for i in {0..2}; do + PORT=$((BASE_PORT + i)) + IS_LEADER=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_leader","params":[],"id":1}' http://localhost:$PORT | jq -r .result) + if [ "$IS_LEADER" = "true" ]; then + NEW_LEADER=$((i+1)) + if [ "$NEW_LEADER" != "$OLD_LEADER" ]; then + echo "Leadership transferred: conductor-$OLD_LEADER -> conductor-$NEW_LEADER in (${second}s)" + exit 0 + fi + fi + done + done + echo "Warning: Leader transfer not detected after $MAX_SECONDS seconds" +fi diff --git a/test-pp-op/scripts/transfer-leader.sh b/test-pp-op/scripts/transfer-leader.sh new file mode 100755 index 0000000000000..ef1a34eeb3f73 --- /dev/null +++ b/test-pp-op/scripts/transfer-leader.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +BASE_PORT=8547 +LEADER_PORT=0 +OLD_LEADER=0 + +# Find leader +for i in {0..2}; do + PORT=$((BASE_PORT + i)) + IS_LEADER=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_leader","params":[],"id":1}' http://localhost:$PORT | jq -r .result) + if [ "$IS_LEADER" = "true" ]; then + LEADER_PORT=$PORT + OLD_LEADER=$((i+1)) + echo "conductor-$OLD_LEADER is leader (port $PORT)" + break + fi +done + +# Transfer leadership +if [ "$LEADER_PORT" != "0" ]; then + echo "Transferring leadership..." + if [ -n "$1" ] && [ "$1" -ge 1 ] && [ "$1" -le 3 ]; then + # Transfer to specific node + TARGET_NUM=$1 + # Check if target is current leader + if [ "$TARGET_NUM" = "$OLD_LEADER" ]; then + echo "Error: conductor-$TARGET_NUM is already the leader" + exit 1 + fi + ADDR="op-conductor" + [ "$TARGET_NUM" != "1" ] && ADDR="${ADDR}${TARGET_NUM}" + curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_transferLeaderToServer","params":["conductor-'$TARGET_NUM'", "'$ADDR':50050"],"id":1}' http://localhost:$LEADER_PORT >/dev/null + # Check if leader transferred to target node + sleep 1 + NEW_LEADER=$(curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_leader","params":[],"id":1}' http://localhost:$((BASE_PORT + TARGET_NUM - 1)) | jq -r .result) + if [ "$NEW_LEADER" = "true" ]; then + echo "Leadership transferred: conductor-$OLD_LEADER -> conductor-$TARGET_NUM" + else + echo "Failed to transfer leadership from conductor-$OLD_LEADER to conductor-$TARGET_NUM" + fi + else + # Auto select target node + curl -s -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"conductor_transferLeader","params":[],"id":1}' http://localhost:$LEADER_PORT > /dev/null + # Find new leader + sleep 1 + echo "Checking new leader..." + for i in {0..2}; do + PORT=$((BASE_PORT + i)) + IS_LEADER=$(curl -s -X POST -H "Content-Type: application/json" \ + --data '{"jsonrpc":"2.0","method":"conductor_leader","params":[],"id":1}' \ + http://localhost:$PORT | jq -r .result) + + if [ "$IS_LEADER" = "true" ]; then + echo "Leadership transferred: conductor-$OLD_LEADER -> conductor-$((i+1))" + break + fi + done + fi +fi diff --git a/test-pp-op/tools.sh b/test-pp-op/tools.sh new file mode 100644 index 0000000000000..b3f3f6c7bb9a1 --- /dev/null +++ b/test-pp-op/tools.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# Strict mode: exit on command failure or undefined variable +set -eu + +# ============================================================================= +# This script performs checks tools required in linux/mac +# ============================================================================= + +# Check if jq is available for JSON parsing +if ! command -v jq >/dev/null 2>&1; then + echo "โŒ jq is required but not installed. Please install jq to parse JSON config files." + exit 1 +fi + +# check md5sum +if [[ "$OSTYPE" == "darwin"* ]]; then + MD5SUM_CMD=md5 +else + MD5SUM_CMD=md5sum +fi + +if [ "$ENV" = "local" ]; then + COMPOSE_FILE=docker-compose-local.yml +else + COMPOSE_FILE=docker-compose.yml +fi + +echo "COMPOSE_FILE: ${COMPOSE_FILE}" +DOCKER_COMPOSE=$(docker compose version >/dev/null 2>&1 && echo "docker compose" || echo "docker-compose") +DOCKER_COMPOSE_CMD="${DOCKER_COMPOSE} -f ${COMPOSE_FILE}" +echo "DOCKER_COMPOSE_CMD: ${DOCKER_COMPOSE_CMD}" diff --git a/test-pp-op/utils.sh b/test-pp-op/utils.sh new file mode 100644 index 0000000000000..a1d3d2d8ccd9f --- /dev/null +++ b/test-pp-op/utils.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e +set -x + +# init-erigon.sh runs outside the container. +ROOT_DIR=$(which git &>/dev/null && git rev-parse --show-toplevel || echo "/data") +PWD_DIR="$(pwd)" +TMP_DIR="$PWD_DIR/tmp" + +sed_inplace() { + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "$@" + else + sed -i "$@" + fi +} diff --git a/test/2-deploy-op-contracts.sh b/test/2-deploy-op-contracts.sh index bfd321b561308..f03bd38fd4f47 100755 --- a/test/2-deploy-op-contracts.sh +++ b/test/2-deploy-op-contracts.sh @@ -10,12 +10,91 @@ sed_inplace() { fi } +# Deploy Safe function +deploy_safe() { + echo "=== Deploying Gnosis Safe ===" + + # Use deployer as single owner with threshold 1 + echo "Using deployer as single owner with threshold 1" + + # Execute Safe deployment + SAFE_DEPLOY_OUTPUT=$(docker run --rm \ + --network "$DOCKER_NETWORK" \ + -v "$(pwd)/$CONFIG_DIR:/deployments" \ + -e DEPLOYER_PRIVATE_KEY="$DEPLOYER_PRIVATE_KEY" \ + -w /app/packages/contracts-bedrock \ + "${OP_CONTRACTS_IMAGE_TAG}" \ + forge script --json --broadcast --legacy \ + --rpc-url $L1_RPC_URL_IN_DOCKER \ + --private-key $DEPLOYER_PRIVATE_KEY \ + scripts/deploy/DeploySimpleSafe.s.sol:DeploySimpleSafe) + + # Extract Safe address + SAFE_ADDRESS=$(echo "$SAFE_DEPLOY_OUTPUT" | jq -r '.logs[] | select(contains("New Safe L1ProxyAdminSafe deployed at:")) | split(": ")[1]' 2>/dev/null | head -1) + + if [ -z "$SAFE_ADDRESS" ] || [ "$SAFE_ADDRESS" = "null" ]; then + echo "โŒ Failed to deploy Safe" + exit 1 + fi + + echo "โœ… Safe deployed at: $SAFE_ADDRESS" + echo " Owner: $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY)" + echo " Threshold: 1" + + # Update .env file + sed_inplace "s/SAFE_ADDRESS=.*/SAFE_ADDRESS=$SAFE_ADDRESS/" .env + source .env + echo " โœ… Updated SAFE_ADDRESS in .env: $SAFE_ADDRESS" +} + +# Deploy Transactor function +deploy_transactor() { + echo "=== Deploying Transactor ===" + + # Execute Transactor deployment using forge create (original method) + TRANSACTOR_DEPLOY_OUTPUT=$(docker run --rm \ + --network "$DOCKER_NETWORK" \ + -v "$(pwd)/$CONFIG_DIR:/deployments" \ + -w /app/packages/contracts-bedrock \ + "${OP_CONTRACTS_IMAGE_TAG}" \ + forge create --json --broadcast --legacy \ + --rpc-url $L1_RPC_URL_IN_DOCKER \ + --private-key $DEPLOYER_PRIVATE_KEY \ + src/periphery/Transactor.sol:Transactor.0.8.30 \ + --constructor-args $ADMIN_OWNER_ADDRESS) + + # Extract Transactor address + TRANSACTOR_ADDRESS=$(echo "$TRANSACTOR_DEPLOY_OUTPUT" | jq -r '.deployedTo // empty') + + if [ -z "$TRANSACTOR_ADDRESS" ] || [ "$TRANSACTOR_ADDRESS" = "null" ]; then + echo "โŒ Failed to deploy Transactor" + echo "Deployment output: $TRANSACTOR_DEPLOY_OUTPUT" + exit 1 + fi + + echo "โœ… Transactor deployed at: $TRANSACTOR_ADDRESS" + + # Update .env file (using original TRANSACTOR variable name) + sed_inplace "s/TRANSACTOR=.*/TRANSACTOR=$TRANSACTOR_ADDRESS/" .env + source .env + echo " โœ… Updated TRANSACTOR address in .env: $TRANSACTOR_ADDRESS" +} + ROOT_DIR=$(git rev-parse --show-toplevel) PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd $PWD_DIR source .env +source ./setup-cgt-function.sh + +# Validate OWNER_TYPE configuration +if [ "$OWNER_TYPE" != "transactor" ] && [ "$OWNER_TYPE" != "safe" ]; then + echo "โŒ Error: Invalid OWNER_TYPE '$OWNER_TYPE'. Must be 'transactor' or 'safe'" + exit 1 +fi + +echo "=== Deploying with OWNER_TYPE: $OWNER_TYPE ===" # Derive CHALLENGER address from OP_CHALLENGER_PRIVATE_KEY if not set if [ -z "$CHALLENGER" ]; then @@ -23,33 +102,20 @@ if [ -z "$CHALLENGER" ]; then echo " โœ… Derived CHALLENGER address from private key: $CHALLENGER" fi -# Deploy Transactor contract first -echo "๐Ÿ”ง Deploying Transactor contract..." -TRANSACTOR_DEPLOY_OUTPUT=$(docker run --rm \ - --network "$DOCKER_NETWORK" \ - -v "$(pwd)/$CONFIG_DIR:/deployments" \ - -w /app/packages/contracts-bedrock \ - "${OP_CONTRACTS_IMAGE_TAG}" \ - forge create --json --broadcast --legacy \ - --rpc-url $L1_RPC_URL_IN_DOCKER \ - --private-key $DEPLOYER_PRIVATE_KEY \ - src/periphery/Transactor.sol:Transactor \ - --constructor-args $ADMIN_OWNER_ADDRESS) - -# Extract contract address from deployment output -TRANSACTOR_ADDRESS=$(echo "$TRANSACTOR_DEPLOY_OUTPUT" | jq -r '.deployedTo // empty') -if [ -z "$TRANSACTOR_ADDRESS" ] || [ "$TRANSACTOR_ADDRESS" = "null" ]; then - echo " โŒ Failed to extract Transactor contract address from deployment output" - echo "Deployment output: $TRANSACTOR_DEPLOY_OUTPUT" - exit 1 +# Deploy owner contract based on OWNER_TYPE +if [ "$OWNER_TYPE" = "safe" ]; then + echo "๐Ÿ”ง Deploying Gnosis Safe for l1ProxyAdminOwner..." + deploy_safe + L1_PROXY_ADMIN_OWNER=$SAFE_ADDRESS +elif [ "$OWNER_TYPE" = "transactor" ]; then + echo "๐Ÿ”ง Deploying Transactor for l1ProxyAdminOwner..." + deploy_transactor + L1_PROXY_ADMIN_OWNER=$TRANSACTOR_ADDRESS fi -echo " โœ… Transactor contract deployed at: $TRANSACTOR_ADDRESS" - -# Update .env file with Transactor address -sed_inplace "s/TRANSACTOR=.*/TRANSACTOR=$TRANSACTOR_ADDRESS/" .env -source .env -echo " โœ… Updated TRANSACTOR address in .env: $TRANSACTOR_ADDRESS" +# Update configuration files +echo "=== Updating configuration files ===" +echo "Using $OWNER_TYPE as l1ProxyAdminOwner: $L1_PROXY_ADMIN_OWNER" echo "๐Ÿ”ง Bootstrapping superchain with op-deployer..." @@ -63,7 +129,7 @@ docker run --rm \ --l1-rpc-url $L1_RPC_URL_IN_DOCKER \ --private-key $DEPLOYER_PRIVATE_KEY \ --artifacts-locator file:///app/packages/contracts-bedrock/forge-artifacts \ - --superchain-proxy-admin-owner $TRANSACTOR_ADDRESS \ + --superchain-proxy-admin-owner $L1_PROXY_ADMIN_OWNER \ --protocol-versions-owner $ADMIN_OWNER_ADDRESS \ --guardian $ADMIN_OWNER_ADDRESS \ --outfile /deployments/superchain.json @@ -96,8 +162,10 @@ docker run --rm \ --challenge-period-seconds $CHALLENGE_PERIOD_SECONDS \ --withdrawal-delay-seconds $WITHDRAWAL_DELAY_SECONDS \ --proof-maturity-delay-seconds $WITHDRAWAL_DELAY_SECONDS \ - --dispute-game-finality-delay-seconds $DISPUTE_GAME_FINALITY_DELAY_SECONDS + --dispute-game-finality-delay-seconds $DISPUTE_GAME_FINALITY_DELAY_SECONDS \ + --dev-feature-bitmap 0x0000000000000000000000000000000000000000000000000000000000001000 " +# Enable custom gas token feature: --dev-feature-bitmap 0x0000000000000000000000000000000000000000000000000000000000001000 cp ./config-op/intent.toml.bak ./config-op/intent.toml cp ./config-op/state.json.bak ./config-op/state.json @@ -105,9 +173,9 @@ CHAIN_ID_UINT256=$(cast to-uint256 $CHAIN_ID) sed_inplace 's/id = .*/id = "'"$CHAIN_ID_UINT256"'"/' ./config-op/intent.toml echo " โœ… Updated chain id in intent.toml: $CHAIN_ID_UINT256" -# Update intent.toml with Transactor address for l1ProxyAdminOwner -sed_inplace "s/l1ProxyAdminOwner = \".*\"/l1ProxyAdminOwner = \"$TRANSACTOR_ADDRESS\"/" ./config-op/intent.toml -echo " โœ… Updated l1ProxyAdminOwner in intent.toml: $TRANSACTOR_ADDRESS" +# Update intent.toml +sed_inplace "s/l1ProxyAdminOwner = .*/l1ProxyAdminOwner = \"$L1_PROXY_ADMIN_OWNER\"/" "$CONFIG_DIR/intent.toml" +echo " โœ… Updated intent.toml with $OWNER_TYPE owner: $L1_PROXY_ADMIN_OWNER" # Read opcmAddress from implementations.json and write it into intent.toml OPCM_ADDRESS=$(jq -r '.opcmAddress' ./config-op/implementations.json) @@ -153,3 +221,10 @@ docker run --rm \ echo "genesis.json and rollup.json are generated in deployments folder" echo "๐ŸŽ‰ OP Stack deployment preparation completed!" + +echo "" +echo "๐Ÿ”ง Setting up Custom Gas Token (CGT)..." +setup_cgt + +echo "" +echo "๐ŸŽ‰ Complete setup with Custom Gas Token finished!" diff --git a/test/3-op-init.sh b/test/3-op-init.sh index 2b3255f05deac..75bef5edcbb77 100755 --- a/test/3-op-init.sh +++ b/test/3-op-init.sh @@ -40,18 +40,21 @@ if [ -f "$STATE_JSON" ]; then L2OO_ADDRESS=$(jq -r '.opChainDeployments.L2OutputOracleProxy // empty' "$STATE_JSON") OPCM_IMPL_ADDRESS=$(jq -r '.appliedIntent.opcmAddress // empty' "$STATE_JSON") SYSTEM_CONFIG_PROXY_ADDRESS=$(jq -r '.opChainDeployments.SystemConfigProxy // empty' "$STATE_JSON") + OPTIMISM_PORTAL_PROXY_ADDRESS=$(jq -r '.opChainDeployments.OptimismPortalProxy // empty' "$STATE_JSON") PROXY_ADMIN=$(jq -r '.superchainContracts.SuperchainProxyAdminImpl // empty' "$STATE_JSON") elif [ "$OPCD_TYPE" = "array" ]; then DISPUTE_GAME_FACTORY_ADDRESS=$(jq -r '.opChainDeployments[0].DisputeGameFactoryProxy // empty' "$STATE_JSON") L2OO_ADDRESS=$(jq -r '.opChainDeployments[0].L2OutputOracleProxy // empty' "$STATE_JSON") OPCM_IMPL_ADDRESS=$(jq -r '.appliedIntent.opcmAddress // empty' "$STATE_JSON") SYSTEM_CONFIG_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].SystemConfigProxy // empty' "$STATE_JSON") + OPTIMISM_PORTAL_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].OptimismPortalProxy // empty' "$STATE_JSON") PROXY_ADMIN=$(jq -r '.superchainContracts.SuperchainProxyAdminImpl // empty' "$STATE_JSON") else DISPUTE_GAME_FACTORY_ADDRESS="" L2OO_ADDRESS="" OPCM_IMPL_ADDRESS="" SYSTEM_CONFIG_PROXY_ADDRESS="" + OPTIMISM_PORTAL_PROXY_ADDRESS="" PROXY_ADMIN="" fi @@ -84,6 +87,13 @@ if [ -f "$STATE_JSON" ]; then echo " โš ๏ธ SystemConfigProxy address not found in opChainDeployments" fi + if [ -n "$OPTIMISM_PORTAL_PROXY_ADDRESS" ]; then + echo " โœ… Found OptimismPortalProxy address: $OPTIMISM_PORTAL_PROXY_ADDRESS" + sed_inplace "s/OPTIMISM_PORTAL_PROXY_ADDRESS=.*/OPTIMISM_PORTAL_PROXY_ADDRESS=$OPTIMISM_PORTAL_PROXY_ADDRESS/" .env + else + echo " โš ๏ธ OptimismPortalProxy address not found in opChainDeployments" + fi + if [ -n "$PROXY_ADMIN" ]; then echo " โœ… Found ProxyAdmin address: $PROXY_ADMIN" sed_inplace "s/PROXY_ADMIN=.*/PROXY_ADMIN=$PROXY_ADMIN/" .env @@ -97,6 +107,7 @@ if [ -f "$STATE_JSON" ]; then echo " L2OO_ADDRESS=$L2OO_ADDRESS" echo " OPCM_IMPL_ADDRESS=$OPCM_IMPL_ADDRESS" echo " SYSTEM_CONFIG_PROXY_ADDRESS=$SYSTEM_CONFIG_PROXY_ADDRESS" + echo " OPTIMISM_PORTAL_PROXY_ADDRESS=$OPTIMISM_PORTAL_PROXY_ADDRESS" echo " PROXY_ADMIN=$PROXY_ADMIN" else echo " โŒ $STATE_JSON is not a valid JSON object" diff --git a/test/4-op-start-service.sh b/test/4-op-start-service.sh index e827fba561114..e174072423426 100755 --- a/test/4-op-start-service.sh +++ b/test/4-op-start-service.sh @@ -16,112 +16,38 @@ PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(dirname "$PWD_DIR")" SCRIPTS_DIR=$ROOT_DIR/test/scripts -docker compose up -d op-batcher - if [ "$CONDUCTOR_ENABLED" = "true" ]; then docker compose up -d op-conductor docker compose up -d op-conductor2 docker compose up -d op-conductor3 sleep 3 $SCRIPTS_DIR/active-sequencer.sh +else + docker compose up -d op-seq fi if [ "$LAUNCH_RPC_NODE" = "true" ]; then docker compose up -d op-rpc fi -sleep 10 - -# Setup P2P static connections between op-geth nodes -echo "๐Ÿ”— Setting up P2P static connections between op-geth nodes..." - -# Function to get enode from a geth container -get_enode() { - local container_name=$1 - local rpc_port=$2 - local enode=$(docker exec $container_name geth attach --exec "admin.nodeInfo.enode" --datadir /datadir 2>/dev/null | tr -d '"') - echo "$enode" -} - -# Function to replace 127.0.0.1 with container name in enode -replace_enode_ip() { - local enode=$1 - local container_name=$2 - echo "$enode" | sed "s/@127.0.0.1:/@$container_name:/" -} - -# Get enodes for all op-geth containers -echo "๐Ÿ“ก Getting enode addresses..." - -# Get enodes -OP_GETH_SEQ_ENODE=$(get_enode "op-geth-seq" "8545") -OP_GETH_RPC_ENODE=$(get_enode "op-geth-rpc" "8545") - -if [ "$CONDUCTOR_ENABLED" = "true" ]; then - OP_GETH_SEQ2_ENODE=$(get_enode "op-geth-seq2" "8545") - OP_GETH_SEQ3_ENODE=$(get_enode "op-geth-seq3" "8545") -fi - -# Replace 127.0.0.1 with container names -OP_GETH_SEQ_ENODE=$(replace_enode_ip "$OP_GETH_SEQ_ENODE" "op-geth-seq") -OP_GETH_RPC_ENODE=$(replace_enode_ip "$OP_GETH_RPC_ENODE" "op-geth-rpc") - -if [ "$CONDUCTOR_ENABLED" = "true" ]; then - OP_GETH_SEQ2_ENODE=$(replace_enode_ip "$OP_GETH_SEQ2_ENODE" "op-geth-seq2") - OP_GETH_SEQ3_ENODE=$(replace_enode_ip "$OP_GETH_SEQ3_ENODE" "op-geth-seq3") -fi +$SCRIPTS_DIR/add-peers.sh -echo "โœ… Enode addresses:" -echo " op-geth-seq: $OP_GETH_SEQ_ENODE" -echo " op-geth-rpc: $OP_GETH_RPC_ENODE" +# Configure op-batcher endpoints based on conductor mode if [ "$CONDUCTOR_ENABLED" = "true" ]; then - echo " op-geth-seq2: $OP_GETH_SEQ2_ENODE" - echo " op-geth-seq3: $OP_GETH_SEQ3_ENODE" -fi - -# Function to add peer to a geth container -add_peer() { - local container_name=$1 - local peer_enode=$2 - echo "๐Ÿ”— Adding peer to $container_name: $peer_enode" - docker exec $container_name geth attach --exec "admin.addPeer('$peer_enode')" --datadir /datadir 2>/dev/null -} - -# Setup static connections between sequencer nodes -echo "๐Ÿ”— Setting up static connections between sequencer nodes..." - -# Add peers to op-geth-seq (connect to other sequencers) -echo "๐Ÿ”— Setting up peers for op-geth-seq..." -if [ "$CONDUCTOR_ENABLED" = "true" ]; then - add_peer "op-geth-seq" "$OP_GETH_SEQ2_ENODE" - add_peer "op-geth-seq" "$OP_GETH_SEQ3_ENODE" -fi - -if [ "$CONDUCTOR_ENABLED" = "true" ]; then - # Add peers to op-geth-seq2 (connect to other sequencers) - echo "๐Ÿ”— Setting up peers for op-geth-seq2..." - add_peer "op-geth-seq2" "$OP_GETH_SEQ_ENODE" - add_peer "op-geth-seq2" "$OP_GETH_SEQ3_ENODE" - - # Add peers to op-geth-seq3 (connect to other sequencers) - echo "๐Ÿ”— Setting up peers for op-geth-seq3..." - add_peer "op-geth-seq3" "$OP_GETH_SEQ_ENODE" - add_peer "op-geth-seq3" "$OP_GETH_SEQ2_ENODE" -fi - -# Setup RPC node to connect to all sequencer nodes -echo "๐Ÿ”— Setting up RPC node to connect to all sequencer nodes..." -add_peer "op-geth-rpc" "$OP_GETH_SEQ_ENODE" -if [ "$CONDUCTOR_ENABLED" = "true" ]; then - add_peer "op-geth-rpc" "$OP_GETH_SEQ2_ENODE" - add_peer "op-geth-rpc" "$OP_GETH_SEQ3_ENODE" + echo "๐Ÿ”ง Configuring op-batcher for conductor mode with conductor RPC endpoints..." + # Set conductor mode endpoints + export OP_BATCHER_L2_ETH_RPC="http://op-conductor:8547,http://op-conductor2:8547,http://op-conductor3:8547" + export OP_BATCHER_ROLLUP_RPC="http://op-conductor:8547,http://op-conductor2:8547,http://op-conductor3:8547" + echo "โœ… op-batcher configured for conductor mode (connecting to conductor RPC endpoints)" +else + echo "๐Ÿ”ง Configuring op-batcher for single sequencer mode..." + # Set single sequencer mode endpoints + export OP_BATCHER_L2_ETH_RPC="http://op-geth-seq:8545" + export OP_BATCHER_ROLLUP_RPC="http://op-seq:9545" + echo "โœ… op-batcher configured for single sequencer mode" fi -echo "โœ… P2P static connections established:" -echo " - Sequencer nodes (op-geth-seq, op-geth-seq2, op-geth-seq3) are connected to each other" -echo " - RPC node (op-geth-rpc) is connected to all sequencer nodes" - - +docker compose up -d op-batcher PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd $PWD_DIR @@ -143,7 +69,7 @@ VM="0x${VM_RAW: -40}" ANCHOR_STATE_REGISTRY=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "anchorStateRegistry()") L2_CHAIN_ID=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "l2ChainId()") -# Call the function to add game type 1 (permissioned) via Transactor +# Call the function to add game type 1 (permissioned) "$SCRIPTS_DIR/add-game-type.sh" 1 true $TEMP_CLOCK_EXTENSION $TEMP_MAX_CLOCK_DURATION $ABSOLUTE_PRESTATE export GAME_TYPE=1 @@ -240,7 +166,7 @@ PERMISSIONED_GAME=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY_ADDRES ABSOLUTE_PRESTATE=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "absolutePrestate()") ANCHOR_STATE_REGISTRY=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME "anchorStateRegistry()") -# Call the function to add game type 0 (permissionless) via Transactor +# Call the function to add game type 0 (permissionless) "$SCRIPTS_DIR/add-game-type.sh" 0 false $CLOCK_EXTENSION $MAX_CLOCK_DURATION $ABSOLUTE_PRESTATE export GAME_TYPE=0 diff --git a/test/config-op/intent.toml.bak b/test/config-op/intent.toml.bak index 2adece7de8edf..cf04ac0b40e8b 100644 --- a/test/config-op/intent.toml.bak +++ b/test/config-op/intent.toml.bak @@ -28,3 +28,8 @@ l2ContractsLocator = "file:///app/packages/contracts-bedrock/forge-artifacts" batcher = "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" proposer = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" challenger = "0x7d18A1B858253b5588f61fb5739d52e4b84e2cdA" + [chains.customGasToken] + enabled = true + name = "OKB" + symbol = "OKB" + InitialLiquidity = "0x0" # 0 OKB, no premint diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 9cc047762a8e5..8b4941b3e357e 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -352,23 +352,29 @@ services: command: - /app/op-batcher/bin/op-batcher - --log.level=debug - - --l2-eth-rpc=http://op-geth-seq:8545 - - --rollup-rpc=http://op-seq:9545 - - --poll-interval=1s + - --l2-eth-rpc=${OP_BATCHER_L2_ETH_RPC:-http://op-geth-seq:8545} + - --rollup-rpc=${OP_BATCHER_ROLLUP_RPC:-http://op-seq:9545} + - --wait-node-sync=true + - --check-recent-txs-depth=5 + - --poll-interval=5s + - --batch-type=1 + - --compression-algo=brotli-11 + - --data-availability-type=auto + - --max-channel-duration=30 + - --target-num-frames=5 - --sub-safety-margin=6 - - --num-confirmations=1 + - --num-confirmations=4 + - --network-timeout=10s - --safe-abort-nonce-too-low-count=3 + - --max-pending-tx=10 - --resubmission-timeout=30s - --rpc.addr=0.0.0.0 - --rpc.port=8548 - --rpc.enable-admin - - --max-channel-duration=25 - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} - --private-key=${OP_BATCHER_PRIVATE_KEY} - --throttle.block-size-upper-limit=1300000 - - -data-availability-type=auto - depends_on: - - op-seq + - --active-sequencer-check-duration=5s op-proposer: image: "${OP_STACK_IMAGE_TAG}" @@ -378,9 +384,14 @@ services: command: - /app/op-proposer/bin/op-proposer - --log.level=debug - - --poll-interval=2s + - --poll-interval=20s + - --wait-node-sync=true + - --allow-non-finalized=false + - --num-confirmations=1 + - --safe-abort-nonce-too-low-count=3 + - --resubmission-timeout=30s - --rpc.port=8560 - - --rollup-rpc=http://op-seq:9545 + - --rollup-rpc=http://op-rpc:9545 - --game-factory-address=${DISPUTE_GAME_FACTORY_ADDRESS} - --proposal-interval=1m - --private-key=${OP_PROPOSER_PRIVATE_KEY} @@ -409,8 +420,8 @@ services: - --log.level=debug - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} - --l1-beacon=${L1_BEACON_URL_IN_DOCKER} - - --l2-eth-rpc=http://op-geth-seq:8545 - - --rollup-rpc=http://op-seq:9545 + - --l2-eth-rpc=http://op-geth-rpc:8545 + - --rollup-rpc=http://op-rpc:9545 - --game-factory-address=${DISPUTE_GAME_FACTORY_ADDRESS} - --cannon-bin=/app/cannon/bin/cannon - --cannon-server=/data/op-program @@ -431,7 +442,7 @@ services: command: - /app/op-dispute-mon/bin/op-dispute-mon - --l1-eth-rpc=${L1_RPC_URL_IN_DOCKER} - - --rollup-rpc=http://op-seq:9545 + - --rollup-rpc=http://op-rpc:9545 - --game-factory-address=${DISPUTE_GAME_FACTORY_ADDRESS} - --game-window=${GAME_WINDOW}s - --honest-actors=${PROPOSER_ADDRESS} diff --git a/test/example.env b/test/example.env index a314024a5c993..e4a37dadf7cc0 100644 --- a/test/example.env +++ b/test/example.env @@ -1,12 +1,12 @@ OP_GETH_LOCAL_DIRECTORY= -OP_GETH_BRANCH= +OP_GETH_BRANCH=dev SKIP_OP_STACK_BUILD=false SKIP_OP_CONTRACTS_BUILD=false SKIP_OP_GETH_BUILD=false -OP_GETH_IMAGE_TAG=op-geth:v1.101511.0-patch -OP_STACK_IMAGE_TAG=op-stack:v1.13.4 -OP_CONTRACTS_IMAGE_TAG=op-contracts:v1.13.4 +OP_GETH_IMAGE_TAG=op-geth:latest +OP_STACK_IMAGE_TAG=op-stack:latest +OP_CONTRACTS_IMAGE_TAG=op-contracts:latest DOCKER_NETWORK=dev-op CONFIG_DIR=config-op @@ -18,10 +18,12 @@ RICH_L1_PRIVATE_KEY=0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7c L1_RPC_URL=http://localhost:8545 L2_RPC_URL=http://localhost:8124 L1_RPC_URL_IN_DOCKER=http://l1-geth:8545 +L2_RPC_URL=http://localhost:8123 L2_RPC_URL_IN_DOCKER=http://op-geth-seq:8545 L1_BEACON_URL_IN_DOCKER=http://l1-beacon-chain:3500 -TRANSACTOR=0x162a433068f51e18b7d13932f27e66a3f99e6890 +SAFE_ADDRESS=0x0000000000000000000000000000000000000000 +TRANSACTOR=0x0000000000000000000000000000000000000000 DEPLOYER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 SEQUENCER_P2P_KEY=0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba @@ -36,6 +38,10 @@ OPCM_IMPL_ADDRESS=0xd5ea6d3f520eac42f989019a8d3c51a123e73113 SYSTEM_CONFIG_PROXY_ADDRESS=0x330cff9f99a75bc9c71750b5c60fdc0eff1789e1 PROXY_ADMIN=0x922d6956c99e12dfeb3224dea977d0939758a1fe PROPOSER_ADDRESS=0x70997970C51812dc3A010C7d01b50e0d17dc79C8 +OPTIMISM_PORTAL_PROXY_ADDRESS=0xc8e8b7b181db301f27aef90ed285787a3ce179e9 + +# OKB Token Address on L1. If not set, a new MockOKB will be deployed. +OKB_TOKEN_ADDRESS=0x75231f58b43240c9718dd58b4967c5114342a86c # First game only for update anchor root TEMP_MAX_CLOCK_DURATION=40 @@ -64,3 +70,5 @@ DB_ENGINE="pebble" CONDUCTOR_ENABLED=true LAUNCH_RPC_NODE=true + +OWNER_TYPE=safe # transactor diff --git a/test/scripts/add-game-type.sh b/test/scripts/add-game-type.sh index 4ae3e209b6c6b..17f141cac7ed4 100755 --- a/test/scripts/add-game-type.sh +++ b/test/scripts/add-game-type.sh @@ -7,6 +7,14 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ENV_FILE="$(dirname "$SCRIPT_DIR")/.env" source "$ENV_FILE" +# Validate OWNER_TYPE configuration +if [ "$OWNER_TYPE" != "transactor" ] && [ "$OWNER_TYPE" != "safe" ]; then + echo "โŒ Error: Invalid OWNER_TYPE '$OWNER_TYPE'. Must be 'transactor' or 'safe'" + exit 1 +fi + +echo "=== Using OWNER_TYPE: $OWNER_TYPE ===" + # Function to set respected game type set_respected_game_type() { local GAME_TYPE=${1:-0} # Default to game type 0 @@ -56,6 +64,172 @@ set_respected_game_type() { fi } +# Function to add game type via Safe +add_game_type_via_safe() { + # Check parameter count + if [ $# -ne 5 ]; then + echo "Error: add_game_type_via_safe requires exactly 5 parameters" + echo "Usage: add_game_type_via_safe " + echo "Example: add_game_type_via_safe 2 true 600 1800 0x..." + return 1 + fi + + local GAME_TYPE=$1 + local IS_PERMISSIONED=$2 + local CLOCK_EXTENSION_VAL=$3 + local MAX_CLOCK_DURATION_VAL=$4 + local ABSOLUTE_PRESTATE_VAL=$5 + + echo "=== Adding Game Type $GAME_TYPE via Safe ===" + echo " Game Type: $GAME_TYPE" + echo " Is Permissioned: $IS_PERMISSIONED" + echo " Clock Extension: $CLOCK_EXTENSION_VAL" + echo " Max Clock Duration: $MAX_CLOCK_DURATION_VAL" + echo "" + + # Get dispute game factory address + DISPUTE_GAME_FACTORY=$(cast call --rpc-url $L1_RPC_URL $SYSTEM_CONFIG_PROXY_ADDRESS 'disputeGameFactory()(address)') + + echo "Debug Info:" + echo " State JSON: $STATE_JSON_PATH" + echo " Dispute Game Factory: $DISPUTE_GAME_FACTORY" + echo " System Config: $SYSTEM_CONFIG_PROXY_ADDRESS" + echo " Proxy Admin: $PROXY_ADMIN" + echo " OPCM: $OPCM_IMPL_ADDRESS" + echo " Safe: $SAFE_ADDRESS" + echo " RPC URL: $L1_RPC_URL" + echo " Sender: $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY)" + echo "" + + # Retrieve existing permissioned game implementation for parameters + echo "Retrieving permissioned game parameters..." + PERMISSIONED_GAME=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY 'gameImpls(uint32)(address)' 1) + echo "Permissioned Game Implementation: $PERMISSIONED_GAME" + + if [ "$PERMISSIONED_GAME" == "0x0000000000000000000000000000000000000000" ]; then + echo "Error: No permissioned game found. Cannot retrieve parameters." + exit 1 + fi + + # Retrieve parameters from existing permissioned game + ABSOLUTE_PRESTATE="$ABSOLUTE_PRESTATE_VAL" + MAX_GAME_DEPTH=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME 'maxGameDepth()') + SPLIT_DEPTH=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME 'splitDepth()') + VM=$(cast call --rpc-url $L1_RPC_URL $PERMISSIONED_GAME 'vm()(address)') + + echo "Retrieved parameters:" + echo " Absolute Prestate: $ABSOLUTE_PRESTATE" + echo " Max Game Depth: $MAX_GAME_DEPTH" + echo " Split Depth: $SPLIT_DEPTH" + echo " Clock Extension: $CLOCK_EXTENSION_VAL" + echo " Max Clock Duration: $MAX_CLOCK_DURATION_VAL" + echo " VM: $VM" + echo "" + + # Set constants + INITIAL_BOND='80000000000000000' # 0.08 ETH in wei + SALT_MIXER='123' # Unique salt for game type + + echo "Creating addGameType calldata..." + + # Build game type parameters array (simplified) + GAME_PARAMS="[(\"$SALT_MIXER\",$SYSTEM_CONFIG_PROXY_ADDRESS,$PROXY_ADMIN,0x0000000000000000000000000000000000000000,$GAME_TYPE,$ABSOLUTE_PRESTATE,$MAX_GAME_DEPTH,$SPLIT_DEPTH,$CLOCK_EXTENSION_VAL,$MAX_CLOCK_DURATION_VAL,$INITIAL_BOND,$VM,$IS_PERMISSIONED)]" + + echo "Parameters prepared for addGameType" + + # Execute the transaction through Safe + echo "Executing transaction via Safe..." + echo "Target: $SAFE_ADDRESS" + echo "From: $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY)" + + # Simplified DELEGATECALL - build calldata first, then call + ADDGAMETYPE_CALLDATA=$(cast calldata 'addGameType((string,address,address,address,uint32,bytes32,uint256,uint256,uint64,uint64,uint256,address,bool)[])' "$GAME_PARAMS") + + + # Execute transaction via Safe's execTransaction with proper signature + echo "Executing transaction via Safe with signature..." + DEPLOYER_ADDRESS=$(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY) + + # Use the calldata we built earlier + echo "Using calldata: $ADDGAMETYPE_CALLDATA" + + # Get Safe nonce + SAFE_NONCE=$(cast call --rpc-url $L1_RPC_URL $SAFE_ADDRESS 'nonce()(uint256)') + echo "Safe nonce: $SAFE_NONCE" + + # Build signature exactly like DeployOwnership.s.sol _callViaSafe method + # abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1)) + echo "Building signature like DeployOwnership.s.sol _callViaSafe..." + + # Convert deployer address to uint256(uint160(address)) format + # This is equivalent to: uint256(uint160(msg.sender)) + DEPLOYER_ADDRESS_NO_PREFIX=${DEPLOYER_ADDRESS#0x} + DEPLOYER_ADDRESS_PADDED=$(printf "%064s" $DEPLOYER_ADDRESS_NO_PREFIX) + + # Build signature: uint256(uint160(msg.sender)) + bytes32(0) + uint8(1) + # This is exactly what abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1)) produces + PACKED_SIGNATURE="0x${DEPLOYER_ADDRESS_PADDED}000000000000000000000000000000000000000000000000000000000000000001" + + echo "Deployer address: $DEPLOYER_ADDRESS" + echo "Signature (abi.encodePacked format): $PACKED_SIGNATURE" + echo "Signature length: $((${#PACKED_SIGNATURE} - 2)) hex chars = $(((${#PACKED_SIGNATURE} - 2) / 2)) bytes" + + # Execute transaction via Safe's execTransaction + echo "Executing execTransaction on Safe..." + TX_OUTPUT=$(cast send \ + --json \ + --legacy \ + --rpc-url $L1_RPC_URL \ + --private-key $DEPLOYER_PRIVATE_KEY \ + --from $DEPLOYER_ADDRESS \ + $SAFE_ADDRESS \ + 'execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)' \ + $OPCM_IMPL_ADDRESS \ + 0 \ + $ADDGAMETYPE_CALLDATA \ + 1 \ + 0 \ + 0 \ + 0 \ + 0x0000000000000000000000000000000000000000 \ + 0x0000000000000000000000000000000000000000 \ + $PACKED_SIGNATURE) + + # Extract transaction hash and status + TX_HASH=$(echo "$TX_OUTPUT" | jq -r '.transactionHash // empty') + TX_STATUS=$(echo "$TX_OUTPUT" | jq -r '.status // empty') + + echo "" + echo "Transaction sent, TX_HASH: $TX_HASH" + + # Check if transaction was successful + if [ "$TX_STATUS" = "0x1" ] || [ "$TX_STATUS" = "1" ]; then + echo " โœ… Transaction successful!" + else + echo " โŒ Transaction failed with status: $TX_STATUS" + echo "Full output: $TX_OUTPUT" + exit 1 + fi + echo "" + + # Verify the new game type was added + echo "Verifying new game type was added..." + NEW_GAME_IMPL=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY 'gameImpls(uint32)(address)' $GAME_TYPE) + + if [ "$NEW_GAME_IMPL" != "0x0000000000000000000000000000000000000000" ] && [ "$NEW_GAME_IMPL" != "$PERMISSIONED_GAME" ]; then + echo " โœ… Success! New game type $GAME_TYPE added." + echo "Game Type $GAME_TYPE Implementation: $NEW_GAME_IMPL" + else + echo " โŒ Warning: Could not verify game type was added. Check transaction status." + fi + + echo " โœ… AddGameType operations completed successfully" + + # Set the newly added game type as respected + echo "" + set_respected_game_type "$GAME_TYPE" +} + # Function to add game type via Transactor add_game_type_via_transactor() { # Check parameter count @@ -83,7 +257,6 @@ add_game_type_via_transactor() { DISPUTE_GAME_FACTORY=$(cast call --rpc-url $L1_RPC_URL $SYSTEM_CONFIG_PROXY_ADDRESS 'disputeGameFactory()(address)') echo "Debug Info:" - echo " State JSON: $STATE_JSON_PATH" echo " Dispute Game Factory: $DISPUTE_GAME_FACTORY" echo " System Config: $SYSTEM_CONFIG_PROXY_ADDRESS" echo " Proxy Admin: $PROXY_ADMIN" @@ -119,26 +292,24 @@ add_game_type_via_transactor() { echo "" # Set constants - INITIAL_BOND='1000000000000000000' # 1 ETH in wei + INITIAL_BOND='80000000000000000' # 0.08 ETH in wei SALT_MIXER='123' # Unique salt for game type echo "Creating addGameType calldata..." - # Build game type parameters array (simplified) + # Build game type parameters array GAME_PARAMS="[(\"$SALT_MIXER\",$SYSTEM_CONFIG_PROXY_ADDRESS,$PROXY_ADMIN,0x0000000000000000000000000000000000000000,$GAME_TYPE,$ABSOLUTE_PRESTATE,$MAX_GAME_DEPTH,$SPLIT_DEPTH,$CLOCK_EXTENSION_VAL,$MAX_CLOCK_DURATION_VAL,$INITIAL_BOND,$VM,$IS_PERMISSIONED)]" echo "Parameters prepared for addGameType" - # Execute the transaction through Transactor - echo "Executing transaction via Transactor..." - echo "Target: $TRANSACTOR" - echo "From: $(cast wallet address --private-key $DEPLOYER_PRIVATE_KEY)" - - # Simplified DELEGATECALL - build calldata first, then call + # Build calldata for addGameType ADDGAMETYPE_CALLDATA=$(cast calldata 'addGameType((string,address,address,address,uint32,bytes32,uint256,uint256,uint64,uint64,uint256,address,bool)[])' "$GAME_PARAMS") - # Execute transaction and capture output - # Use --legacy to force Type 0 transactions, avoiding EIP-1559 gas estimation issues on local testnet + echo "Executing DELEGATECALL via Transactor..." + echo "TRANSACTOR address: $TRANSACTOR" + echo "TRANSACTOR address length: ${#TRANSACTOR}" + + # Execute through Transactor's DELEGATECALL method TX_OUTPUT=$(cast send \ --json \ --legacy \ @@ -171,7 +342,7 @@ add_game_type_via_transactor() { echo "Verifying new game type was added..." NEW_GAME_IMPL=$(cast call --rpc-url $L1_RPC_URL $DISPUTE_GAME_FACTORY 'gameImpls(uint32)(address)' $GAME_TYPE) - if [ "$NEW_GAME_IMPL" != "0x0000000000000000000000000000000000000000" ]; then + if [ "$NEW_GAME_IMPL" != "0x0000000000000000000000000000000000000000" ] && [ "$NEW_GAME_IMPL" != "$PERMISSIONED_GAME" ]; then echo " โœ… Success! New game type $GAME_TYPE added." echo "Game Type $GAME_TYPE Implementation: $NEW_GAME_IMPL" else @@ -187,6 +358,13 @@ add_game_type_via_transactor() { # Main execution if [ "${BASH_SOURCE[0]}" == "${0}" ]; then - # Script is being executed directly - call the function - add_game_type_via_transactor "$@" + # Script is being executed directly - choose function based on OWNER_TYPE + if [ "$OWNER_TYPE" = "safe" ]; then + add_game_type_via_safe "$@" + elif [ "$OWNER_TYPE" = "transactor" ]; then + add_game_type_via_transactor "$@" + else + echo "Error: Invalid OWNER_TYPE '$OWNER_TYPE'" + exit 1 + fi fi diff --git a/test/scripts/add-peers.sh b/test/scripts/add-peers.sh new file mode 100755 index 0000000000000..f6a64fa1e8581 --- /dev/null +++ b/test/scripts/add-peers.sh @@ -0,0 +1,127 @@ +#!/bin/bash + +set -e + +# Source environment variables +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ENV_FILE="$(dirname "$SCRIPT_DIR")/.env" +source "$ENV_FILE" + +# Setup P2P static connections between op-geth nodes +echo "๐Ÿ”— Setting up P2P static connections between op-geth nodes..." + +# Function to get enode from a geth container +get_enode() { + local container_name=$1 + local rpc_port=$2 + local enode=$(docker exec $container_name geth attach --exec "admin.nodeInfo.enode" --datadir /datadir 2>/dev/null | tr -d '"') + echo "$enode" +} + +# Function to replace 127.0.0.1 with container name in enode +replace_enode_ip() { + local enode=$1 + local container_name=$2 + echo "$enode" | sed "s/@127.0.0.1:/@$container_name:/" +} + +# Get enodes for all op-geth containers +echo "๐Ÿ“ก Getting enode addresses..." + +# Get enodes +OP_GETH_SEQ_ENODE=$(get_enode "op-geth-seq" "8545") +if [ -z "$OP_GETH_SEQ_ENODE" ]; then + echo "โŒ Failed to get enode for op-geth-seq" + exit 1 +fi + +if [ "$LAUNCH_RPC_NODE" = "true" ]; then + OP_GETH_RPC_ENODE=$(get_enode "op-geth-rpc" "8545") + if [ -z "$OP_GETH_RPC_ENODE" ]; then + echo "โŒ Failed to get enode for op-geth-rpc" + exit 1 + fi +fi + +if [ "$CONDUCTOR_ENABLED" = "true" ]; then + OP_GETH_SEQ2_ENODE=$(get_enode "op-geth-seq2" "8545") + if [ -z "$OP_GETH_SEQ2_ENODE" ]; then + echo "โŒ Failed to get enode for op-geth-seq2" + exit 1 + fi + OP_GETH_SEQ3_ENODE=$(get_enode "op-geth-seq3" "8545") + if [ -z "$OP_GETH_SEQ3_ENODE" ]; then + echo "โŒ Failed to get enode for op-geth-seq3" + exit 1 + fi +fi + +# Replace 127.0.0.1 with container names +OP_GETH_SEQ_ENODE=$(replace_enode_ip "$OP_GETH_SEQ_ENODE" "op-geth-seq") + +if [ "$LAUNCH_RPC_NODE" = "true" ]; then + OP_GETH_RPC_ENODE=$(replace_enode_ip "$OP_GETH_RPC_ENODE" "op-geth-rpc") +fi + +if [ "$CONDUCTOR_ENABLED" = "true" ]; then + OP_GETH_SEQ2_ENODE=$(replace_enode_ip "$OP_GETH_SEQ2_ENODE" "op-geth-seq2") + OP_GETH_SEQ3_ENODE=$(replace_enode_ip "$OP_GETH_SEQ3_ENODE" "op-geth-seq3") +fi + +echo "โœ… Enode addresses:" +echo " op-geth-seq: $OP_GETH_SEQ_ENODE" +if [ "$LAUNCH_RPC_NODE" = "true" ]; then + echo " op-geth-rpc: $OP_GETH_RPC_ENODE" +fi +if [ "$CONDUCTOR_ENABLED" = "true" ]; then + echo " op-geth-seq2: $OP_GETH_SEQ2_ENODE" + echo " op-geth-seq3: $OP_GETH_SEQ3_ENODE" +fi + +# Function to add peer to a geth container +add_peer() { + local container_name=$1 + local peer_enode=$2 + echo "๐Ÿ”— Adding peer to $container_name: $peer_enode" + docker exec $container_name geth attach --exec "admin.addPeer('$peer_enode')" --datadir /datadir 2>/dev/null +} + +# Setup static connections between sequencer nodes +echo "๐Ÿ”— Setting up static connections between sequencer nodes..." + +# Add peers to op-geth-seq (connect to other sequencers) +echo "๐Ÿ”— Setting up peers for op-geth-seq..." +if [ "$CONDUCTOR_ENABLED" = "true" ]; then + add_peer "op-geth-seq" "$OP_GETH_SEQ2_ENODE" + add_peer "op-geth-seq" "$OP_GETH_SEQ3_ENODE" +fi + +if [ "$CONDUCTOR_ENABLED" = "true" ]; then + # Add peers to op-geth-seq2 (connect to other sequencers) + echo "๐Ÿ”— Setting up peers for op-geth-seq2..." + add_peer "op-geth-seq2" "$OP_GETH_SEQ_ENODE" + add_peer "op-geth-seq2" "$OP_GETH_SEQ3_ENODE" + + # Add peers to op-geth-seq3 (connect to other sequencers) + echo "๐Ÿ”— Setting up peers for op-geth-seq3..." + add_peer "op-geth-seq3" "$OP_GETH_SEQ_ENODE" + add_peer "op-geth-seq3" "$OP_GETH_SEQ2_ENODE" +fi + +# Setup RPC node to connect to all sequencer nodes +if [ "$LAUNCH_RPC_NODE" = "true" ]; then + echo "๐Ÿ”— Setting up RPC node to connect to all sequencer nodes..." + add_peer "op-geth-rpc" "$OP_GETH_SEQ_ENODE" + if [ "$CONDUCTOR_ENABLED" = "true" ]; then + add_peer "op-geth-rpc" "$OP_GETH_SEQ2_ENODE" + add_peer "op-geth-rpc" "$OP_GETH_SEQ3_ENODE" + fi +fi + +echo "โœ… P2P static connections established:" +if [ "$CONDUCTOR_ENABLED" = "true" ]; then + echo " - Sequencer nodes (op-geth-seq, op-geth-seq2, op-geth-seq3) are connected to each other" +fi +if [ "$LAUNCH_RPC_NODE" = "true" ]; then + echo " - RPC node (op-geth-rpc) is connected to all sequencer nodes" +fi diff --git a/test/setup-cgt-function.sh b/test/setup-cgt-function.sh new file mode 100755 index 0000000000000..2e2217db77942 --- /dev/null +++ b/test/setup-cgt-function.sh @@ -0,0 +1,143 @@ +#!/bin/bash + +sed_inplace() { + if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' "$@" + else + sed -i "$@" + fi +} + +# Setup Custom Gas Token (CGT) function +setup_cgt() { + echo "๐Ÿ”ง Setting up Custom Gas Token (CGT) configuration..." + echo "" + + # Check if OKB_TOKEN_ADDRESS is already set in environment + if [ -n "$OKB_TOKEN_ADDRESS" ]; then + echo "๐Ÿ“ Step 1: Using existing OKB token..." + echo " Found OKB_TOKEN_ADDRESS in environment: $OKB_TOKEN_ADDRESS" + echo "" + + # Verify the token exists at the specified address + cd $ROOT_DIR/packages/contracts-bedrock + echo " Verifying OKB token at address..." + + # Try to call a basic function to verify it's a valid ERC20 + if ! cast call "$OKB_TOKEN_ADDRESS" "name()(string)" --rpc-url "$L1_RPC_URL" >/dev/null 2>&1; then + echo "" + echo "โŒ ERROR: Invalid OKB token address or token not deployed" + echo " Address: $OKB_TOKEN_ADDRESS" + echo " Please check the address or remove OKB_TOKEN_ADDRESS from .env to deploy a new MockOKB" + echo "" + return 1 + fi + + TOKEN_NAME=$(cast call "$OKB_TOKEN_ADDRESS" "name()(string)" --rpc-url "$L1_RPC_URL") + TOKEN_SYMBOL=$(cast call "$OKB_TOKEN_ADDRESS" "symbol()(string)" --rpc-url "$L1_RPC_URL") + echo " โœ… Token verified: $TOKEN_NAME ($TOKEN_SYMBOL)" + echo "" + else + # Deploy MockOKB token if not already set + echo "๐Ÿ“ Step 1: Deploying MockOKB token..." + cd $ROOT_DIR/packages/contracts-bedrock + + # Temporarily disable set -e to capture forge output properly + set +e + MOCK_OKB_OUTPUT=$(forge script scripts/DeployMockOKB.s.sol:DeployMockOKB \ + --rpc-url "$L1_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast 2>&1 | tee /dev/tty) + MOCK_OKB_EXIT_CODE=$? + set -e + + # Check if MockOKB deployment failed + if [ $MOCK_OKB_EXIT_CODE -ne 0 ]; then + echo "" + echo "โŒ ERROR: MockOKB deployment failed with exit code $MOCK_OKB_EXIT_CODE" + echo "Error output shown above โ˜๏ธ" + echo "" + return $MOCK_OKB_EXIT_CODE + fi + + # Extract MockOKB contract address from forge output + OKB_TOKEN_ADDRESS=$(echo "$MOCK_OKB_OUTPUT" | grep "MockOKB deployed at:" | awk '{print $NF}') + + if [ -z "$OKB_TOKEN_ADDRESS" ]; then + echo "" + echo "โŒ ERROR: Could not extract MockOKB address from deployment output" + echo "Please check the deployment logs above" + echo "" + return 1 + fi + + echo "" + echo "โœ… MockOKB deployed successfully!" + echo " Address: $OKB_TOKEN_ADDRESS" + echo "" + echo "๐Ÿ’ก TIP: Add this to your .env file to reuse in future runs:" + echo " export OKB_TOKEN_ADDRESS=$OKB_TOKEN_ADDRESS" + echo "" + fi + + # Export OKB_TOKEN_ADDRESS for the setup script + export OKB_TOKEN_ADDRESS="$OKB_TOKEN_ADDRESS" + + # Get required addresses from state.json + echo "๐Ÿ“ Step 2: Running Custom Gas Token setup script..." + STATE_JSON="$PWD_DIR/config-op/state.json" + SYSTEM_CONFIG_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].SystemConfigProxy' "$STATE_JSON") + OPTIMISM_PORTAL_PROXY_ADDRESS=$(jq -r '.opChainDeployments[0].OptimismPortalProxy' "$STATE_JSON") + + # Export required environment variables for the setup script + export SYSTEM_CONFIG_PROXY_ADDRESS="$SYSTEM_CONFIG_PROXY_ADDRESS" + export OPTIMISM_PORTAL_PROXY_ADDRESS="$OPTIMISM_PORTAL_PROXY_ADDRESS" + + # Temporarily disable set -e to capture forge output properly + set +e + FORGE_OUTPUT=$(forge script scripts/SetupCustomGasToken.s.sol:SetupCustomGasToken \ + --rpc-url "$L1_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" \ + --broadcast 2>&1 | tee /dev/tty) + FORGE_EXIT_CODE=$? + set -e + + # Check if forge script failed + if [ $FORGE_EXIT_CODE -ne 0 ]; then + echo "" + echo "โŒ ERROR: Custom Gas Token setup failed with exit code $FORGE_EXIT_CODE" + echo "Error output shown above โ˜๏ธ" + echo "" + return $FORGE_EXIT_CODE + fi + + # Extract adapter address from setup script output + ADAPTER_ADDRESS=$(echo "$FORGE_OUTPUT" | grep "DepositedOKBAdapter deployed at:" | awk '{print $NF}') + + # Use the already deployed OKB token address + OKB_TOKEN="$OKB_TOKEN_ADDRESS" + + # Query initial OKB total supply + INIT_TOTAL_SUPPLY=$(cast call "$OKB_TOKEN" "totalSupply()(uint256)" --rpc-url "$L1_RPC_URL") + echo "" + echo "๐Ÿ“Š Initial OKB Total Supply: $INIT_TOTAL_SUPPLY" + + echo "" + echo "โœ… L1 Custom Gas Token setup complete!" + echo "" + echo "๐Ÿ“‹ Setup Contract Addresses:" + echo " OKB Token: $OKB_TOKEN" + echo " Adapter: $ADAPTER_ADDRESS" + echo "" + + # Save OKB_TOKEN_ADDRESS to .env file for the test script to use + echo "๐Ÿ’พ Updating .env with OKB token address..." + + # Update OKB_TOKEN_ADDRESS in .env + sed_inplace "s/^OKB_TOKEN_ADDRESS=.*/OKB_TOKEN_ADDRESS=$OKB_TOKEN_ADDRESS/" "$PWD_DIR/.env" + + echo " โœ… OKB token address updated in .env file" + echo " ๐Ÿ’ก ADAPTER_ADDRESS can be queried from SystemConfig.gasPayingToken()" + echo " ๐Ÿ’ก INIT_TOTAL_SUPPLY can be queried from OKB token contract" + echo "" +} diff --git a/test/test-cgt.sh b/test/test-cgt.sh new file mode 100755 index 0000000000000..e0944baa8d7fa --- /dev/null +++ b/test/test-cgt.sh @@ -0,0 +1,189 @@ +#!/bin/bash +set -e + +ROOT_DIR=$(git rev-parse --show-toplevel) +PWD_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +cd $PWD_DIR + +source .env + +# Check if CGT has been set up (OKB_TOKEN_ADDRESS should be in .env) +if [ -z "$OKB_TOKEN_ADDRESS" ]; then + echo "โŒ ERROR: OKB_TOKEN_ADDRESS not found in .env" + echo "" + echo "Please run '2-deploy-op-contracts.sh' first to set up CGT and configure OKB token." + echo "" + exit 1 +fi + +# Query ADAPTER_ADDRESS from SystemConfig.gasPayingToken() +echo "๐Ÿ“ Querying ADAPTER_ADDRESS from SystemConfig..." +ADAPTER_ADDRESS=$(cast call "$SYSTEM_CONFIG_PROXY_ADDRESS" "gasPayingToken()(address,uint8)" --rpc-url "$L1_RPC_URL" | head -n1) +if [ -z "$ADAPTER_ADDRESS" ] || [ "$ADAPTER_ADDRESS" = "0x0000000000000000000000000000000000000000" ]; then + echo "โŒ ERROR: Could not query ADAPTER_ADDRESS from SystemConfig or CGT not configured" + echo " SystemConfig address: $SYSTEM_CONFIG_PROXY_ADDRESS" + exit 1 +fi + +# Query INIT_TOTAL_SUPPLY from OKB token contract +echo "๐Ÿ“ Querying INIT_TOTAL_SUPPLY from OKB token..." +INIT_TOTAL_SUPPLY=$(cast call "$OKB_TOKEN_ADDRESS" "totalSupply()(uint256)" --rpc-url "$L1_RPC_URL") + +echo "" +echo "๐Ÿงช Testing Custom Gas Token (CGT) configuration..." +echo "" +echo "๐Ÿ“‹ Using Contract Addresses:" +echo " OKB Token: $OKB_TOKEN_ADDRESS" +echo " Adapter: $ADAPTER_ADDRESS (queried from SystemConfig)" +echo " Initial Supply: $INIT_TOTAL_SUPPLY (queried from OKB)" +echo "" + +# Check if L2 is running before verifying L2 configuration +if curl -s -X POST "$L2_RPC_URL" \ + -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \ + > /dev/null 2>&1; then + + echo "๐Ÿ“ Step 1: Verifying L2 configuration..." + echo "" + + # Call L1Block predeploy to check configuration + L1_BLOCK_ADDR="0x4200000000000000000000000000000000000015" + + # Check isCustomGasToken + IS_CUSTOM_GAS_TOKEN=$(cast call "$L1_BLOCK_ADDR" \ + "isCustomGasToken()(bool)" \ + --rpc-url "$L2_RPC_URL") + + echo " L1Block.isCustomGasToken(): $IS_CUSTOM_GAS_TOKEN" + + # Check gasPayingTokenName + TOKEN_NAME=$(cast call "$L1_BLOCK_ADDR" \ + "gasPayingTokenName()(string)" \ + --rpc-url "$L2_RPC_URL") + + echo " L1Block.gasPayingTokenName(): $TOKEN_NAME" + + # Check gasPayingTokenSymbol + TOKEN_SYMBOL=$(cast call "$L1_BLOCK_ADDR" \ + "gasPayingTokenSymbol()(string)" \ + --rpc-url "$L2_RPC_URL") + + echo " L1Block.gasPayingTokenSymbol(): $TOKEN_SYMBOL" + + echo "" + if [ "$IS_CUSTOM_GAS_TOKEN" = "true" ]; then + echo "โœ… L2 Custom Gas Token configuration verified!" + else + echo "โš ๏ธ WARNING: L2 custom gas token not yet active" + echo " The L2 chain needs to process the setCustomGasToken transaction" + echo " This will happen automatically when the chain processes L1 data" + fi +else + echo "โš ๏ธ L2 node is not running yet - skipping L2 verification" + echo " Please verify L2 configuration after the L2 node starts" +fi + +echo "" +echo "๐ŸŽ‰ Custom Gas Token verification completed!" +echo "" + +# Perform test deposit +if [ -n "$OKB_TOKEN_ADDRESS" ] && [ -n "$ADAPTER_ADDRESS" ]; then + echo "๐Ÿ“ Step 2: Performing test deposit..." + echo "" + + DEPOSIT_AMOUNT="7999000000000000" + + # L2 recipient address + L2_RECIPIENT=0x70997970C51812dc3A010C7d01b50e0d17dc79C9 + + INIT_BALANCE=$(cast balance $L2_RECIPIENT --rpc-url $L2_RPC_URL) + echo " Deposit Amount: $DEPOSIT_AMOUNT" + echo " L2 Recipient: $L2_RECIPIENT" + echo " Initial Balance: $INIT_BALANCE" + echo "" + + # Check deployer's OKB balance before proceeding + DEPLOYER_ADDRESS=$(cast wallet address --private-key "$DEPLOYER_PRIVATE_KEY") + DEPLOYER_OKB_BALANCE=$(cast call "$OKB_TOKEN_ADDRESS" "balanceOf(address)(uint256)" "$DEPLOYER_ADDRESS" --rpc-url "$L1_RPC_URL") + echo " Deployer ($DEPLOYER_ADDRESS) OKB Balance: $DEPLOYER_OKB_BALANCE" + echo "" + + # Step 2a: Approve the adapter to spend OKB + cast send "$OKB_TOKEN_ADDRESS" \ + "approve(address,uint256)" \ + "$ADAPTER_ADDRESS" \ + "$DEPOSIT_AMOUNT" \ + --rpc-url "$L1_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" + + # Step 2b: Perform the deposit + cast send "$ADAPTER_ADDRESS" \ + "deposit(address,uint256)" \ + "$L2_RECIPIENT" \ + "$DEPOSIT_AMOUNT" \ + --rpc-url "$L1_RPC_URL" \ + --private-key "$DEPLOYER_PRIVATE_KEY" + + echo "" + echo "โœ… Test deposit transaction sent!" + echo "" + echo "โณ Waiting for L2 to process the deposit..." + echo " Checking balance every 5 seconds..." + echo "" + + # Expected final balance + EXPECTED_BALANCE=$((INIT_BALANCE + DEPOSIT_AMOUNT)) + + # Timeout after 5 minutes (60 attempts * 5 seconds) + MAX_ATTEMPTS=60 + ATTEMPT=0 + + while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do + CURRENT_BALANCE=$(cast balance $L2_RECIPIENT --rpc-url $L2_RPC_URL) + + echo " [Attempt $((ATTEMPT + 1))/$MAX_ATTEMPTS] Current Balance: $CURRENT_BALANCE (Expected: $EXPECTED_BALANCE)" + + if [ "$CURRENT_BALANCE" = "$EXPECTED_BALANCE" ]; then + echo "" + echo "๐ŸŽ‰ Deposit processed successfully!" + echo "" + + # Query OKB total supply after successful deposit + DEPOSIT_FINAL_TOTAL_SUPPLY=$(cast call "$OKB_TOKEN_ADDRESS" "totalSupply()(uint256)" --rpc-url "$L1_RPC_URL") + + echo "๐Ÿ“Š Final Status:" + echo " Initial Balance: $INIT_BALANCE" + echo " Deposit Amount: $DEPOSIT_AMOUNT" + echo " Final Balance: $CURRENT_BALANCE" + echo " L2 Recipient: $L2_RECIPIENT" + echo "" + echo "๐Ÿ”ฅ OKB Token Supply Status:" + echo " Initial Total Supply: $INIT_TOTAL_SUPPLY" + echo " Final Total Supply: $DEPOSIT_FINAL_TOTAL_SUPPLY" + echo "" + break + fi + + ATTEMPT=$((ATTEMPT + 1)) + + if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then + sleep 5 + fi + done + + if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then + echo "" + echo "โš ๏ธ WARNING: Deposit not processed within timeout period (5 minutes)" + echo " Current Balance: $CURRENT_BALANCE" + echo " Expected Balance: $EXPECTED_BALANCE" + echo "" + echo "๐Ÿ“š Troubleshooting:" + echo " 1. Check if L2 node is running and syncing" + echo " 2. Check L1 transaction status" + echo " 3. Monitor TransactionDeposited events on OptimismPortal: $OPTIMISM_PORTAL_PROXY_ADDRESS" + echo " 4. Manually check balance: cast balance $L2_RECIPIENT --rpc-url $L2_RPC_URL" + fi +fi