From ae52e6e49a7721979ccbeae8c6c664eba6dde33d Mon Sep 17 00:00:00 2001 From: AnshuJalan Date: Thu, 9 Jan 2025 14:53:44 +0530 Subject: [PATCH] feat: pre testnet release updates --- .../contracts/layer1/based/ITaikoL1.sol | 3 +- .../contracts/layer1/based/TaikoL1.sol | 4 +- .../contracts/layer1/surge/SurgeTaikoL1.sol | 36 ++ .../layer1/surge/SurgeTierProviderBase.sol | 53 +++ .../layer1/surge/SurgeTierRouter.sol | 24 ++ .../layer1/verifiers/SgxVerifier.sol | 6 +- .../verifiers/compose/ComposeVerifier.sol | 1 + .../verifiers/compose/TwoOfThreeVerifier.sol | 2 +- .../shared/common/EssentialContract.sol | 5 +- .../contracts/shared/common/LibNetwork.sol | 3 + .../contracts/shared/common/LibStrings.sol | 1 + .../script/layer1/surge/DeploySurgeOnL1.s.sol | 384 ++++++++++++++++++ .../script/layer1/surge/deploy_surge_on_l1.sh | 23 ++ .../protocol/test/layer1/based/TaikoL1.t.sol | 2 +- .../based/TaikoL1LibProvingWithTiers.t.sol | 2 +- .../layer1/based/TaikoL1TestGroupBase.sol | 2 +- .../layer1/based/TaikoL1testGroupA1.t.sol | 2 +- .../layer1/based/TaikoL1testGroupA2.t.sol | 2 +- 18 files changed, 544 insertions(+), 11 deletions(-) create mode 100644 packages/protocol/contracts/layer1/surge/SurgeTaikoL1.sol create mode 100644 packages/protocol/contracts/layer1/surge/SurgeTierProviderBase.sol create mode 100644 packages/protocol/contracts/layer1/surge/SurgeTierRouter.sol create mode 100644 packages/protocol/script/layer1/surge/DeploySurgeOnL1.s.sol create mode 100644 packages/protocol/script/layer1/surge/deploy_surge_on_l1.sh diff --git a/packages/protocol/contracts/layer1/based/ITaikoL1.sol b/packages/protocol/contracts/layer1/based/ITaikoL1.sol index 306dc6e0447..cbd74e07c67 100644 --- a/packages/protocol/contracts/layer1/based/ITaikoL1.sol +++ b/packages/protocol/contracts/layer1/based/ITaikoL1.sol @@ -100,5 +100,6 @@ interface ITaikoL1 { /// @notice Gets the configuration of the TaikoL1 contract. /// @return Config struct containing configuration parameters. - function getConfig() external pure returns (TaikoData.Config memory); + // Surge: switch to `view` to allow for dynamic chainid + function getConfig() external view returns (TaikoData.Config memory); } diff --git a/packages/protocol/contracts/layer1/based/TaikoL1.sol b/packages/protocol/contracts/layer1/based/TaikoL1.sol index 7b5fc676a9a..abd9c1ca5a7 100644 --- a/packages/protocol/contracts/layer1/based/TaikoL1.sol +++ b/packages/protocol/contracts/layer1/based/TaikoL1.sol @@ -159,6 +159,7 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents { /// @inheritdoc ITaikoL1 function pauseProving(bool _pause) external { + // Surge: disable pausing of proving _disable(); _authorizePause(msg.sender, _pause); LibProving.pauseProving(state, _pause); @@ -289,7 +290,8 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents { } /// @inheritdoc ITaikoL1 - function getConfig() public pure virtual returns (TaikoData.Config memory) { + // Surge: switch to `view` to allow for dynamic chainid + function getConfig() public view virtual returns (TaikoData.Config memory) { return TaikoData.Config({ chainId: LibNetwork.TAIKO_MAINNET, blockMaxProposals: 324_000, // = 7200 * 45 diff --git a/packages/protocol/contracts/layer1/surge/SurgeTaikoL1.sol b/packages/protocol/contracts/layer1/surge/SurgeTaikoL1.sol new file mode 100644 index 00000000000..74a3ddb770c --- /dev/null +++ b/packages/protocol/contracts/layer1/surge/SurgeTaikoL1.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "../based/TaikoL1.sol"; + +/// @title SurgeTaikoL1 +/// @dev Labeled in AddressResolver as "taiko" +contract SurgeTaikoL1 is TaikoL1 { + uint64 private immutable chainId; + + constructor(uint64 _chainId) { + chainId = _chainId; + } + + /// @inheritdoc ITaikoL1 + function getConfig() public view override returns (TaikoData.Config memory) { + return TaikoData.Config({ + chainId: chainId, + blockMaxProposals: 324_000, + blockRingBufferSize: 360_000, + maxBlocksToVerify: 16, + blockMaxGasLimit: 240_000_000, + livenessBond: 0.07 ether, + stateRootSyncInternal: 16, + maxAnchorHeightOffset: 64, + baseFeeConfig: LibSharedData.BaseFeeConfig({ + adjustmentQuotient: 8, + sharingPctg: 75, + gasIssuancePerSecond: 5_000_000, + minGasExcess: 1_340_000_000, + maxGasIssuancePerBlock: 600_000_000 + }), + ontakeForkHeight: 1 + }); + } +} \ No newline at end of file diff --git a/packages/protocol/contracts/layer1/surge/SurgeTierProviderBase.sol b/packages/protocol/contracts/layer1/surge/SurgeTierProviderBase.sol new file mode 100644 index 00000000000..f00c19ce30b --- /dev/null +++ b/packages/protocol/contracts/layer1/surge/SurgeTierProviderBase.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "src/shared/common/LibStrings.sol"; +import "../tiers/ITierProvider.sol"; +import "../tiers/LibTiers.sol"; + +/// @title SurgeTierProviderBase +/// @notice This contract is a version of Taiko's TierProviderBase modified for Nethermind's Surge +/// @dev Modification include: +/// - Removed guardian tiers +/// - Only one proving tier i.e TWO_OF_THREE +/// - No contestation for the proof +abstract contract SurgeTierProviderBase is ITierProvider { + uint96 public constant BOND_UNIT = 0.04 ether; + + /// @inheritdoc ITierProvider + function getTier(uint16 _tierId) public pure virtual returns (ITierProvider.Tier memory) { + if (_tierId == LibTiers.TIER_TWO_OF_THREE) { + // No validity or contestation period + return _buildTier(LibStrings.B_TIER_TWO_OF_THREE, 0, 0, 180); + } + + revert TIER_NOT_FOUND(); + } + + /// @dev Builds a generic tier with specified parameters. + /// @param _verifierName The name of the verifier. + /// @param _validityBondUnits The units of validity bonds. + /// @param _cooldownWindow The cooldown window duration in minutes. + /// @param _provingWindow The proving window duration in minutes. + /// @return A Tier struct with the provided parameters. + function _buildTier( + bytes32 _verifierName, + uint8 _validityBondUnits, + uint16 _cooldownWindow, + uint16 _provingWindow + ) + private + pure + returns (ITierProvider.Tier memory) + { + uint96 validityBond = BOND_UNIT * _validityBondUnits; + return ITierProvider.Tier({ + verifierName: _verifierName, + validityBond: validityBond, + contestBond: validityBond / 10_000 * 65_625, + cooldownWindow: _cooldownWindow, + provingWindow: _provingWindow, + maxBlocksToVerifyPerProof: 0 + }); + } +} \ No newline at end of file diff --git a/packages/protocol/contracts/layer1/surge/SurgeTierRouter.sol b/packages/protocol/contracts/layer1/surge/SurgeTierRouter.sol new file mode 100644 index 00000000000..14ff23fa6a1 --- /dev/null +++ b/packages/protocol/contracts/layer1/surge/SurgeTierRouter.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "./SurgeTierProviderBase.sol"; +import "../tiers/ITierRouter.sol"; + +/// @title SurgeTierRouter +contract SurgeTierRouter is SurgeTierProviderBase, ITierRouter { + /// @inheritdoc ITierRouter + function getProvider(uint256) external view returns (address) { + return address(this); + } + + /// @inheritdoc ITierProvider + function getTierIds() external pure returns (uint16[] memory tiers_) { + tiers_ = new uint16[](1); + tiers_[0] = LibTiers.TIER_TWO_OF_THREE; + } + + /// @inheritdoc ITierProvider + function getMinTier(address, uint256) public pure override returns (uint16) { + return LibTiers.TIER_TWO_OF_THREE; + } +} \ No newline at end of file diff --git a/packages/protocol/contracts/layer1/verifiers/SgxVerifier.sol b/packages/protocol/contracts/layer1/verifiers/SgxVerifier.sol index f5bf83f024e..c016888d606 100644 --- a/packages/protocol/contracts/layer1/verifiers/SgxVerifier.sol +++ b/packages/protocol/contracts/layer1/verifiers/SgxVerifier.sol @@ -144,8 +144,9 @@ contract SgxVerifier is EssentialContract, IVerifier { TaikoData.TierProof calldata _proof ) external + // Surge: Allow either TaikoL1 or the composite verifier to call this + onlyFromNamedEither(LibStrings.B_TAIKO, LibStrings.B_TIER_TWO_OF_THREE) { - // ^ Access controls removed for testnet. // Do not run proof verification to contest an existing proof if (_ctx.isContesting) return; @@ -177,7 +178,8 @@ contract SgxVerifier is EssentialContract, IVerifier { TaikoData.TierProof calldata _proof ) external - onlyFromNamedEither(LibStrings.B_TAIKO, LibStrings.B_TIER_TEE_ANY) + // Surge: Allow either TaikoL1 or the composite verifier to call this + onlyFromNamedEither(LibStrings.B_TAIKO, LibStrings.B_TIER_TWO_OF_THREE) { // Size is: 109 bytes // 4 bytes + 20 bytes + 20 bytes + 65 bytes (signature) = 109 diff --git a/packages/protocol/contracts/layer1/verifiers/compose/ComposeVerifier.sol b/packages/protocol/contracts/layer1/verifiers/compose/ComposeVerifier.sol index 550842af007..71fe03d6acc 100644 --- a/packages/protocol/contracts/layer1/verifiers/compose/ComposeVerifier.sol +++ b/packages/protocol/contracts/layer1/verifiers/compose/ComposeVerifier.sol @@ -44,6 +44,7 @@ abstract contract ComposeVerifier is EssentialContract, IVerifier { TaikoData.TierProof calldata _proof ) external + onlyAuthorizedCaller nonReentrant { (address[] memory verifiers, uint256 numSubProofs_) = getSubVerifiersAndThreshold(); diff --git a/packages/protocol/contracts/layer1/verifiers/compose/TwoOfThreeVerifier.sol b/packages/protocol/contracts/layer1/verifiers/compose/TwoOfThreeVerifier.sol index 71f37721e50..696b408c779 100644 --- a/packages/protocol/contracts/layer1/verifiers/compose/TwoOfThreeVerifier.sol +++ b/packages/protocol/contracts/layer1/verifiers/compose/TwoOfThreeVerifier.sol @@ -5,7 +5,7 @@ import "src/shared/common/LibStrings.sol"; import "./ComposeVerifier.sol"; /// @title TwoOfThreeVerifier -/// @custom:security-contact security@taiko.xyz +/// @dev Surge: Allows using any two of the three verifier from SGX / RISC0 / SP1 contract TwoOfThreeVerifier is ComposeVerifier { uint256[50] private __gap; diff --git a/packages/protocol/contracts/shared/common/EssentialContract.sol b/packages/protocol/contracts/shared/common/EssentialContract.sol index 601e6de6292..2d0a01eccee 100644 --- a/packages/protocol/contracts/shared/common/EssentialContract.sol +++ b/packages/protocol/contracts/shared/common/EssentialContract.sol @@ -31,6 +31,8 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable, error REENTRANT_CALL(); error ZERO_ADDRESS(); error ZERO_VALUE(); + + // Surge: revert message for when a function is disable for a surge chain error FUNCTION_DISABLED(); /// @dev Modifier that ensures the caller is the owner or resolved address of a given name. @@ -79,7 +81,7 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable, /// @notice Pauses the contract. function pause() public virtual { - _disable(); + _disable(); // Surge: disable pausing of contracts _pause(); // We call the authorize function here to avoid: // Warning (5740): Unreachable code. @@ -139,6 +141,7 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable, emit Unpaused(msg.sender); } + // Surge: use this to block entry to a function in Taiko stack function _disable() internal pure { revert FUNCTION_DISABLED(); } diff --git a/packages/protocol/contracts/shared/common/LibNetwork.sol b/packages/protocol/contracts/shared/common/LibNetwork.sol index 24573c9c462..6ebf1d9c839 100644 --- a/packages/protocol/contracts/shared/common/LibNetwork.sol +++ b/packages/protocol/contracts/shared/common/LibNetwork.sol @@ -11,9 +11,11 @@ library LibNetwork { uint256 internal constant ETHEREUM_HOLESKY = 17_000; uint256 internal constant ETHEREUM_SEPOLIA = 11_155_111; + // Surge: updated chainid for surge uint64 internal constant TAIKO_MAINNET = 763_374; uint64 internal constant TAIKO_HEKLA = 167_009; + // Surge: required for enabling blob support uint64 internal constant KURTOSIS_DEVNET = 3_151_908; /// @dev Checks if the chain ID represents an Ethereum testnet. @@ -53,6 +55,7 @@ library LibNetwork { /// @param _chainId The chain ID. /// @return true if the chain supports Dencun hardfork, false otherwise. function isDencunSupported(uint256 _chainId) internal pure returns (bool) { + // Surge: Kurtosis based devnet should support Dencun return _chainId == LibNetwork.ETHEREUM_MAINNET || _chainId == LibNetwork.ETHEREUM_HOLESKY || _chainId == LibNetwork.ETHEREUM_SEPOLIA || _chainId == LibNetwork.KURTOSIS_DEVNET || isTaikoDevnet(_chainId); } diff --git a/packages/protocol/contracts/shared/common/LibStrings.sol b/packages/protocol/contracts/shared/common/LibStrings.sol index 7554b06dee7..be5ae6fba3e 100644 --- a/packages/protocol/contracts/shared/common/LibStrings.sol +++ b/packages/protocol/contracts/shared/common/LibStrings.sol @@ -32,6 +32,7 @@ library LibStrings { bytes32 internal constant B_TIER_ZKVM_SP1 = bytes32("tier_zkvm_sp1"); bytes32 internal constant B_TIER_ZKVM_ANY = bytes32("tier_zkvm_any"); bytes32 internal constant B_TIER_ZKVM_AND_TEE = bytes32("tier_zkvm_and_tee"); + // Surge: Tier to choose two of three from SGX / RISC0 / SP1 bytes32 internal constant B_TIER_TWO_OF_THREE = bytes32("tier_two_of_three"); bytes32 internal constant B_RISCZERO_GROTH16_VERIFIER = bytes32("risc0_groth16_verifier"); bytes32 internal constant B_WITHDRAWER = bytes32("withdrawer"); diff --git a/packages/protocol/script/layer1/surge/DeploySurgeOnL1.s.sol b/packages/protocol/script/layer1/surge/DeploySurgeOnL1.s.sol new file mode 100644 index 00000000000..d6af266fd74 --- /dev/null +++ b/packages/protocol/script/layer1/surge/DeploySurgeOnL1.s.sol @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "@openzeppelin/contracts/utils/Strings.sol"; +import "@openzeppelin/contracts/governance/TimelockController.sol"; +import "@risc0/contracts/groth16/RiscZeroGroth16Verifier.sol"; +import { SP1Verifier as SuccinctVerifier } from "@sp1-contracts/src/v3.0.0-rc3/SP1VerifierPlonk.sol"; + +// Actually this one is deployed already on mainnet, but we are now deploying our own (non via-ir) +// version. For mainnet, it is easier to go with one of: +// - https://github.com/daimo-eth/p256-verifier +// - https://github.com/rdubois-crypto/FreshCryptoLib +import "@p256-verifier/contracts/P256Verifier.sol"; + +import "src/shared/common/LibStrings.sol"; +import "src/shared/bridge/Bridge.sol"; +import "src/shared/signal/SignalService.sol"; +import "src/shared/tokenvault/BridgedERC1155.sol"; +import "src/shared/tokenvault/BridgedERC20.sol"; +import "src/shared/tokenvault/BridgedERC721.sol"; +import "src/shared/tokenvault/ERC1155Vault.sol"; +import "src/shared/tokenvault/ERC20Vault.sol"; +import "src/shared/tokenvault/ERC721Vault.sol"; +import "src/layer1/automata-attestation/AutomataDcapV3Attestation.sol"; +import "src/layer1/automata-attestation/lib/PEMCertChainLib.sol"; +import "src/layer1/automata-attestation/utils/SigVerifyLib.sol"; +import "src/layer1/based/TaikoL1.sol"; +import "src/layer1/surge/SurgeTierRouter.sol"; +import "src/layer1/surge/SurgeTaikoL1.sol"; +import "src/layer1/verifiers/SgxVerifier.sol"; +import "src/layer1/verifiers/Risc0Verifier.sol"; +import "src/layer1/verifiers/SP1Verifier.sol"; +import "src/layer1/verifiers/compose/TwoOfThreeVerifier.sol"; +import "src/layer1/verifiers/compose/ComposeVerifier.sol"; +import "test/shared/token/FreeMintERC20.sol"; +import "test/shared/token/MayFailFreeMintERC20.sol"; +import "test/shared/DeployCapability.sol"; + +/// @title DeploySurgeOnL1 +/// @notice This script deploys Taiko protocol modified for Nethermind's Surge. +/// @dev Modification include: +/// - Using Ether as bonds, thus no reference to Taiko token and prover set is removed +/// - Configurable chainId to spin up Surge networks with ease +/// - Automated setup of fields in L1 address manager +/// - Removed guardian prover +contract DeploySurgeOnL1 is DeployCapability { + uint256 internal immutable ADDRESS_LENGTH = 40; + + uint64 internal l2ChainId = uint64(vm.envUint("L2_CHAINID")); + + modifier broadcast() { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + require(privateKey != 0, "invalid priv key"); + vm.startBroadcast(); + _; + vm.stopBroadcast(); + } + + function run() external broadcast { + require(l2ChainId != block.chainid || l2ChainId != 0, "L2_CHAIN_ID"); + require(vm.envBytes32("L2_GENESIS_HASH") != 0, "L2_GENESIS_HASH"); + + //--------------------------------------------------------------- + // Timelocked owner setup + address[] memory executors = vm.envAddress("OWNER_MULTISIG_SIGNERS", ","); + + address ownerMultisig = vm.envAddress("OWNER_MULTISIG"); + addressNotNull(ownerMultisig, "ownerMultisig"); + + address[] memory proposers = new address[](1); + proposers[0] = ownerMultisig; + + uint256 timelockPeriod = uint64(vm.envUint("TIMELOCK_PERIOD")); + address timelockController = address( + new TimelockController(timelockPeriod, proposers, executors, address(0)) + ); + address contractOwner = timelockController; + + console2.log("contractOwner(timelocked): ", contractOwner); + + // --------------------------------------------------------------- + // Deploy shared contracts + (address sharedAddressManager) = deploySharedContracts(contractOwner); + console2.log("sharedAddressManager: ", sharedAddressManager); + + // --------------------------------------------------------------- + // Deploy rollup contracts + address verifierOwner = vm.envAddress("VERIFIER_OWNER"); + addressNotNull(verifierOwner, "verifierOwner"); + + address rollupAddressManager = deployRollupContracts(sharedAddressManager, contractOwner, verifierOwner); + + // --------------------------------------------------------------- + // Signal service need to authorize the new rollup + address signalServiceAddr = AddressManager(sharedAddressManager).getAddress( + uint64(block.chainid), LibStrings.B_SIGNAL_SERVICE + ); + addressNotNull(signalServiceAddr, "signalServiceAddr"); + SignalService signalService = SignalService(signalServiceAddr); + + address taikoL1Addr = AddressManager(rollupAddressManager).getAddress( + uint64(block.chainid), LibStrings.B_TAIKO + ); + addressNotNull(taikoL1Addr, "taikoL1Addr"); + + SignalService(signalServiceAddr).authorize(taikoL1Addr, true); + + console2.log("------------------------------------------"); + console2.log("msg.sender: ", msg.sender); + console2.log("address(this): ", address(this)); + console2.log("signalService.owner(): ", signalService.owner()); + console2.log("------------------------------------------"); + + if (signalService.owner() == msg.sender) { + signalService.transferOwnership(contractOwner); + } else { + console2.log("------------------------------------------"); + console2.log("Warning - you need to transact manually:"); + console2.log("signalService.authorize(taikoL1Addr, bytes32(block.chainid))"); + console2.log("- signalService : ", signalServiceAddr); + console2.log("- taikoL1Addr : ", taikoL1Addr); + console2.log("- chainId : ", block.chainid); + } + + address taikoL2Address = getConstantAddress(vm.toString(l2ChainId), "10001"); + address l2SignalServiceAddress = getConstantAddress(vm.toString(l2ChainId), "5"); + address l2BridgeAddress = getConstantAddress(vm.toString(l2ChainId), "1"); + + // --------------------------------------------------------------- + // Register L2 addresses + register(rollupAddressManager, "taiko", taikoL2Address, l2ChainId); + register( + rollupAddressManager, "signal_service", l2SignalServiceAddress, l2ChainId + ); + register(sharedAddressManager, "signal_service", l2SignalServiceAddress, l2ChainId); + register(sharedAddressManager, "bridge", l2BridgeAddress, l2ChainId); + + + // --------------------------------------------------------------- + // Deploy other contracts + if (block.chainid != 1) { + deployAuxContracts(); + } + + if (AddressManager(sharedAddressManager).owner() == msg.sender) { + AddressManager(sharedAddressManager).transferOwnership(contractOwner); + console2.log("** sharedAddressManager ownership transferred to:", contractOwner); + } + + AddressManager(rollupAddressManager).transferOwnership(contractOwner); + console2.log("** rollupAddressManager ownership transferred to:", contractOwner); + } + + function deploySharedContracts(address owner) internal returns (address sharedAddressManager) { + addressNotNull(owner, "owner"); + + sharedAddressManager = deployProxy({ + name: "shared_address_manager", + impl: address(new AddressManager()), + data: abi.encodeCall(AddressManager.init, (address(0))) + }); + + // Deploy Bridging contracts + deployProxy({ + name: "signal_service", + impl: address(new SignalService()), + data: abi.encodeCall(SignalService.init, (address(0), sharedAddressManager)), + registerTo: sharedAddressManager + }); + + address brdige = deployProxy({ + name: "bridge", + impl: address(new Bridge()), + data: abi.encodeCall(Bridge.init, (address(0), sharedAddressManager)), + registerTo: sharedAddressManager + }); + + Bridge(payable(brdige)).transferOwnership(owner); + + console2.log("------------------------------------------"); + console2.log( + "Warning - you need to register *all* counterparty bridges to enable multi-hop bridging:" + ); + console2.log( + "sharedAddressManager.setAddress(remoteChainId, \"bridge\", address(remoteBridge))" + ); + console2.log("- sharedAddressManager : ", sharedAddressManager); + + // Deploy Vaults + deployProxy({ + name: "erc20_vault", + impl: address(new ERC20Vault()), + data: abi.encodeCall(ERC20Vault.init, (owner, sharedAddressManager)), + registerTo: sharedAddressManager + }); + deployProxy({ + name: "erc721_vault", + impl: address(new ERC721Vault()), + data: abi.encodeCall(ERC721Vault.init, (owner, sharedAddressManager)), + registerTo: sharedAddressManager + }); + deployProxy({ + name: "erc1155_vault", + impl: address(new ERC1155Vault()), + data: abi.encodeCall(ERC1155Vault.init, (owner, sharedAddressManager)), + registerTo: sharedAddressManager + }); + + console2.log("------------------------------------------"); + console2.log( + "Warning - you need to register *all* counterparty vaults to enable multi-hop bridging:" + ); + console2.log( + "sharedAddressManager.setAddress(remoteChainId, \"erc20_vault\", address(remoteERC20Vault))" + ); + console2.log( + "sharedAddressManager.setAddress(remoteChainId, \"erc721_vault\", address(remoteERC721Vault))" + ); + console2.log( + "sharedAddressManager.setAddress(remoteChainId, \"erc1155_vault\", address(remoteERC1155Vault))" + ); + console2.log("- sharedAddressManager : ", sharedAddressManager); + + // Deploy Bridged token implementations + register(sharedAddressManager, "bridged_erc20", address(new BridgedERC20())); + register(sharedAddressManager, "bridged_erc721", address(new BridgedERC721())); + register(sharedAddressManager, "bridged_erc1155", address(new BridgedERC1155())); + } + + function deployRollupContracts( + address _sharedAddressManager, + address owner, + address verifierOwner + ) + internal + returns (address rollupAddressManager) + { + addressNotNull(_sharedAddressManager, "sharedAddressManager"); + addressNotNull(owner, "owner"); + + rollupAddressManager = deployProxy({ + name: "rollup_address_manager", + impl: address(new AddressManager()), + data: abi.encodeCall(AddressManager.init, (address(0))) + }); + + // --------------------------------------------------------------- + // Register shared contracts in the new rollup + copyRegister(rollupAddressManager, _sharedAddressManager, "signal_service"); + copyRegister(rollupAddressManager, _sharedAddressManager, "bridge"); + + TaikoL1 taikoL1 = TaikoL1(address(new SurgeTaikoL1(l2ChainId))); + + deployProxy({ + name: "taiko", + impl: address(taikoL1), + data: abi.encodeCall( + TaikoL1.init, + ( + owner, + rollupAddressManager, + vm.envBytes32("L2_GENESIS_HASH"), + false + ) + ), + registerTo: rollupAddressManager + }); + + deployProxy({ + name: "tier_sgx", + impl: address(new SgxVerifier()), + data: abi.encodeCall(SgxVerifier.init, (verifierOwner, rollupAddressManager)), + registerTo: rollupAddressManager + }); + + register( + rollupAddressManager, + "tier_router", + address(new SurgeTierRouter()) + ); + + // No need to proxy these, because they are 3rd party. If we want to modify, we simply + // change the registerAddress("automata_dcap_attestation", address(attestation)); + P256Verifier p256Verifier = new P256Verifier(); + SigVerifyLib sigVerifyLib = new SigVerifyLib(address(p256Verifier)); + PEMCertChainLib pemCertChainLib = new PEMCertChainLib(); + + addAddress({ + name: "PemCertChainLib", + proxy: address(pemCertChainLib) + }); + + address automateDcapV3AttestationImpl = address(new AutomataDcapV3Attestation()); + + address automataProxy = deployProxy({ + name: "automata_dcap_attestation", + impl: automateDcapV3AttestationImpl, + data: abi.encodeCall( + AutomataDcapV3Attestation.init, (verifierOwner, address(sigVerifyLib), address(pemCertChainLib)) + ), + registerTo: rollupAddressManager + }); + + // Log addresses for the user to register sgx instance + console2.log("SigVerifyLib", address(sigVerifyLib)); + console2.log("PemCertChainLib", address(pemCertChainLib)); + console2.log("AutomataDcapVaAttestation", automataProxy); + + deployZKVerifiers(verifierOwner, rollupAddressManager); + + // Deploy composite verifier + deployProxy({ + name: "tier_two_of_three", + impl: address(new TwoOfThreeVerifier()), + data: abi.encodeCall(ComposeVerifier.init, (verifierOwner, rollupAddressManager)), + registerTo: rollupAddressManager + }); + } + + // deploy both sp1 & risc0 verifiers. + // using function to avoid stack too deep error + function deployZKVerifiers(address verifierOwner, address rollupAddressManager) private { + // Deploy r0 groth16 verifier + RiscZeroGroth16Verifier verifier = + new RiscZeroGroth16Verifier(ControlID.CONTROL_ROOT, ControlID.BN254_CONTROL_ID); + register(rollupAddressManager, "risc0_groth16_verifier", address(verifier)); + + deployProxy({ + name: "tier_zkvm_risc0", + impl: address(new Risc0Verifier()), + data: abi.encodeCall(Risc0Verifier.init, (verifierOwner, rollupAddressManager)), + registerTo: rollupAddressManager + }); + + // Deploy sp1 plonk verifier + SuccinctVerifier succinctVerifier = new SuccinctVerifier(); + register(rollupAddressManager, "sp1_remote_verifier", address(succinctVerifier)); + + deployProxy({ + name: "tier_zkvm_sp1", + impl: address(new SP1Verifier()), + data: abi.encodeCall(SP1Verifier.init, (verifierOwner, rollupAddressManager)), + registerTo: rollupAddressManager + }); + } + + function deployAuxContracts() private { + address horseToken = address(new FreeMintERC20("Horse Token", "HORSE")); + console2.log("HorseToken", horseToken); + + address bullToken = address(new MayFailFreeMintERC20("Bull Token", "BULL")); + console2.log("BullToken", bullToken); + } + + function addressNotNull(address addr, string memory err) private pure { + require(addr != address(0), err); + } + + function getConstantAddress(string memory prefix, string memory suffix) internal pure returns (address) { + bytes memory prefixBytes = bytes(prefix); + bytes memory suffixBytes = bytes(suffix); + + require(prefixBytes.length + suffixBytes.length <= ADDRESS_LENGTH, "Prefix + suffix too long"); + + // Create the middle padding of zeros + uint256 paddingLength = ADDRESS_LENGTH - prefixBytes.length - suffixBytes.length; + bytes memory padding = new bytes(paddingLength); + for(uint i = 0; i < paddingLength; i++) { + padding[i] = "0"; + } + + // Concatenate the parts + string memory hexString = string( + abi.encodePacked( + "0x", + prefix, + string(padding), + suffix + ) + ); + + return vm.parseAddress(hexString); + } +} \ No newline at end of file diff --git a/packages/protocol/script/layer1/surge/deploy_surge_on_l1.sh b/packages/protocol/script/layer1/surge/deploy_surge_on_l1.sh new file mode 100644 index 00000000000..f2e34e2ae97 --- /dev/null +++ b/packages/protocol/script/layer1/surge/deploy_surge_on_l1.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +set -e + +export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +export FORK_URL=http://127.0.0.1:8545 + +L2_CHAINID=167000 \ +L2_GENESIS_HASH=0x00e5e4522f1520280092094a73023c0fc52c2d032d91b3a09c03a375f6afa826 \ +OWNER_MULTISIG=0x1237810000000000000000000000000000000001 \ +OWNER_MULTISIG_SIGNERS="0x1237810000000000000000000000000000000002,0x1237810000000000000000000000000000000003,0x1237810000000000000000000000000000000004" \ +TIMELOCK_PERIOD=3888000 \ +VERIFIER_OWNER=0x1237810000000000000000000000000000000002 \ +FOUNDRY_PROFILE="layer1" \ +forge script ./script/layer1/surge/DeploySurgeOnL1.s.sol:DeploySurgeOnL1 \ + --fork-url $FORK_URL \ + --broadcast \ + --ffi \ + -vv \ + --private-key $PRIVATE_KEY \ + --block-gas-limit 100000000 + +# Timelock period is 45 days. \ No newline at end of file diff --git a/packages/protocol/test/layer1/based/TaikoL1.t.sol b/packages/protocol/test/layer1/based/TaikoL1.t.sol index ea1dd208876..43379f6ea61 100644 --- a/packages/protocol/test/layer1/based/TaikoL1.t.sol +++ b/packages/protocol/test/layer1/based/TaikoL1.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.24; import "./TaikoL1TestBase.sol"; contract TaikoL1_NoCooldown is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() public view override returns (TaikoData.Config memory config) { config = TaikoL1.getConfig(); // over-write the following config.maxBlocksToVerify = 0; diff --git a/packages/protocol/test/layer1/based/TaikoL1LibProvingWithTiers.t.sol b/packages/protocol/test/layer1/based/TaikoL1LibProvingWithTiers.t.sol index a75c11dedef..309566759df 100644 --- a/packages/protocol/test/layer1/based/TaikoL1LibProvingWithTiers.t.sol +++ b/packages/protocol/test/layer1/based/TaikoL1LibProvingWithTiers.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.24; import "./TaikoL1TestBase.sol"; contract TaikoL1Tiers is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() public view override returns (TaikoData.Config memory config) { config = TaikoL1.getConfig(); config.maxBlocksToVerify = 0; diff --git a/packages/protocol/test/layer1/based/TaikoL1TestGroupBase.sol b/packages/protocol/test/layer1/based/TaikoL1TestGroupBase.sol index 1bee2b0b3b1..a4000a59155 100644 --- a/packages/protocol/test/layer1/based/TaikoL1TestGroupBase.sol +++ b/packages/protocol/test/layer1/based/TaikoL1TestGroupBase.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.24; import "./TaikoL1TestBase.sol"; contract TaikoL1New is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() public view override returns (TaikoData.Config memory config) { config = TaikoL1.getConfig(); config.maxBlocksToVerify = 0; config.blockMaxProposals = 20; diff --git a/packages/protocol/test/layer1/based/TaikoL1testGroupA1.t.sol b/packages/protocol/test/layer1/based/TaikoL1testGroupA1.t.sol index d42f91c8332..73984219c92 100644 --- a/packages/protocol/test/layer1/based/TaikoL1testGroupA1.t.sol +++ b/packages/protocol/test/layer1/based/TaikoL1testGroupA1.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.24; import "./TaikoL1TestGroupBase.sol"; contract TaikoL1ForkA1 is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() public view override returns (TaikoData.Config memory config) { config = TaikoL1.getConfig(); config.maxBlocksToVerify = 0; config.blockMaxProposals = 20; diff --git a/packages/protocol/test/layer1/based/TaikoL1testGroupA2.t.sol b/packages/protocol/test/layer1/based/TaikoL1testGroupA2.t.sol index 1479f9d76e8..0932523bcaa 100644 --- a/packages/protocol/test/layer1/based/TaikoL1testGroupA2.t.sol +++ b/packages/protocol/test/layer1/based/TaikoL1testGroupA2.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.24; import "./TaikoL1TestGroupBase.sol"; contract TaikoL1ForkA2 is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() public view override returns (TaikoData.Config memory config) { config = TaikoL1.getConfig(); config.maxBlocksToVerify = 0; config.blockMaxProposals = 10;