diff --git a/packages/protocol/contracts/L2/CrossChainOwned.sol b/packages/protocol/contracts/L2/CrossChainOwned.sol new file mode 100644 index 00000000000..b708b9b4c50 --- /dev/null +++ b/packages/protocol/contracts/L2/CrossChainOwned.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +// _____ _ _ _ _ +// |_ _|_ _(_) |_____ | | __ _| |__ ___ +// | |/ _` | | / / _ \ | |__/ _` | '_ (_-< +// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/ + +pragma solidity 0.8.20; + +import "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; + +import "../common/EssentialContract.sol"; +import "../bridge/IBridge.sol"; + +/// @title CrossChainOwned +/// @notice This contract's owner can be a local address or one that lives on another chain and uses +/// signals for transaction approval. +/// @dev Notice that when send the message on the owner chain, the gas limit of the message must not +/// be zero, so on this chain, some EOA can help execute this transaction. +abstract contract CrossChainOwned is EssentialContract { + uint64 public ownerChainId; // slot 1 + uint64 public nextTxId; + uint256[49] private __gap; + + event TransactionExecuted(uint64 indexed txId, bytes4 indexed selector); + + error XCO_INVALID_TX_ID(); + error XCO_INVALID_OWNER_CHAINID(); + error XCO_PERMISSION_DENIED(); + error XCO_TX_REVERTED(); + + function executeCrossChainTransaction(uint64 txId, bytes calldata txdata) external { + if (txId != nextTxId) revert XCO_INVALID_TX_ID(); + + if (msg.sender != resolve("bridge", false)) revert XCO_PERMISSION_DENIED(); + + IBridge.Context memory ctx = IBridge(msg.sender).context(); + if (ctx.srcChainId != ownerChainId || ctx.from != owner()) { + revert XCO_PERMISSION_DENIED(); + } + + (bool success,) = address(this).call(txdata); + if (!success) revert XCO_TX_REVERTED(); + + emit TransactionExecuted(nextTxId++, bytes4(txdata)); + } + + /// @notice Initializes the contract. + /// @param _addressManager The address of the address manager. + /// @param _ownerChainId The owner's deployment chain ID. + // solhint-disable-next-line func-name-mixedcase + function __CrossChainOwned_init( + address _addressManager, + uint64 _ownerChainId + ) + internal + virtual + { + __Essential_init(_addressManager); + + if (_ownerChainId == 0 || _ownerChainId == block.chainid) { + revert XCO_INVALID_OWNER_CHAINID(); + } + ownerChainId = _ownerChainId; + } + + function _checkOwner() internal view virtual override { + if (msg.sender != owner() && msg.sender != address(this)) { + revert XCO_PERMISSION_DENIED(); + } + } +} diff --git a/packages/protocol/contracts/L2/TaikoL2.sol b/packages/protocol/contracts/L2/TaikoL2.sol index 79eb60de3af..862d6f7a111 100644 --- a/packages/protocol/contracts/L2/TaikoL2.sol +++ b/packages/protocol/contracts/L2/TaikoL2.sol @@ -8,12 +8,12 @@ pragma solidity 0.8.20; import "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -import "../common/EssentialContract.sol"; import "../common/ICrossChainSync.sol"; +import "../signal/ISignalService.sol"; import "../libs/LibAddress.sol"; import "../libs/LibMath.sol"; -import "../signal/ISignalService.sol"; import "./Lib1559Math.sol"; +import "./CrossChainOwned.sol"; import "./TaikoL2Signer.sol"; /// @title TaikoL2 @@ -22,7 +22,7 @@ import "./TaikoL2Signer.sol"; /// It is used to anchor the latest L1 block details to L2 for cross-layer /// communication, manage EIP-1559 parameters for gas pricing, and store /// verified L1 block information. -contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { +contract TaikoL2 is CrossChainOwned, TaikoL2Signer, ICrossChainSync { using LibAddress for address; using LibMath for uint256; @@ -37,13 +37,11 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { mapping(uint256 l1height => ICrossChainSync.Snippet) public snippets; // A hash to check the integrity of public inputs. - address public signalService; // slot 3 - bytes32 public publicInputHash; // slot 4 - - uint64 public gasExcess; // slot 5 + bytes32 public publicInputHash; // slot 3 + uint64 public gasExcess; // slot 4 uint64 public latestSyncedL1Height; - uint256[145] private __gap; + uint256[146] private __gap; event Anchored(bytes32 parentHash, uint64 gasExcess); @@ -55,13 +53,18 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { error L2_TOO_LATE(); /// @notice Initializes the TaikoL2 contract. - /// @param _signalService Address of the {ISignalService} contract. + /// @param _addressManager Address of the AddressManager contract. + /// @param _l1ChainId The ID of the base layer. /// @param _gasExcess The initial gasExcess. - function init(address _signalService, uint64 _gasExcess) external initializer { - __Essential_init(); - - if (_signalService == address(0)) revert L2_INVALID_PARAM(); - signalService = _signalService; + function init( + address _addressManager, + uint64 _l1ChainId, + uint64 _gasExcess + ) + external + initializer + { + __CrossChainOwned_init(_addressManager, _l1ChainId); if (block.chainid <= 1 || block.chainid >= type(uint64).max) { revert L2_INVALID_CHAIN_ID(); @@ -125,7 +128,7 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { // Store the L1's signal root as a signal to the local signal service to // allow for multi-hop bridging. - ISignalService(signalService).sendSignal(l1SignalRoot); + ISignalService(resolve("signal_service", false)).sendSignal(l1SignalRoot); emit CrossChainSynced(uint64(block.number), l1Height, l1BlockHash, l1SignalRoot); // Update state variables diff --git a/packages/protocol/genesis/GenerateGenesis.g.sol b/packages/protocol/genesis/GenerateGenesis.g.sol index da473e4f283..ba0b6b05722 100644 --- a/packages/protocol/genesis/GenerateGenesis.g.sol +++ b/packages/protocol/genesis/GenerateGenesis.g.sol @@ -20,7 +20,9 @@ contract TestGenerateGenesis is Test, AddressResolver { vm.readFile(string.concat(vm.projectRoot(), "/deployments/genesis_config.json")); string private genesisAllocJSON = vm.readFile(string.concat(vm.projectRoot(), "/deployments/genesis_alloc.json")); - address private owner = configJSON.readAddress(".contractOwner"); + address private ownerTimelockController = configJSON.readAddress(".ownerTimelockController"); + address private ownerSecurityCouncil = configJSON.readAddress(".ownerSecurityCouncil"); + uint256 private ownerChainId = configJSON.readUint(".ownerChainId"); function testSharedContractsDeployment() public { assertEq(block.chainid, 167); @@ -59,7 +61,7 @@ contract TestGenerateGenesis is Test, AddressResolver { checkDeployedCode("RollupAddressManager"); // check proxy implementations - checkProxyImplementation("TaikoL2", "TaikoL2Impl"); + checkProxyImplementation("TaikoL2", "TaikoL2Impl", ownerTimelockController); checkProxyImplementation("RollupAddressManager", "RollupAddressManagerImpl"); // check proxies @@ -71,7 +73,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManagerProxy = AddressManager(getPredeployedContractAddress("SharedAddressManager")); - assertEq(owner, addressManagerProxy.owner()); + assertEq(ownerSecurityCouncil, addressManagerProxy.owner()); checkSavedAddress(addressManagerProxy, "Bridge", "bridge"); checkSavedAddress(addressManagerProxy, "ERC20Vault", "erc20_vault"); @@ -95,7 +97,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManagerProxy = AddressManager(getPredeployedContractAddress("RollupAddressManager")); - assertEq(owner, addressManagerProxy.owner()); + assertEq(ownerSecurityCouncil, addressManagerProxy.owner()); checkSavedAddress(addressManagerProxy, "TaikoL2", "taiko"); checkSavedAddress(addressManagerProxy, "SignalService", "signal_service"); @@ -115,6 +117,9 @@ contract TestGenerateGenesis is Test, AddressResolver { function testTaikoL2() public { TaikoL2 taikoL2Proxy = TaikoL2(getPredeployedContractAddress("TaikoL2")); + assertEq(ownerTimelockController, taikoL2Proxy.owner()); + assertEq(ownerChainId, taikoL2Proxy.ownerChainId()); + vm.startPrank(taikoL2Proxy.GOLDEN_TOUCH_ADDRESS()); for (uint32 i = 0; i < 300; ++i) { vm.roll(block.number + 1); @@ -152,7 +157,7 @@ contract TestGenerateGenesis is Test, AddressResolver { function testSingletonBridge() public { Bridge bridgeProxy = Bridge(payable(getPredeployedContractAddress("Bridge"))); - assertEq(owner, bridgeProxy.owner()); + assertEq(ownerSecurityCouncil, bridgeProxy.owner()); vm.expectRevert(Bridge.B_PERMISSION_DENIED.selector); bridgeProxy.processMessage( @@ -175,7 +180,7 @@ contract TestGenerateGenesis is Test, AddressResolver { assertEq(bridgeProxy.paused(), false); - vm.startPrank(owner); + vm.startPrank(ownerSecurityCouncil); bridgeProxy.pause(); assertEq(bridgeProxy.paused(), true); @@ -218,7 +223,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManager = AddressManager(getPredeployedContractAddress("SharedAddressManager")); - assertEq(owner, erc20VaultProxy.owner()); + assertEq(ownerSecurityCouncil, erc20VaultProxy.owner()); vm.startPrank(addressManager.owner()); addressManager.setAddress(1, "bridge", bridgeAddress); @@ -244,7 +249,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManager = AddressManager(getPredeployedContractAddress("SharedAddressManager")); - assertEq(owner, erc721VaultProxy.owner()); + assertEq(ownerSecurityCouncil, erc721VaultProxy.owner()); vm.startPrank(addressManager.owner()); addressManager.setAddress(1, "bridge", bridgeAddress); @@ -269,7 +274,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManager = AddressManager(getPredeployedContractAddress("SharedAddressManager")); - assertEq(owner, erc1155VaultProxy.owner()); + assertEq(ownerSecurityCouncil, erc1155VaultProxy.owner()); vm.startPrank(addressManager.owner()); addressManager.setAddress(1, "bridge", bridgeProxyAddress); @@ -293,7 +298,7 @@ contract TestGenerateGenesis is Test, AddressResolver { SignalService signalServiceProxy = SignalService(getPredeployedContractAddress("SignalService")); - assertEq(owner, signalServiceProxy.owner()); + assertEq(ownerSecurityCouncil, signalServiceProxy.owner()); signalServiceProxy.sendSignal(keccak256(abi.encodePacked(block.prevrandao))); @@ -304,7 +309,7 @@ contract TestGenerateGenesis is Test, AddressResolver { ) ); - vm.startPrank(owner); + vm.startPrank(ownerSecurityCouncil); SignalService signalService = SignalService(payable(getPredeployedContractAddress("SignalServiceImpl"))); @@ -335,11 +340,22 @@ contract TestGenerateGenesis is Test, AddressResolver { assertEq(address(contractAddress).code, vm.parseBytes(deployedCode)); } + function checkProxyImplementation( string memory proxyName, string memory contractName ) private + { + return checkProxyImplementation(proxyName, contractName, ownerSecurityCouncil); + } + + function checkProxyImplementation( + string memory proxyName, + string memory contractName, + address owner + ) + private { vm.startPrank(owner); address contractAddress = getPredeployedContractAddress(contractName); diff --git a/packages/protocol/genesis/test_config.js b/packages/protocol/genesis/test_config.js index abb25629703..aa65ccec1ce 100644 --- a/packages/protocol/genesis/test_config.js +++ b/packages/protocol/genesis/test_config.js @@ -2,7 +2,9 @@ const ADDRESS_LENGTH = 40; module.exports = { - contractOwner: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ownerTimelockController: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + ownerSecurityCouncil: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + ownerChainId: 1, chainId: 167, seedAccounts: [ { diff --git a/packages/protocol/test/L1/Guardians.t.sol b/packages/protocol/test/L1/Guardians.t.sol index da13a9e4356..92e780ae195 100644 --- a/packages/protocol/test/L1/Guardians.t.sol +++ b/packages/protocol/test/L1/Guardians.t.sol @@ -31,7 +31,7 @@ contract TestSignalService is TaikoTest { deployProxy({ name: "guardians", impl: address(new DummyGuardians()), - data: bytes.concat(DummyGuardians.init.selector) + data: abi.encodeCall(DummyGuardians.init, ()) }) ); } diff --git a/packages/protocol/test/L2/TaikoL2.t.sol b/packages/protocol/test/L2/TaikoL2.t.sol index 7784ade85ae..aa351aaa9ea 100644 --- a/packages/protocol/test/L2/TaikoL2.t.sol +++ b/packages/protocol/test/L2/TaikoL2.t.sol @@ -17,40 +17,36 @@ contract TestTaikoL2 is TaikoTest { // same as `block_gas_limit` in foundry.toml uint32 public constant BLOCK_GAS_LIMIT = 30_000_000; - AddressManager public addressManager; - SignalService public ss; + address public addressManager; TaikoL2EIP1559Configurable public L2; SkipBasefeeCheckL2 public L2skip; function setUp() public { - addressManager = AddressManager( - deployProxy({ - name: "address_manager", - impl: address(new AddressManager()), - data: bytes.concat(AddressManager.init.selector) - }) - ); - - ss = SignalService( - deployProxy({ - name: "signal_service", - impl: address(new SignalService()), - data: bytes.concat(SignalService.init.selector), - registerTo: address(addressManager), - owner: address(0) - }) - ); + addressManager = deployProxy({ + name: "address_manager", + impl: address(new AddressManager()), + data: abi.encodeCall(AddressManager.init, ()) + }); + + deployProxy({ + name: "signal_service", + impl: address(new SignalService()), + data: abi.encodeCall(SignalService.init, ()), + registerTo: addressManager, + owner: address(0) + }); uint64 gasExcess = 0; uint8 quotient = 8; uint32 gasTarget = 60_000_000; + uint64 l1ChainId = 12_345; L2 = TaikoL2EIP1559Configurable( payable( deployProxy({ name: "taiko_l2", impl: address(new TaikoL2EIP1559Configurable()), - data: bytes.concat(TaikoL2.init.selector, abi.encode(address(ss), gasExcess)) + data: abi.encodeCall(TaikoL2.init, (addressManager, l1ChainId, gasExcess)) }) ) ); @@ -63,7 +59,7 @@ contract TestTaikoL2 is TaikoTest { deployProxy({ name: "taiko_l2", impl: address(new SkipBasefeeCheckL2()), - data: bytes.concat(TaikoL2.init.selector, abi.encode(address(ss), gasExcess)) + data: abi.encodeCall(TaikoL2.init, (addressManager, l1ChainId, gasExcess)) }) ) ); @@ -258,11 +254,6 @@ contract TestTaikoL2 is TaikoTest { L2skip.anchor(l1Hash, l1SignalRoot, l1Height, parentGasLimit); } - function registerAddress(bytes32 nameHash, address addr) internal { - addressManager.setAddress(uint64(block.chainid), nameHash, addr); - console2.log(block.chainid, uint256(nameHash), unicode"→", addr); - } - // Semi-random number generator function pickRandomNumber( uint256 randomNum, diff --git a/packages/protocol/test/common/EssentialContract.t.sol b/packages/protocol/test/common/EssentialContract.t.sol index f78a6bbc392..2b4d48ace6a 100644 --- a/packages/protocol/test/common/EssentialContract.t.sol +++ b/packages/protocol/test/common/EssentialContract.t.sol @@ -28,7 +28,7 @@ contract Target2 is Target1 { contract TestOwnerUUPSUpgradable is TaikoTest { function test_essential_behind_1967_proxy() external { - bytes memory data = bytes.concat(Target1.init.selector); + bytes memory data = abi.encodeCall(Target1.init, ()); vm.startPrank(Alice); ERC1967Proxy proxy = new ERC1967Proxy(address(new Target1()), data); Target1 target = Target1(address(proxy)); @@ -49,7 +49,7 @@ contract TestOwnerUUPSUpgradable is TaikoTest { target.adjust(); address v2 = address(new Target2()); - data = bytes.concat(Target2.update.selector); + data = abi.encodeCall(Target2.update, ()); vm.prank(Bob); vm.expectRevert(); @@ -67,7 +67,7 @@ contract TestOwnerUUPSUpgradable is TaikoTest { // This tests shows that the admin() and owner() cannot be the same, otherwise, // the owner cannot transact delegated functions on implementation. function test_essential_behind_transparent_proxy() external { - bytes memory data = bytes.concat(Target1.init.selector); + bytes memory data = abi.encodeCall(Target1.init, ()); vm.startPrank(Alice); TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(address(new Target1()), Bob, data); diff --git a/packages/protocol/test/signal/SignalService.t.sol b/packages/protocol/test/signal/SignalService.t.sol index 280d0492ec2..dc8b97db94d 100644 --- a/packages/protocol/test/signal/SignalService.t.sol +++ b/packages/protocol/test/signal/SignalService.t.sol @@ -19,7 +19,7 @@ contract TestSignalService is TaikoTest { deployProxy({ name: "address_manager", impl: address(new AddressManager()), - data: bytes.concat(AddressManager.init.selector), + data: abi.encodeCall(AddressManager.init, ()), registerTo: address(addressManager), owner: address(0) }) @@ -29,7 +29,7 @@ contract TestSignalService is TaikoTest { deployProxy({ name: "signal_service", impl: address(new SignalService()), - data: bytes.concat(SignalService.init.selector) + data: abi.encodeCall(SignalService.init, ()) }) ); @@ -37,7 +37,7 @@ contract TestSignalService is TaikoTest { deployProxy({ name: "signal_service", impl: address(new SignalService()), - data: bytes.concat(SignalService.init.selector) + data: abi.encodeCall(SignalService.init, ()) }) ); diff --git a/packages/protocol/test/team/TimelockTokenPool.t.sol b/packages/protocol/test/team/TimelockTokenPool.t.sol index e0f4caff512..4b658ad3419 100644 --- a/packages/protocol/test/team/TimelockTokenPool.t.sol +++ b/packages/protocol/test/team/TimelockTokenPool.t.sol @@ -20,7 +20,7 @@ contract TestTimelockTokenPool is TaikoTest { deployProxy({ name: "time_lock_token_pool", impl: address(new TimelockTokenPool()), - data: bytes.concat(TimelockTokenPool.init.selector, abi.encode(address(tko), Vault)) + data: abi.encodeCall(TimelockTokenPool.init, (address(tko), Vault)) }) ); } diff --git a/packages/protocol/test/team/airdrop/MerkleClaimable.t.sol b/packages/protocol/test/team/airdrop/MerkleClaimable.t.sol index 49cfd6920c8..a7afe7e11bf 100644 --- a/packages/protocol/test/team/airdrop/MerkleClaimable.t.sol +++ b/packages/protocol/test/team/airdrop/MerkleClaimable.t.sol @@ -27,9 +27,7 @@ contract TestERC20Airdrop is TaikoTest { deployProxy({ name: "airdrop", impl: address(new ERC20Airdrop()), - data: bytes.concat( - ERC20Airdrop.init.selector, abi.encode(0, 0, merkleRoot, address(token), owner) - ) + data: abi.encodeCall(ERC20Airdrop.init, (0, 0, merkleRoot, address(token), owner)) }) ); @@ -39,9 +37,8 @@ contract TestERC20Airdrop is TaikoTest { deployProxy({ name: "airdrop", impl: address(new ERC20Airdrop2()), - data: bytes.concat( - ERC20Airdrop2.init.selector, - abi.encode(0, 0, merkleRoot, address(token), owner, 10 days) + data: abi.encodeCall( + ERC20Airdrop2.init, (0, 0, merkleRoot, address(token), owner, 10 days) ) }) ); diff --git a/packages/protocol/test/tokenvault/BridgedERC20.t.sol b/packages/protocol/test/tokenvault/BridgedERC20.t.sol index cae02838b10..3162437cd63 100644 --- a/packages/protocol/test/tokenvault/BridgedERC20.t.sol +++ b/packages/protocol/test/tokenvault/BridgedERC20.t.sol @@ -12,7 +12,7 @@ contract TestBridgedERC20 is TaikoTest { manager = deployProxy({ name: "address_manager", impl: address(new AddressManager()), - data: bytes.concat(AddressManager.init.selector) + data: abi.encodeCall(AddressManager.init, ()) }); register(manager, "erc20_vault", vault); @@ -130,9 +130,8 @@ contract TestBridgedERC20 is TaikoTest { deployProxy({ name: "bridged_token1", impl: address(new BridgedERC20()), - data: bytes.concat( - BridgedERC20.init.selector, - abi.encode(address(manager), srcToken, srcChainId, srcDecimals, name, name) + data: abi.encodeCall( + BridgedERC20.init, (address(manager), srcToken, srcChainId, srcDecimals, name, name) ), registerTo: manager, owner: owner diff --git a/packages/protocol/test/tokenvault/ERC1155Vault.t.sol b/packages/protocol/test/tokenvault/ERC1155Vault.t.sol index d01484dc499..8e1f2623c98 100644 --- a/packages/protocol/test/tokenvault/ERC1155Vault.t.sol +++ b/packages/protocol/test/tokenvault/ERC1155Vault.t.sol @@ -111,7 +111,7 @@ contract ERC1155VaultTest is TaikoTest { deployProxy({ name: "address_manager", impl: address(new AddressManager()), - data: bytes.concat(AddressManager.init.selector) + data: abi.encodeCall(AddressManager.init, ()) }) ); @@ -120,7 +120,7 @@ contract ERC1155VaultTest is TaikoTest { deployProxy({ name: "bridge", impl: address(new Bridge()), - data: bytes.concat(Bridge.init.selector, abi.encode(addressManager)), + data: abi.encodeCall(Bridge.init, (address(addressManager))), registerTo: address(addressManager), owner: address(0) }) @@ -132,7 +132,7 @@ contract ERC1155VaultTest is TaikoTest { deployProxy({ name: "bridge", impl: address(new Bridge()), - data: bytes.concat(Bridge.init.selector, abi.encode(addressManager)), + data: abi.encodeCall(Bridge.init, (address(addressManager))), registerTo: address(addressManager), owner: address(0) }) @@ -143,7 +143,7 @@ contract ERC1155VaultTest is TaikoTest { deployProxy({ name: "signal_service", impl: address(new SignalService()), - data: bytes.concat(SignalService.init.selector) + data: abi.encodeCall(SignalService.init, ()) }) ); @@ -151,7 +151,7 @@ contract ERC1155VaultTest is TaikoTest { deployProxy({ name: "erc1155_vault", impl: address(new ERC1155Vault()), - data: bytes.concat(BaseVault.init.selector, abi.encode(address(addressManager))) + data: abi.encodeCall(BaseVault.init, (address(addressManager))) }) ); @@ -159,7 +159,7 @@ contract ERC1155VaultTest is TaikoTest { deployProxy({ name: "erc1155_vault", impl: address(new ERC1155Vault()), - data: bytes.concat(BaseVault.init.selector, abi.encode(address(addressManager))) + data: abi.encodeCall(BaseVault.init, (address(addressManager))) }) ); @@ -170,7 +170,7 @@ contract ERC1155VaultTest is TaikoTest { deployProxy({ name: "signal_service", impl: address(new SkipProofCheckSignal()), - data: bytes.concat(SignalService.init.selector) + data: abi.encodeCall(SignalService.init, ()) }) ); diff --git a/packages/protocol/test/tokenvault/ERC20Vault.t.sol b/packages/protocol/test/tokenvault/ERC20Vault.t.sol index f01970cb72d..44b0ac7603f 100644 --- a/packages/protocol/test/tokenvault/ERC20Vault.t.sol +++ b/packages/protocol/test/tokenvault/ERC20Vault.t.sol @@ -89,9 +89,7 @@ contract TestERC20Vault is TaikoTest { deployProxy({ name: "taiko_token", impl: address(new TaikoToken()), - data: bytes.concat( - TaikoToken.init.selector, abi.encode("Taiko Token", "TTKOk", address(this)) - ) + data: abi.encodeCall(TaikoToken.init, ("Taiko Token", "TTKOk", address(this))) }) ); @@ -99,7 +97,7 @@ contract TestERC20Vault is TaikoTest { deployProxy({ name: "address_manager", impl: address(new AddressManager()), - data: bytes.concat(AddressManager.init.selector) + data: abi.encodeCall(AddressManager.init, ()) }) ); @@ -109,7 +107,7 @@ contract TestERC20Vault is TaikoTest { deployProxy({ name: "erc20_vault", impl: address(new ERC20Vault()), - data: bytes.concat(BaseVault.init.selector, abi.encode(address(addressManager))) + data: abi.encodeCall(BaseVault.init, (address(addressManager))) }) ); @@ -117,7 +115,7 @@ contract TestERC20Vault is TaikoTest { deployProxy({ name: "erc20_vault", impl: address(new ERC20Vault()), - data: bytes.concat(BaseVault.init.selector, abi.encode(address(addressManager))) + data: abi.encodeCall(BaseVault.init, (address(addressManager))) }) ); @@ -129,7 +127,7 @@ contract TestERC20Vault is TaikoTest { deployProxy({ name: "bridge", impl: address(new Bridge()), - data: bytes.concat(Bridge.init.selector, abi.encode(addressManager)), + data: abi.encodeCall(Bridge.init, (address(addressManager))), registerTo: address(addressManager), owner: address(0) }) @@ -143,7 +141,7 @@ contract TestERC20Vault is TaikoTest { deployProxy({ name: "signal_service", impl: address(new SignalService()), - data: bytes.concat(SignalService.init.selector), + data: abi.encodeCall(SignalService.init, ()), registerTo: address(0), owner: address(0) }) diff --git a/packages/protocol/test/tokenvault/ERC721Vault.t.sol b/packages/protocol/test/tokenvault/ERC721Vault.t.sol index b67aafd935a..dc25777b94c 100644 --- a/packages/protocol/test/tokenvault/ERC721Vault.t.sol +++ b/packages/protocol/test/tokenvault/ERC721Vault.t.sol @@ -127,7 +127,7 @@ contract ERC721VaultTest is TaikoTest { deployProxy({ name: "address_manager", impl: address(new AddressManager()), - data: bytes.concat(AddressManager.init.selector) + data: abi.encodeCall(AddressManager.init, ()) }) ); @@ -136,7 +136,7 @@ contract ERC721VaultTest is TaikoTest { deployProxy({ name: "bridge", impl: address(new Bridge()), - data: bytes.concat(Bridge.init.selector, abi.encode(addressManager)), + data: abi.encodeCall(Bridge.init, (address(addressManager))), registerTo: address(addressManager), owner: address(0) }) @@ -148,7 +148,7 @@ contract ERC721VaultTest is TaikoTest { deployProxy({ name: "bridge", impl: address(new Bridge()), - data: bytes.concat(Bridge.init.selector, abi.encode(addressManager)), + data: abi.encodeCall(Bridge.init, (address(addressManager))), registerTo: address(addressManager), owner: address(0) }) @@ -159,7 +159,7 @@ contract ERC721VaultTest is TaikoTest { deployProxy({ name: "signal_service", impl: address(new SignalService()), - data: bytes.concat(SignalService.init.selector) + data: abi.encodeCall(SignalService.init, ()) }) ); @@ -167,7 +167,7 @@ contract ERC721VaultTest is TaikoTest { deployProxy({ name: "erc721_vault", impl: address(new ERC721Vault()), - data: bytes.concat(BaseVault.init.selector, abi.encode(address(addressManager))) + data: abi.encodeCall(BaseVault.init, (address(addressManager))) }) ); @@ -175,7 +175,7 @@ contract ERC721VaultTest is TaikoTest { deployProxy({ name: "erc721_vault", impl: address(new ERC721Vault()), - data: bytes.concat(BaseVault.init.selector, abi.encode(address(addressManager))) + data: abi.encodeCall(BaseVault.init, (address(addressManager))) }) ); @@ -186,7 +186,7 @@ contract ERC721VaultTest is TaikoTest { deployProxy({ name: "signal_service", impl: address(new SkipProofCheckSignal()), - data: bytes.concat(SignalService.init.selector) + data: abi.encodeCall(SignalService.init, ()) }) ); diff --git a/packages/protocol/utils/generate_genesis/interface.ts b/packages/protocol/utils/generate_genesis/interface.ts index 054b7837f3f..36759d1b462 100644 --- a/packages/protocol/utils/generate_genesis/interface.ts +++ b/packages/protocol/utils/generate_genesis/interface.ts @@ -1,6 +1,7 @@ export interface Config { - contractOwner: string; - contractAdmin: string; + ownerTimelockController: string; + ownerSecurityCouncil: string; + ownerChainId: number; chainId: number; seedAccounts: Array<{ [key: string]: number; diff --git a/packages/protocol/utils/generate_genesis/main.ts b/packages/protocol/utils/generate_genesis/main.ts index a792c95a1c5..d50bd9d9f0e 100644 --- a/packages/protocol/utils/generate_genesis/main.ts +++ b/packages/protocol/utils/generate_genesis/main.ts @@ -18,13 +18,15 @@ async function main() { : path.join(process.cwd(), process.argv[2]), ); - const contractOwner = config.contractOwner; + const ownerTimelockController = config.ownerTimelockController; + const ownerSecurityCouncil = config.ownerSecurityCouncil; const chainId = config.chainId; const seedAccounts = config.seedAccounts; const predeployERC20 = config.predeployERC20; if ( - !ethers.utils.isAddress(contractOwner) || + !ethers.utils.isAddress(ownerTimelockController) || + !ethers.utils.isAddress(ownerSecurityCouncil) || !Number.isInteger(chainId) || !Array.isArray(seedAccounts) || !seedAccounts.every((seedAccount) => { @@ -38,7 +40,8 @@ async function main() { ) { throw new Error( `invalid input: ${JSON.stringify({ - contractOwner, + ownerTimelockController, + ownerSecurityCouncil, chainId, seedAccounts, })}`, diff --git a/packages/protocol/utils/generate_genesis/taikoL2.ts b/packages/protocol/utils/generate_genesis/taikoL2.ts index 39d1e9d4ed5..b7e33c9a0c1 100644 --- a/packages/protocol/utils/generate_genesis/taikoL2.ts +++ b/packages/protocol/utils/generate_genesis/taikoL2.ts @@ -17,7 +17,13 @@ export async function deployTaikoL2( config: Config, result: Result, ): Promise { - const { contractOwner, chainId, seedAccounts } = config; + const { + ownerTimelockController, + ownerSecurityCouncil, + ownerChainId, + chainId, + seedAccounts, + } = config; const alloc: any = {}; @@ -42,7 +48,9 @@ export async function deployTaikoL2( console.log("\n"); const contractConfigs: any = await generateContractConfigs( - contractOwner, + ownerTimelockController, + ownerSecurityCouncil, + ownerChainId, chainId, config.contractAddresses, config.param1559, @@ -112,7 +120,9 @@ export async function deployTaikoL2( // generateContractConfigs returns all L2 contracts address, deployedBytecode, // and initialized variables. async function generateContractConfigs( - contractOwner: string, + ownerTimelockController: string, + ownerSecurityCouncil: string, + ownerChainId: number, chainId: number, hardCodedAddresses: any, param1559: any, @@ -192,7 +202,7 @@ async function generateContractConfigs( addressMap[contractName] = hardCodedAddresses[contractName]; } else { addressMap[contractName] = ethers.utils.getCreate2Address( - contractOwner, + ownerSecurityCouncil, ethers.utils.keccak256( ethers.utils.toUtf8Bytes(`${chainId}${contractName}`), ), @@ -212,7 +222,7 @@ async function generateContractConfigs( contractArtifacts.SharedAddressManagerImpl.deployedBytecode .object, variables: { - _owner: contractOwner, + _owner: ownerSecurityCouncil, }, }, SharedAddressManager: { @@ -224,7 +234,7 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // Ownable2Upgradeable - _owner: contractOwner, + _owner: ownerSecurityCouncil, // AddressManager addresses: { [chainId]: { @@ -267,7 +277,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: contractOwner, + _owner: ownerSecurityCouncil, }, }, Bridge: { @@ -281,7 +291,7 @@ async function generateContractConfigs( _reentry: 1, // _FALSE _paused: 1, // _FALSE // Ownable2Upgradeable - _owner: contractOwner, + _owner: ownerSecurityCouncil, // AddressResolver addressManager: addressMap.SharedAddressManager, }, @@ -297,7 +307,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: contractOwner, + _owner: ownerSecurityCouncil, }, }, ERC20Vault: { @@ -312,7 +322,7 @@ async function generateContractConfigs( _reentry: 1, // _FALSE _paused: 1, // _FALSE // Ownable2Upgradeable - _owner: contractOwner, + _owner: ownerSecurityCouncil, // AddressResolver addressManager: addressMap.SharedAddressManager, }, @@ -328,7 +338,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: contractOwner, + _owner: ownerSecurityCouncil, }, }, ERC721Vault: { @@ -343,7 +353,7 @@ async function generateContractConfigs( _reentry: 1, // _FALSE _paused: 1, // _FALSE // Ownable2Upgradeable - _owner: contractOwner, + _owner: ownerSecurityCouncil, // AddressResolver addressManager: addressMap.SharedAddressManager, }, @@ -359,7 +369,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: contractOwner, + _owner: ownerSecurityCouncil, }, }, ERC1155Vault: { @@ -374,7 +384,7 @@ async function generateContractConfigs( _reentry: 1, // _FALSE _paused: 1, // _FALSE // Ownable2Upgradeable - _owner: contractOwner, + _owner: ownerSecurityCouncil, // AddressResolver addressManager: addressMap.SharedAddressManager, }, @@ -405,7 +415,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: contractOwner, + _owner: ownerSecurityCouncil, }, }, SignalService: { @@ -420,7 +430,7 @@ async function generateContractConfigs( _reentry: 1, // _FALSE _paused: 1, // _FALSE // Ownable2Upgradeable - _owner: contractOwner, + _owner: ownerSecurityCouncil, authorizedAddresses: { [addressMap.TaikoL2]: ethers.utils.hexZeroPad( ethers.utils.hexlify(chainId), @@ -441,7 +451,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: contractOwner, + _owner: ownerTimelockController, }, }, TaikoL2: { @@ -450,8 +460,9 @@ async function generateContractConfigs( variables: { // TaikoL2 // Ownable2Upgradeable - _owner: contractOwner, - signalService: addressMap.SignalService, + _owner: ownerTimelockController, + addressManager: addressMap.RollupAddressManager, + ownerChainId, gasExcess: param1559.gasExcess, // keccak256(abi.encodePacked(block.chainid, basefee, ancestors)) publicInputHash: `${ethers.utils.solidityKeccak256( @@ -479,7 +490,7 @@ async function generateContractConfigs( contractArtifacts.RollupAddressManagerImpl.deployedBytecode .object, variables: { - _owner: contractOwner, + _owner: ownerSecurityCouncil, }, }, RollupAddressManager: { @@ -491,13 +502,16 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // Ownable2Upgradeable - _owner: contractOwner, + _owner: ownerSecurityCouncil, // AddressManager addresses: { [chainId]: { [ethers.utils.hexlify( ethers.utils.toUtf8Bytes("taiko"), )]: addressMap.TaikoL2, + [ethers.utils.hexlify( + ethers.utils.toUtf8Bytes("bridge"), + )]: addressMap.Bridge, [ethers.utils.hexlify( ethers.utils.toUtf8Bytes("signal_service"), )]: addressMap.SignalService,