diff --git a/packages/nfts/script/trailblazers-season-2/Deploy.s.sol b/packages/nfts/script/trailblazers-season-2/Deploy.s.sol index 2775e877772..d92ce7dd670 100644 --- a/packages/nfts/script/trailblazers-season-2/Deploy.s.sol +++ b/packages/nfts/script/trailblazers-season-2/Deploy.s.sol @@ -22,11 +22,12 @@ contract DeployS2Script is Script { BadgeRecruitment recruitment; // Taiko Mainnet Values + /* //address owner = 0xf8ff2AF0DC1D5BA4811f22aCb02936A1529fd2Be; address claimMintSigner = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; address recruitmentSigner = 0x9Fc8d56c7376f9b062FEe7E02BAdFA670d603248; string baseURI = - "https://taikonfts.4everland.link/ipfs/bafybeiatuzeeeznd3hi5qiulslxcjd22ebu45t4fra2jvi3smhocr2c66a"; + "https://taikonfts.4everland.link/ipfs/bafybeiatuzeeeznd3hi5qiulslxcjd22ebu45t4fra2jvi3smhocr2c66a"; IMinimalBlacklist blacklist = IMinimalBlacklist(0xfA5EA6f9A13532cd64e805996a941F101CCaAc9a); uint256 public MAX_INFLUENCES = 5; @@ -37,11 +38,10 @@ contract DeployS2Script is Script { uint256 public DEFAULT_CYCLE_DURATION = 7 days; uint256 public s1EndDate = 1_734_350_400; // Dec 16th 2024, noon UTC uint256 public S1_LOCK_DURATION = (s1EndDate - block.timestamp); - + */ // Hekla Testnet Values - /* string baseURI = - "https://taikonfts.4everland.link/ipfs/bafybeiatuzeeeznd3hi5qiulslxcjd22ebu45t4fra2jvi3smhocr2c66a"; + "https://taikonfts.4everland.link/ipfs/bafybeiatuzeeeznd3hi5qiulslxcjd22ebu45t4fra2jvi3smhocr2c66a"; IMinimalBlacklist blacklist = IMinimalBlacklist(0xe61E9034b5633977eC98E302b33e321e8140F105); address claimMintSigner = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; @@ -54,7 +54,6 @@ contract DeployS2Script is Script { uint256 public MAX_INFLUENCES_DIVIDER = 100; uint256 public DEFAULT_CYCLE_DURATION = 7 days; uint256 public S1_LOCK_DURATION = 365 days; - */ address s1Contract = 0xa20a8856e00F5ad024a55A663F06DCc419FFc4d5; diff --git a/packages/nfts/script/trailblazers-season-2/UpgradeRecruitmentsV2.s.sol b/packages/nfts/script/trailblazers-season-2/UpgradeRecruitmentsV2.s.sol new file mode 100644 index 00000000000..0b9d9218d09 --- /dev/null +++ b/packages/nfts/script/trailblazers-season-2/UpgradeRecruitmentsV2.s.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import { UtilsScript } from "./Utils.s.sol"; +import { Script, console } from "forge-std/src/Script.sol"; +import { BadgeRecruitment } from "../../contracts/trailblazers-season-2/BadgeRecruitment.sol"; +import { BadgeRecruitmentV2 } from "../../contracts/trailblazers-season-2/BadgeRecruitmentV2.sol"; + +contract UpgradeRecruitmentsV2 is Script { + UtilsScript public utils; + string public jsonLocation; + uint256 public deployerPrivateKey; + + address recruitmentAddress = 0xa9Ceb04F3aF71fF123409d426A92BABb5124970C; + BadgeRecruitment public recruitmentV1; + BadgeRecruitmentV2 public recruitmentV2; + + function setUp() public { + utils = new UtilsScript(); + utils.setUp(); + + jsonLocation = utils.getContractJsonLocation(); + deployerPrivateKey = utils.getPrivateKey(); + } + + function run() public { + vm.startBroadcast(deployerPrivateKey); + recruitmentV1 = BadgeRecruitment(recruitmentAddress); + + recruitmentV1.upgradeToAndCall( + address(new BadgeRecruitmentV2()), abi.encodeCall(BadgeRecruitmentV2.version, ()) + ); + + recruitmentV2 = BadgeRecruitmentV2(address(recruitmentV1)); + + console.log("Upgraded BadgeRecruitmentV2 to:", address(recruitmentV2)); + } +} diff --git a/packages/protocol/contracts/layer1/based/ForcedInclusionInbox.sol b/packages/protocol/contracts/layer1/based/ForcedInclusionInbox.sol index da9e6664db8..ee51d21474f 100644 --- a/packages/protocol/contracts/layer1/based/ForcedInclusionInbox.sol +++ b/packages/protocol/contracts/layer1/based/ForcedInclusionInbox.sol @@ -9,7 +9,6 @@ import "src/shared/libs/LibNetwork.sol"; import "src/shared/libs/LibStrings.sol"; import "src/shared/signal/ISignalService.sol"; import "src/layer1/verifiers/IVerifier.sol"; -import "./IFork.sol"; import "./ITaikoInbox.sol"; import "./IForcedInclusionStore.sol"; @@ -68,12 +67,12 @@ contract ForcedInclusionInbox is EssentialContract { nonReentrant returns (ITaikoInbox.BatchInfo memory info_, ITaikoInbox.BatchMetadata memory meta_) { - ITaikoInbox inbox = ITaikoInbox(resolve(LibStrings.B_TAIKO, false)); + ITaikoInbox inbox = ITaikoInbox(resolveAddress(LibStrings.B_TAIKO, false)); (info_, meta_) = inbox.proposeBatch(_params, _txList); // Process the next forced inclusion. IForcedInclusionStore store = - IForcedInclusionStore(resolve(LibStrings.B_FORCED_INCLUSION_STORE, false)); + IForcedInclusionStore(resolveAddress(LibStrings.B_FORCED_INCLUSION_STORE, false)); IForcedInclusionStore.ForcedInclusion memory inclusion = store.consumeForcedInclusion(msg.sender); diff --git a/packages/protocol/contracts/layer1/based/IFork.sol b/packages/protocol/contracts/layer1/based/IFork.sol deleted file mode 100644 index e968eb9ffc5..00000000000 --- a/packages/protocol/contracts/layer1/based/IFork.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "src/shared/based/LibSharedData.sol"; - -/// @title IFork -/// @custom:security-contact security@taiko.xyz -interface IFork { - /// @notice Returns true if the fork is active, false otherwise - function isForkActive() external view returns (bool); -} diff --git a/packages/protocol/contracts/layer1/based/ITaikoInbox.sol b/packages/protocol/contracts/layer1/based/ITaikoInbox.sol index dbe675de4fe..9fbf96fe923 100644 --- a/packages/protocol/contracts/layer1/based/ITaikoInbox.sol +++ b/packages/protocol/contracts/layer1/based/ITaikoInbox.sol @@ -71,6 +71,8 @@ interface ITaikoInbox { uint32 blobByteOffset; uint32 blobByteSize; uint32 gasLimit; + uint64 lastBlockId; + uint64 lastBlockTimestamp; // Data for the L2 anchor transaction, shared by all blocks in the batch uint64 anchorBlockId; // corresponds to the `_anchorStateRoot` parameter in the anchor transaction. @@ -187,7 +189,7 @@ interface ITaikoInbox { uint256 batchId_mod_batchRingBufferSize => mapping(uint24 transitionId => TransitionState ts) ) transitions; - bytes32 __reserve1; // Used as a ring buffer for Ether deposits + bytes32 __reserve1; // slot 4 - was used as a ring buffer for Ether deposits Stats1 stats1; // slot 5 Stats2 stats2; // slot 6 mapping(address account => uint256 bond) bondBalance; @@ -264,6 +266,7 @@ interface ITaikoInbox { error CustomProposerMissing(); error CustomProposerNotAllowed(); error EtherNotPaidAsBond(); + error ForkNotActivated(); error InsufficientBond(); error InvalidBlobParams(); error InvalidGenesisBlockHash(); @@ -344,7 +347,7 @@ interface ITaikoInbox { /// @param _batchId The batch ID. /// @param _tid The transition ID. /// @return The specified transition state. - function getTransition( + function getTransitionById( uint64 _batchId, uint24 _tid ) @@ -357,7 +360,7 @@ interface ITaikoInbox { /// @param _batchId The batch ID. /// @param _parentHash The parent hash. /// @return The specified transition state. - function getTransition( + function getTransitionByParentHash( uint64 _batchId, bytes32 _parentHash ) @@ -393,5 +396,5 @@ interface ITaikoInbox { /// @notice Retrieves the current protocol configuration. /// @return The current configuration. - function getConfig() external view returns (Config memory); + function pacayaConfig() external view returns (Config memory); } diff --git a/packages/protocol/contracts/layer1/based/TaikoInbox.sol b/packages/protocol/contracts/layer1/based/TaikoInbox.sol index a503bc43f40..8ba1033ff6c 100644 --- a/packages/protocol/contracts/layer1/based/TaikoInbox.sol +++ b/packages/protocol/contracts/layer1/based/TaikoInbox.sol @@ -10,11 +10,8 @@ import "src/shared/libs/LibNetwork.sol"; import "src/shared/libs/LibStrings.sol"; import "src/shared/signal/ISignalService.sol"; import "src/layer1/verifiers/IVerifier.sol"; -import "./IFork.sol"; import "./ITaikoInbox.sol"; -// import "forge-std/src/console2.sol"; - /// @title TaikoInbox /// @notice Acts as the inbox for the Taiko Alethia protocol, a simplified version of the /// original Taiko-Based Contestable Rollup (BCR). The tier-based proof system and @@ -28,7 +25,7 @@ import "./ITaikoInbox.sol"; /// /// @dev Registered in the address resolver as "taiko". /// @custom:security-contact security@taiko.xyz -abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { +abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko { using LibMath for uint256; State public state; // storage layout much match Ontake fork @@ -58,8 +55,9 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { { Stats2 memory stats2 = state.stats2; require(!stats2.paused, ContractPaused()); + require(stats2.numBatches >= pacayaConfig().forkHeights.pacaya, ForkNotActivated()); - Config memory config = getConfig(); + Config memory config = pacayaConfig(); unchecked { require( @@ -70,7 +68,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { BatchParams memory params = abi.decode(_params, (BatchParams)); { - address whitelistedProposer = resolve(LibStrings.B_WHITELISTED_PROPOSER, true); + address whitelistedProposer = resolveAddress(LibStrings.B_WHITELISTED_PROPOSER, true); if (whitelistedProposer == address(0)) { require(params.proposer == address(0), CustomProposerNotAllowed()); params.proposer = msg.sender; @@ -138,6 +136,8 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { blobByteOffset: params.blobParams.byteOffset, blobByteSize: params.blobParams.byteSize, gasLimit: config.blockMaxGasLimit, + lastBlockId: 0, // to be initialised later + lastBlockTimestamp: lastBlockTimestamp, // // Data for the L2 anchor transaction, shared by all blocks in the batch anchorBlockId: anchorBlockId, @@ -149,6 +149,10 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { require(info_.anchorBlockHash != 0, ZeroAnchorBlockHash()); + info_.lastBlockId = stats2.numBatches == config.forkHeights.pacaya + ? stats2.numBatches + uint64(params.blocks.length) - 1 + : lastBatch.lastBlockId + uint64(params.blocks.length); + (info_.txsHash, info_.blobHashes) = _calculateTxsHash(keccak256(_txList), params.blobParams); @@ -178,12 +182,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { _debitBond(params.proposer, livenessBond); // SSTORE #3 {{ - if (stats2.numBatches == config.forkHeights.pacaya) { - batch.lastBlockId = batch.batchId + uint64(params.blocks.length) - 1; - } else { - batch.lastBlockId = lastBatch.lastBlockId + uint64(params.blocks.length); - } - + batch.lastBlockId = info_.lastBlockId; batch.livenessBond = livenessBond; batch._reserved3 = 0; // SSTORE }} @@ -212,13 +211,15 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { Stats2 memory stats2 = state.stats2; require(stats2.paused == false, ContractPaused()); - Config memory config = getConfig(); + Config memory config = pacayaConfig(); IVerifier.Context[] memory ctxs = new IVerifier.Context[](metas.length); bool hasConflictingProof; for (uint256 i; i < metas.length; ++i) { BatchMetadata memory meta = metas[i]; + require(meta.batchId >= pacayaConfig().forkHeights.pacaya, ForkNotActivated()); + require(meta.batchId > stats2.lastVerifiedBatchId, BatchNotFound()); require(meta.batchId < stats2.numBatches, BatchNotFound()); @@ -291,7 +292,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { } } - address verifier = resolve(LibStrings.B_PROOF_VERIFIER, false); + address verifier = resolveAddress(LibStrings.B_PROOF_VERIFIER, false); IVerifier(verifier).verifyProof(ctxs, _proof); // Emit the event @@ -312,6 +313,14 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { } } + /// @notice Verify batches by providing the length of the batches to verify. + /// @dev This function is necessary to upgrade from this fork to the next one. + /// @param _length Specifis how many batches to verify. The max number of batches to verify is + /// `pacayaConfig().maxBatchesToVerify * _length`. + function verifyBatches(uint64 _length) external nonZeroValue(_length) nonReentrant { + _verifyBatches(pacayaConfig(), state.stats2, _length); + } + /// @notice Manually write a transition for a batch. /// @dev This function is supposed to be used by the owner to force prove a transition for a /// block that has not been verified. @@ -329,7 +338,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { require(_blockHash != 0 && _parentHash != 0 && _stateRoot != 0, InvalidParams()); require(_batchId > state.stats2.lastVerifiedBatchId, BatchVerified()); - Config memory config = getConfig(); + Config memory config = pacayaConfig(); uint256 slot = _batchId % config.batchRingBufferSize; Batch storage batch = state.batches[slot]; require(batch.batchId == _batchId, BatchNotFound()); @@ -392,7 +401,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { } /// @inheritdoc ITaikoInbox - function getTransition( + function getTransitionById( uint64 _batchId, uint24 _tid ) @@ -400,7 +409,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { view returns (TransitionState memory) { - Config memory config = getConfig(); + Config memory config = pacayaConfig(); uint256 slot = _batchId % config.batchRingBufferSize; Batch storage batch = state.batches[slot]; require(batch.batchId == _batchId, BatchNotFound()); @@ -409,7 +418,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { } /// @inheritdoc ITaikoInbox - function getTransition( + function getTransitionByParentHash( uint64 _batchId, bytes32 _parentHash ) @@ -417,7 +426,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { view returns (TransitionState memory) { - Config memory config = getConfig(); + Config memory config = pacayaConfig(); uint256 slot = _batchId % config.batchRingBufferSize; Batch storage batch = state.batches[slot]; require(batch.batchId == _batchId, BatchNotFound()); @@ -461,11 +470,6 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { return true; } - // @inheritdoc IFork - function isForkActive() external view override returns (bool) { - return state.stats2.numBatches >= getConfig().forkHeights.pacaya; - } - // Public functions ------------------------------------------------------------------------- /// @inheritdoc EssentialContract @@ -475,12 +479,12 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { /// @inheritdoc ITaikoInbox function bondToken() public view returns (address) { - return resolve(LibStrings.B_BOND_TOKEN, true); + return resolveAddress(LibStrings.B_BOND_TOKEN, true); } /// @inheritdoc ITaikoInbox function getBatch(uint64 _batchId) public view returns (Batch memory batch_) { - Config memory config = getConfig(); + Config memory config = pacayaConfig(); batch_ = state.batches[_batchId % config.batchRingBufferSize]; require(batch_.batchId == _batchId, BatchNotFound()); @@ -492,7 +496,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { view returns (TransitionState memory ts_) { - Config memory config = getConfig(); + Config memory config = pacayaConfig(); uint64 slot = _batchId % config.batchRingBufferSize; Batch storage batch = state.batches[slot]; @@ -504,7 +508,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { } /// @inheritdoc ITaikoInbox - function getConfig() public view virtual returns (Config memory); + function pacayaConfig() public view virtual returns (Config memory); // Internal functions ---------------------------------------------------------------------- @@ -574,85 +578,96 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { private { uint64 batchId = _stats2.lastVerifiedBatchId; - uint256 slot = batchId % _config.batchRingBufferSize; - Batch storage batch = state.batches[slot]; - uint24 tid = batch.verifiedTransitionId; - bytes32 blockHash = state.transitions[slot][tid].blockHash; - - SyncBlock memory synced; - uint256 stopBatchId; + bool canVerifyBlocks; unchecked { - stopBatchId = (_config.maxBatchesToVerify * _length + _stats2.lastVerifiedBatchId + 1) - .min(_stats2.numBatches); + uint64 pacayaForkHeight = pacayaConfig().forkHeights.pacaya; + canVerifyBlocks = pacayaForkHeight == 0 || batchId >= pacayaForkHeight - 1; } - for (++batchId; batchId < stopBatchId; ++batchId) { - slot = batchId % _config.batchRingBufferSize; - batch = state.batches[slot]; - uint24 nextTransitionId = batch.nextTransitionId; + if (canVerifyBlocks) { + uint256 slot = batchId % _config.batchRingBufferSize; + Batch storage batch = state.batches[slot]; + uint24 tid = batch.verifiedTransitionId; + bytes32 blockHash = state.transitions[slot][tid].blockHash; - if (nextTransitionId <= 1) break; + SyncBlock memory synced; - TransitionState storage ts = state.transitions[slot][1]; - if (ts.parentHash == blockHash) { - tid = 1; - } else if (nextTransitionId > 2) { - uint24 _tid = state.transitionIds[batchId][blockHash]; - if (_tid == 0) break; - tid = _tid; - ts = state.transitions[slot][tid]; - } else { - break; + uint256 stopBatchId; + unchecked { + stopBatchId = ( + _config.maxBatchesToVerify * _length + _stats2.lastVerifiedBatchId + 1 + ).min(_stats2.numBatches); } - blockHash = ts.blockHash; + for (++batchId; batchId < stopBatchId; ++batchId) { + slot = batchId % _config.batchRingBufferSize; + batch = state.batches[slot]; + uint24 nextTransitionId = batch.nextTransitionId; - uint96 bondToReturn = ts.inProvingWindow ? batch.livenessBond : batch.livenessBond / 2; - _creditBond(ts.prover, bondToReturn); + if (nextTransitionId <= 1) break; - if (batchId % _config.stateRootSyncInternal == 0) { - synced.batchId = batchId; - synced.blockId = batch.lastBlockId; - synced.tid = tid; - synced.stateRoot = ts.stateRoot; - } + TransitionState storage ts = state.transitions[slot][1]; + if (ts.parentHash == blockHash) { + tid = 1; + } else if (nextTransitionId > 2) { + uint24 _tid = state.transitionIds[batchId][blockHash]; + if (_tid == 0) break; + tid = _tid; + ts = state.transitions[slot][tid]; + } else { + break; + } + + blockHash = ts.blockHash; + + uint96 bondToReturn = + ts.inProvingWindow ? batch.livenessBond : batch.livenessBond / 2; + _creditBond(ts.prover, bondToReturn); - for (uint24 i = 2; i < nextTransitionId; ++i) { - ts = state.transitions[slot][i]; - delete state.transitionIds[batchId][ts.parentHash]; + if (batchId % _config.stateRootSyncInternal == 0) { + synced.batchId = batchId; + synced.blockId = batch.lastBlockId; + synced.tid = tid; + synced.stateRoot = ts.stateRoot; + } + + for (uint24 i = 2; i < nextTransitionId; ++i) { + ts = state.transitions[slot][i]; + delete state.transitionIds[batchId][ts.parentHash]; + } } - } - unchecked { - --batchId; - } + unchecked { + --batchId; + } - if (_stats2.lastVerifiedBatchId != batchId) { - _stats2.lastVerifiedBatchId = batchId; + if (_stats2.lastVerifiedBatchId != batchId) { + _stats2.lastVerifiedBatchId = batchId; - batch = state.batches[_stats2.lastVerifiedBatchId % _config.batchRingBufferSize]; - batch.verifiedTransitionId = tid; - emit BatchesVerified(_stats2.lastVerifiedBatchId, blockHash); + batch = state.batches[_stats2.lastVerifiedBatchId % _config.batchRingBufferSize]; + batch.verifiedTransitionId = tid; + emit BatchesVerified(_stats2.lastVerifiedBatchId, blockHash); - if (synced.batchId != 0) { - if (synced.batchId != _stats2.lastVerifiedBatchId) { - // We write the synced batch's verifiedTransitionId to storage - batch = state.batches[synced.batchId % _config.batchRingBufferSize]; - batch.verifiedTransitionId = synced.tid; - } + if (synced.batchId != 0) { + if (synced.batchId != _stats2.lastVerifiedBatchId) { + // We write the synced batch's verifiedTransitionId to storage + batch = state.batches[synced.batchId % _config.batchRingBufferSize]; + batch.verifiedTransitionId = synced.tid; + } - Stats1 memory stats1 = state.stats1; - stats1.lastSyncedBatchId = batch.batchId; - stats1.lastSyncedAt = uint64(block.timestamp); - state.stats1 = stats1; + Stats1 memory stats1 = state.stats1; + stats1.lastSyncedBatchId = batch.batchId; + stats1.lastSyncedAt = uint64(block.timestamp); + state.stats1 = stats1; - emit Stats1Updated(stats1); + emit Stats1Updated(stats1); - // Ask signal service to write cross chain signal - ISignalService(resolve(LibStrings.B_SIGNAL_SERVICE, false)).syncChainData( - _config.chainId, LibStrings.H_STATE_ROOT, synced.blockId, synced.stateRoot - ); + // Ask signal service to write cross chain signal + ISignalService(resolveAddress(LibStrings.B_SIGNAL_SERVICE, false)).syncChainData( + _config.chainId, LibStrings.H_STATE_ROOT, synced.blockId, synced.stateRoot + ); + } } } @@ -757,7 +772,7 @@ abstract contract TaikoInbox is EssentialContract, ITaikoInbox, ITaiko, IFork { require(_params.signalSlots.length <= _maxSignalsToReceive, TooManySignals()); ISignalService signalService = - ISignalService(resolve(LibStrings.B_SIGNAL_SERVICE, false)); + ISignalService(resolveAddress(LibStrings.B_SIGNAL_SERVICE, false)); for (uint256 i; i < _params.signalSlots.length; ++i) { require(signalService.isSignalSent(_params.signalSlots[i]), SignalNotSent()); diff --git a/packages/protocol/contracts/layer1/devnet/DevnetInbox.sol b/packages/protocol/contracts/layer1/devnet/DevnetInbox.sol index 83a9f0d817e..e5fd7b69d2a 100644 --- a/packages/protocol/contracts/layer1/devnet/DevnetInbox.sol +++ b/packages/protocol/contracts/layer1/devnet/DevnetInbox.sol @@ -10,7 +10,7 @@ contract DevnetInbox is TaikoInbox { constructor(address _resolver) TaikoInbox(_resolver) { } /// @inheritdoc ITaikoInbox - function getConfig() public pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() public pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: 167_001, maxUnverifiedBatches: 324_000, diff --git a/packages/protocol/contracts/layer1/based/ForkRouter.sol b/packages/protocol/contracts/layer1/fork-router/ForkRouter.sol similarity index 74% rename from packages/protocol/contracts/layer1/based/ForkRouter.sol rename to packages/protocol/contracts/layer1/fork-router/ForkRouter.sol index d92659346a8..410e38d8b8e 100644 --- a/packages/protocol/contracts/layer1/based/ForkRouter.sol +++ b/packages/protocol/contracts/layer1/fork-router/ForkRouter.sol @@ -4,26 +4,22 @@ pragma solidity ^0.8.24; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; -import "./IFork.sol"; - /// @title ForkRouter /// @custom:security-contact security@taiko.xyz /// @notice This contract routes calls to the current fork. /// /// +--> newFork -/// PROXY -> FORK_MANAGER --| +/// PROXY -> FORK_ROUTER--| /// +--> oldFork contract ForkRouter is UUPSUpgradeable, Ownable2StepUpgradeable { address public immutable oldFork; address public immutable newFork; error InvalidParams(); - error NewForkNotActive(); - error ZeroAddress(); + error ZeroForkAddress(); constructor(address _oldFork, address _newFork) { require(_newFork != address(0) && _newFork != _oldFork, InvalidParams()); - require(_oldFork != address(0) || IFork(_newFork).isForkActive(), NewForkNotActive()); oldFork = _oldFork; newFork = _newFork; @@ -39,17 +35,15 @@ contract ForkRouter is UUPSUpgradeable, Ownable2StepUpgradeable { _fallback(); } - function currentFork() public view returns (address) { - return IFork(newFork).isForkActive() ? newFork : oldFork; - } - - function isForkRouter() public pure returns (bool) { - return true; + /// @notice Returns true if a function should be routed to the old fork + /// @dev This function should be overridden by the implementation contract + function shouldRouteToOldFork(bytes4) public pure virtual returns (bool) { + return false; } function _fallback() internal virtual { - address fork = currentFork(); - require(fork != address(0), ZeroAddress()); + address fork = shouldRouteToOldFork(msg.sig) ? oldFork : newFork; + require(fork != address(0), ZeroForkAddress()); assembly { calldatacopy(0, 0, calldatasize()) diff --git a/packages/protocol/contracts/layer1/fork-router/PacayaForkRouter.sol b/packages/protocol/contracts/layer1/fork-router/PacayaForkRouter.sol new file mode 100644 index 00000000000..47ab7245bec --- /dev/null +++ b/packages/protocol/contracts/layer1/fork-router/PacayaForkRouter.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "./ForkRouter.sol"; + +/// @title IOntakeFork +/// @dev Derived from TaikoL1.sol in the Taiko Ontake fork +/// https://github.com/taikoxyz/taiko-mono/releases/tag/protocol-v1.11.0 +/// @custom:security-contact security@taiko.xyz +interface IOntakeFork { + function proposeBlockV2(bytes calldata, bytes calldata) external; + function proposeBlocksV2(bytes[] calldata, bytes[] calldata) external; + function proveBlock(uint64, bytes calldata) external; + function proveBlocks(uint64[] calldata, bytes[] calldata, bytes calldata) external; + function verifyBlocks(uint64) external; + function getVerifiedBlockProver(uint64) external view; + function getLastVerifiedBlock() external view; + function getBlockV2(uint64) external view; + function getTransition(uint64, uint32) external view; + function getTransition(uint64, bytes32) external; + function getTransitions(uint64[] calldata, bytes32[] calldata) external; + function lastProposedIn() external view; + function getStateVariables() external view; + function getConfig() external pure; + function resolve(uint64, bytes32, bool) external view; + function resolve(bytes32, bool) external view; +} + +/// @title PacayaForkRouter +/// @notice This contract routes calls to the current fork. +/// @custom:security-contact security@taiko.xyz +contract PacayaForkRouter is ForkRouter { + constructor(address _oldFork, address _newFork) ForkRouter(_oldFork, _newFork) { } + + function shouldRouteToOldFork(bytes4 _selector) public pure override returns (bool) { + if ( + _selector == IOntakeFork.proposeBlockV2.selector + || _selector == IOntakeFork.proposeBlocksV2.selector + || _selector == IOntakeFork.proveBlock.selector + || _selector == IOntakeFork.proveBlocks.selector + || _selector == IOntakeFork.verifyBlocks.selector + || _selector == IOntakeFork.getVerifiedBlockProver.selector + || _selector == IOntakeFork.getLastVerifiedBlock.selector + || _selector == IOntakeFork.getBlockV2.selector + || _selector == bytes4(keccak256("getTransition(uint64,uint32)")) + || _selector == bytes4(keccak256("getTransition(uint64,bytes32)")) + || _selector == IOntakeFork.getTransitions.selector + || _selector == IOntakeFork.lastProposedIn.selector + || _selector == IOntakeFork.getStateVariables.selector + || _selector == IOntakeFork.getConfig.selector + || _selector == bytes4(keccak256("resolve(uint64,bytes32,bool)")) + || _selector == bytes4(keccak256("resolve(bytes32,bool)")) + ) return true; + + return false; + } +} diff --git a/packages/protocol/contracts/layer1/hekla/HeklaInbox.sol b/packages/protocol/contracts/layer1/hekla/HeklaInbox.sol index 621b2484a86..075bd78698e 100644 --- a/packages/protocol/contracts/layer1/hekla/HeklaInbox.sol +++ b/packages/protocol/contracts/layer1/hekla/HeklaInbox.sol @@ -9,7 +9,7 @@ import "../based/TaikoInbox.sol"; contract HeklaInbox is TaikoInbox { constructor(address _resolver) TaikoInbox(_resolver) { } - function getConfig() public pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() public pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: LibNetwork.TAIKO_HEKLA, // Never change this value as ring buffer is being reused!!! diff --git a/packages/protocol/contracts/layer1/mainnet/MainnetInbox.sol b/packages/protocol/contracts/layer1/mainnet/MainnetInbox.sol index eb4ce25567a..e3b13a3fbd6 100644 --- a/packages/protocol/contracts/layer1/mainnet/MainnetInbox.sol +++ b/packages/protocol/contracts/layer1/mainnet/MainnetInbox.sol @@ -13,7 +13,7 @@ import "./libs/LibFasterReentryLock.sol"; contract MainnetInbox is TaikoInbox { constructor(address _resolver) TaikoInbox(_resolver) { } - function getConfig() public pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() public pure override returns (ITaikoInbox.Config memory) { // All hard-coded configurations: // - treasury: the actual TaikoL2 address. // - anchorGasLimit: 250_000 (based on internal devnet, its ~220_000 diff --git a/packages/protocol/contracts/layer1/preconf/impl/PreconfRouter.sol b/packages/protocol/contracts/layer1/preconf/impl/PreconfRouter.sol index 3638d7de8fc..4061145c7f7 100644 --- a/packages/protocol/contracts/layer1/preconf/impl/PreconfRouter.sol +++ b/packages/protocol/contracts/layer1/preconf/impl/PreconfRouter.sol @@ -29,15 +29,16 @@ contract PreconfRouter is EssentialContract, IPreconfRouter { returns (ITaikoInbox.BatchMetadata memory meta_) { // Sender must be the selected operator for the epoch - address selectedOperator = - IPreconfWhitelist(resolve(LibStrings.B_PRECONF_WHITELIST, false)).getOperatorForEpoch(); + address selectedOperator = IPreconfWhitelist( + resolveAddress(LibStrings.B_PRECONF_WHITELIST, false) + ).getOperatorForEpoch(); require(msg.sender == selectedOperator, NotTheOperator()); // check if we have a forced inclusion inbox - address forcedInclusionInbox = resolve(LibStrings.B_TAIKO_FORCED_INCLUSION_INBOX, true); + address forcedInclusionInbox = resolveAddress(LibStrings.B_TAIKO_FORCED_INCLUSION_INBOX, true); if (forcedInclusionInbox == address(0)) { // Call the proposeBatch function on the TaikoInbox - address taikoInbox = resolve(LibStrings.B_TAIKO, false); + address taikoInbox = resolveAddress(LibStrings.B_TAIKO, false); (, meta_) = ITaikoInbox(taikoInbox).proposeBatch(_batchParams, _batchTxList); } else { // Call the proposeBatchWithForcedInclusion function on the ForcedInclusionInbox diff --git a/packages/protocol/contracts/layer1/provers/ProverSetBase.sol b/packages/protocol/contracts/layer1/provers/ProverSetBase.sol index adb91fe6567..be1729bab04 100644 --- a/packages/protocol/contracts/layer1/provers/ProverSetBase.sol +++ b/packages/protocol/contracts/layer1/provers/ProverSetBase.sol @@ -122,10 +122,10 @@ abstract contract ProverSetBase is EssentialContract, IERC1271 { } function inbox() internal view virtual returns (address) { - return resolve(LibStrings.B_TAIKO, false); + return resolveAddress(LibStrings.B_TAIKO, false); } function bondToken() internal view virtual returns (address) { - return resolve(LibStrings.B_BOND_TOKEN, true); + return resolveAddress(LibStrings.B_BOND_TOKEN, true); } } diff --git a/packages/protocol/contracts/layer1/team/TokenUnlock.sol b/packages/protocol/contracts/layer1/team/TokenUnlock.sol index e227404e790..d582813ca04 100644 --- a/packages/protocol/contracts/layer1/team/TokenUnlock.sol +++ b/packages/protocol/contracts/layer1/team/TokenUnlock.sol @@ -104,7 +104,7 @@ contract TokenUnlock is EssentialContract { amountVested += _amount; emit TokenVested(_amount); - IERC20(resolve(LibStrings.B_TAIKO_TOKEN, false)).safeTransferFrom( + IERC20(resolveAddress(LibStrings.B_TAIKO_TOKEN, false)).safeTransferFrom( msg.sender, address(this), _amount ); } @@ -112,12 +112,13 @@ contract TokenUnlock is EssentialContract { /// @notice Create a new prover set. function createProverSet() external onlyRecipient returns (address proverSet_) { require( - resolve(LibStrings.B_BOND_TOKEN, false) == resolve(LibStrings.B_TAIKO_TOKEN, false), + resolveAddress(LibStrings.B_BOND_TOKEN, false) + == resolveAddress(LibStrings.B_TAIKO_TOKEN, false), TAIKO_TOKEN_NOT_USED_AS_BOND_TOKEN() ); bytes memory data = abi.encodeCall(ProverSetBase.init, (owner(), address(this))); - proverSet_ = address(new ERC1967Proxy(resolve(LibStrings.B_PROVER_SET, false), data)); + proverSet_ = address(new ERC1967Proxy(resolveAddress(LibStrings.B_PROVER_SET, false), data)); isProverSet[proverSet_] = true; emit ProverSetCreated(proverSet_); @@ -134,7 +135,7 @@ contract TokenUnlock is EssentialContract { if (!isProverSet[_proverSet]) revert NOT_PROVER_SET(); emit DepositToProverSet(_proverSet, _amount); - IERC20(resolve(LibStrings.B_TAIKO_TOKEN, false)).safeTransfer(_proverSet, _amount); + IERC20(resolveAddress(LibStrings.B_TAIKO_TOKEN, false)).safeTransfer(_proverSet, _amount); } /// @notice Withdraws tokens by the recipient. @@ -152,14 +153,14 @@ contract TokenUnlock is EssentialContract { { if (_amount > amountWithdrawable()) revert NOT_WITHDRAWABLE(); emit TokenWithdrawn(_to, _amount); - IERC20(resolve(LibStrings.B_TAIKO_TOKEN, false)).safeTransfer(_to, _amount); + IERC20(resolveAddress(LibStrings.B_TAIKO_TOKEN, false)).safeTransfer(_to, _amount); } /// @notice Withdraws all tokens to the recipient address. function withdraw() external nonReentrant { uint256 amount = amountWithdrawable(); emit TokenWithdrawn(recipient, amount); - IERC20(resolve(LibStrings.B_TAIKO_TOKEN, false)).safeTransfer(recipient, amount); + IERC20(resolveAddress(LibStrings.B_TAIKO_TOKEN, false)).safeTransfer(recipient, amount); } function changeRecipient(address _newRecipient) external onlyRecipientOrOwner { @@ -174,13 +175,13 @@ contract TokenUnlock is EssentialContract { /// @notice Delegates token voting right to a delegatee. /// @param _delegatee The delegatee to receive the voting right. function delegate(address _delegatee) external onlyRecipient nonReentrant { - ERC20VotesUpgradeable(resolve(LibStrings.B_TAIKO_TOKEN, false)).delegate(_delegatee); + ERC20VotesUpgradeable(resolveAddress(LibStrings.B_TAIKO_TOKEN, false)).delegate(_delegatee); } /// @notice Returns the amount of token withdrawable. /// @return The amount of token withdrawable. function amountWithdrawable() public view returns (uint256) { - IERC20 tko = IERC20(resolve(LibStrings.B_TAIKO_TOKEN, false)); + IERC20 tko = IERC20(resolveAddress(LibStrings.B_TAIKO_TOKEN, false)); uint256 balance = tko.balanceOf(address(this)); uint256 locked = _getAmountLocked(); diff --git a/packages/protocol/contracts/layer1/verifiers/Risc0Verifier.sol b/packages/protocol/contracts/layer1/verifiers/Risc0Verifier.sol index 84feb438241..bef2b68b961 100644 --- a/packages/protocol/contracts/layer1/verifiers/Risc0Verifier.sol +++ b/packages/protocol/contracts/layer1/verifiers/Risc0Verifier.sol @@ -81,7 +81,7 @@ contract Risc0Verifier is EssentialContract, IVerifier { bytes32 journalDigest = sha256(abi.encodePacked(publicInputs)); // call risc0 verifier contract - (bool success,) = resolve(RISCZERO_GROTH16_VERIFIER, false).staticcall( + (bool success,) = resolveAddress(RISCZERO_GROTH16_VERIFIER, false).staticcall( abi.encodeCall(IRiscZeroVerifier.verify, (seal, aggregationImageId, journalDigest)) ); require(success, RISC_ZERO_INVALID_PROOF()); diff --git a/packages/protocol/contracts/layer1/verifiers/SP1Verifier.sol b/packages/protocol/contracts/layer1/verifiers/SP1Verifier.sol index 6dab04b53a4..0b358bc4237 100644 --- a/packages/protocol/contracts/layer1/verifiers/SP1Verifier.sol +++ b/packages/protocol/contracts/layer1/verifiers/SP1Verifier.sol @@ -84,6 +84,6 @@ contract SP1Verifier is EssentialContract, IVerifier { } function sp1RemoteVerifier() public view virtual returns (address) { - return resolve(SP1_REMOTE_VERIFIER, false); + return resolveAddress(SP1_REMOTE_VERIFIER, false); } } diff --git a/packages/protocol/contracts/layer1/verifiers/SgxVerifier.sol b/packages/protocol/contracts/layer1/verifiers/SgxVerifier.sol index d976a92cadc..0aa0d17deee 100644 --- a/packages/protocol/contracts/layer1/verifiers/SgxVerifier.sol +++ b/packages/protocol/contracts/layer1/verifiers/SgxVerifier.sol @@ -125,7 +125,8 @@ contract SgxVerifier is EssentialContract, IVerifier { external returns (uint256) { - address automataDcapAttestation = resolve(LibStrings.B_AUTOMATA_DCAP_ATTESTATION, true); + address automataDcapAttestation = + resolveAddress(LibStrings.B_AUTOMATA_DCAP_ATTESTATION, true); require(automataDcapAttestation != address(0), SGX_RA_NOT_SUPPORTED()); diff --git a/packages/protocol/contracts/layer1/verifiers/SgxVerifierBase.sol b/packages/protocol/contracts/layer1/verifiers/SgxVerifierBase.sol index 109bbb52e88..1dff297b63f 100644 --- a/packages/protocol/contracts/layer1/verifiers/SgxVerifierBase.sol +++ b/packages/protocol/contracts/layer1/verifiers/SgxVerifierBase.sol @@ -80,7 +80,8 @@ abstract contract SgxVerifierBase is EssentialContract { external returns (uint256) { - address automataDcapAttestation = resolve(LibStrings.B_AUTOMATA_DCAP_ATTESTATION, true); + address automataDcapAttestation = + resolveAddress(LibStrings.B_AUTOMATA_DCAP_ATTESTATION, true); require(automataDcapAttestation != address(0), SGX_RA_NOT_SUPPORTED()); diff --git a/packages/protocol/contracts/layer2/DelegateOwner.sol b/packages/protocol/contracts/layer2/DelegateOwner.sol index af831161cf7..5c23e9775eb 100644 --- a/packages/protocol/contracts/layer2/DelegateOwner.sol +++ b/packages/protocol/contracts/layer2/DelegateOwner.sol @@ -144,7 +144,7 @@ contract DelegateOwner is EssentialContract, IMessageInvocable { function _isAdminOrRemoteOwner(address _sender) private view returns (bool) { if (_sender == admin) return true; - if (_sender != resolve(LibStrings.B_BRIDGE, false)) return false; + if (_sender != resolveAddress(LibStrings.B_BRIDGE, false)) return false; IBridge.Context memory ctx = IBridge(_sender).context(); return ctx.srcChainId == remoteChainId && ctx.from == remoteOwner; diff --git a/packages/protocol/contracts/layer2/based/TaikoAnchor.sol b/packages/protocol/contracts/layer2/based/TaikoAnchor.sol index 4433632a870..f62ad80cc7d 100644 --- a/packages/protocol/contracts/layer2/based/TaikoAnchor.sol +++ b/packages/protocol/contracts/layer2/based/TaikoAnchor.sol @@ -169,7 +169,9 @@ contract TaikoAnchor is EssentialContract, IBlockHashProvider, TaikoAnchorDeprec _syncChainData(_anchorBlockId, _anchorStateRoot); _updateParentHashAndTimestamp(parentId); - ISignalService(resolve(LibStrings.B_SIGNAL_SERVICE, false)).receiveSignals(_signalSlots); + ISignalService(resolveAddress(LibStrings.B_SIGNAL_SERVICE, false)).receiveSignals( + _signalSlots + ); } /// @notice Anchors the latest L1 block details to L2 for cross-layer @@ -294,7 +296,7 @@ contract TaikoAnchor is EssentialContract, IBlockHashProvider, TaikoAnchorDeprec /// @dev Store the L1's state root as a signal to the local signal service to /// allow for multi-hop bridging. - ISignalService(resolve(LibStrings.B_SIGNAL_SERVICE, false)).syncChainData( + ISignalService(resolveAddress(LibStrings.B_SIGNAL_SERVICE, false)).syncChainData( l1ChainId, LibStrings.H_STATE_ROOT, _anchorBlockId, _anchorStateRoot ); diff --git a/packages/protocol/contracts/shared/bridge/Bridge.sol b/packages/protocol/contracts/shared/bridge/Bridge.sol index 3ef11114b9c..f284c9b7b42 100644 --- a/packages/protocol/contracts/shared/bridge/Bridge.sol +++ b/packages/protocol/contracts/shared/bridge/Bridge.sol @@ -161,7 +161,7 @@ contract Bridge is EssentialContract, IBridge { msgHash_ = hashMessage(message_); emit MessageSent(msgHash_, message_); - ISignalService(resolve(LibStrings.B_SIGNAL_SERVICE, false)).sendSignal(msgHash_); + ISignalService(resolveAddress(LibStrings.B_SIGNAL_SERVICE, false)).sendSignal(msgHash_); } /// @inheritdoc IBridge @@ -178,7 +178,7 @@ contract Bridge is EssentialContract, IBridge { bytes32 msgHash = hashMessage(_message); _checkStatus(msgHash, Status.NEW); - address signalService = resolve(LibStrings.B_SIGNAL_SERVICE, false); + address signalService = resolveAddress(LibStrings.B_SIGNAL_SERVICE, false); if (!ISignalService(signalService).isSignalSent(address(this), msgHash)) { revert B_MESSAGE_NOT_SENT(); @@ -246,7 +246,7 @@ contract Bridge is EssentialContract, IBridge { bytes32 msgHash = hashMessage(_message); _checkStatus(msgHash, Status.NEW); - address signalService = resolve(LibStrings.B_SIGNAL_SERVICE, false); + address signalService = resolveAddress(LibStrings.B_SIGNAL_SERVICE, false); stats.proofSize = uint32(_proof.length); stats.numCacheOps = @@ -329,7 +329,9 @@ contract Bridge is EssentialContract, IBridge { if (!_consumeEtherQuota(_message.value)) revert B_OUT_OF_ETH_QUOTA(); bool succeeded; - if (_unableToInvokeMessageCall(_message, resolve(LibStrings.B_SIGNAL_SERVICE, false))) { + if ( + _unableToInvokeMessageCall(_message, resolveAddress(LibStrings.B_SIGNAL_SERVICE, false)) + ) { succeeded = _message.destOwner.sendEther(_message.value, _SEND_ETHER_GAS_LIMIT, ""); } else { if ((_message.gasLimit == 0 || _isLastAttempt) && msg.sender != _message.destOwner) { @@ -345,7 +347,7 @@ contract Bridge is EssentialContract, IBridge { } else if (_isLastAttempt) { _updateMessageStatus(msgHash, Status.FAILED); - ISignalService(resolve(LibStrings.B_SIGNAL_SERVICE, false)).sendSignal( + ISignalService(resolveAddress(LibStrings.B_SIGNAL_SERVICE, false)).sendSignal( signalForFailedMessage(msgHash) ); } else { @@ -367,7 +369,7 @@ contract Bridge is EssentialContract, IBridge { _checkStatus(msgHash, Status.RETRIABLE); _updateMessageStatus(msgHash, Status.FAILED); - ISignalService(resolve(LibStrings.B_SIGNAL_SERVICE, false)).sendSignal( + ISignalService(resolveAddress(LibStrings.B_SIGNAL_SERVICE, false)).sendSignal( signalForFailedMessage(msgHash) ); } @@ -375,7 +377,7 @@ contract Bridge is EssentialContract, IBridge { /// @inheritdoc IBridge function isMessageSent(Message calldata _message) external view returns (bool) { if (_message.srcChainId != block.chainid) return false; - return ISignalService(resolve(LibStrings.B_SIGNAL_SERVICE, false)).isSignalSent({ + return ISignalService(resolveAddress(LibStrings.B_SIGNAL_SERVICE, false)).isSignalSent({ _app: address(this), _signal: hashMessage(_message) }); @@ -397,7 +399,7 @@ contract Bridge is EssentialContract, IBridge { if (_message.srcChainId != block.chainid) return false; return _isSignalReceived( - resolve(LibStrings.B_SIGNAL_SERVICE, false), + resolveAddress(LibStrings.B_SIGNAL_SERVICE, false), signalForFailedMessage(hashMessage(_message)), _message.destChainId, _proof @@ -419,7 +421,7 @@ contract Bridge is EssentialContract, IBridge { { if (_message.destChainId != block.chainid) return false; return _isSignalReceived( - resolve(LibStrings.B_SIGNAL_SERVICE, false), + resolveAddress(LibStrings.B_SIGNAL_SERVICE, false), hashMessage(_message), _message.srcChainId, _proof @@ -435,7 +437,7 @@ contract Bridge is EssentialContract, IBridge { view returns (bool enabled_, address destBridge_) { - destBridge_ = resolve(_chainId, LibStrings.B_BRIDGE, true); + destBridge_ = resolveAddress(_chainId, LibStrings.B_BRIDGE, true); enabled_ = destBridge_ != address(0); } @@ -472,10 +474,10 @@ contract Bridge is EssentialContract, IBridge { /// only allow watchdog to pause the bridge, but does not allow it to unpause the bridge. function _authorizePause(address addr, bool toPause) internal view override { // Owner and chain watchdog can pause/unpause the bridge. - if (addr == owner() || addr == resolve(LibStrings.B_CHAIN_WATCHDOG, true)) return; + if (addr == owner() || addr == resolveAddress(LibStrings.B_CHAIN_WATCHDOG, true)) return; // bridge_watchdog can pause the bridge, but cannot unpause it. - if (toPause && addr == resolve(LibStrings.B_BRIDGE_WATCHDOG, true)) return; + if (toPause && addr == resolveAddress(LibStrings.B_BRIDGE_WATCHDOG, true)) return; revert ACCESS_DENIED(); } @@ -556,7 +558,7 @@ contract Bridge is EssentialContract, IBridge { returns (uint32 numCacheOps_) { try ISignalService(_signalService).proveSignalReceived( - _chainId, resolve(_chainId, LibStrings.B_BRIDGE, false), _signal, _proof + _chainId, resolveAddress(_chainId, LibStrings.B_BRIDGE, false), _signal, _proof ) returns (uint256 numCacheOps) { numCacheOps_ = uint32(numCacheOps); } catch { @@ -569,7 +571,7 @@ contract Bridge is EssentialContract, IBridge { /// @return true if quota manager has unlimited quota for Ether or the given amount of Ether is /// consumed already. function _consumeEtherQuota(uint256 _amount) private returns (bool) { - address quotaManager = resolve(LibStrings.B_QUOTA_MANAGER, true); + address quotaManager = resolveAddress(LibStrings.B_QUOTA_MANAGER, true); if (quotaManager == address(0)) return true; try IQuotaManager(quotaManager).consumeQuota(address(0), _amount) { @@ -603,7 +605,7 @@ contract Bridge is EssentialContract, IBridge { returns (bool) { try ISignalService(_signalService).verifySignalReceived( - _chainId, resolve(_chainId, LibStrings.B_BRIDGE, false), _signal, _proof + _chainId, resolveAddress(_chainId, LibStrings.B_BRIDGE, false), _signal, _proof ) { return true; } catch { diff --git a/packages/protocol/contracts/shared/common/EssentialContract.sol b/packages/protocol/contracts/shared/common/EssentialContract.sol index 0814076cea2..52354d1aed8 100644 --- a/packages/protocol/contracts/shared/common/EssentialContract.sol +++ b/packages/protocol/contracts/shared/common/EssentialContract.sol @@ -39,7 +39,7 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable /// @dev Modifier that ensures the caller is the owner or resolved address of a given name. /// @param _name The name to check against. modifier onlyFromOwnerOrNamed(bytes32 _name) { - require(msg.sender == owner() || msg.sender == resolve(_name, true), ACCESS_DENIED()); + require(msg.sender == owner() || msg.sender == resolveAddress(_name, true), ACCESS_DENIED()); _; } @@ -84,7 +84,7 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable /// name. /// @param _name The name to check against. modifier onlyFromNamed(bytes32 _name) { - require(msg.sender == resolve(_name, true), ACCESS_DENIED()); + require(msg.sender == resolveAddress(_name, true), ACCESS_DENIED()); _; } @@ -92,7 +92,7 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable /// name, if the name is set. /// @param _name The name to check against. modifier onlyFromOptionalNamed(bytes32 _name) { - address addr = resolve(_name, true); + address addr = resolveAddress(_name, true); require(addr == address(0) || msg.sender == addr, ACCESS_DENIED()); _; } @@ -103,7 +103,7 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable /// @param _name2 The second name to check against. modifier onlyFromNamedEither(bytes32 _name1, bytes32 _name2) { require( - msg.sender == resolve(_name1, true) || msg.sender == resolve(_name2, true), + msg.sender == resolveAddress(_name1, true) || msg.sender == resolveAddress(_name2, true), ACCESS_DENIED() ); _; @@ -151,7 +151,7 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable /// @param _name The name to resolve /// @param _allowZeroAddress Whether to allow resolving to the zero address /// @return The resolved address - function resolve( + function resolveAddress( uint64 _chainId, bytes32 _name, bool _allowZeroAddress @@ -167,7 +167,7 @@ abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable /// @param _name The name to resolve /// @param _allowZeroAddress Whether to allow resolving to the zero address /// @return The resolved address - function resolve(bytes32 _name, bool _allowZeroAddress) public view returns (address) { + function resolveAddress(bytes32 _name, bool _allowZeroAddress) public view returns (address) { return IResolver(resolver()).resolve(block.chainid, _name, _allowZeroAddress); } diff --git a/packages/protocol/contracts/shared/signal/SignalService.sol b/packages/protocol/contracts/shared/signal/SignalService.sol index 767a0df595d..ba879604118 100644 --- a/packages/protocol/contracts/shared/signal/SignalService.sol +++ b/packages/protocol/contracts/shared/signal/SignalService.sol @@ -341,7 +341,7 @@ contract SignalService is EssentialContract, ISignalService { address app = _app; bytes32 signal = _signal; bytes32 value = _signal; - address signalService = resolve(chainId, LibStrings.B_SIGNAL_SERVICE, false); + address signalService = resolveAddress(chainId, LibStrings.B_SIGNAL_SERVICE, false); if (signalService == address(this)) revert SS_INVALID_MID_HOP_CHAINID(); HopProof memory hop; @@ -367,7 +367,7 @@ contract SignalService is EssentialContract, ISignalService { if (hop.chainId == 0 || hop.chainId == block.chainid) { revert SS_INVALID_MID_HOP_CHAINID(); } - signalService = resolve(hop.chainId, LibStrings.B_SIGNAL_SERVICE, false); + signalService = resolveAddress(hop.chainId, LibStrings.B_SIGNAL_SERVICE, false); if (signalService == address(this)) revert SS_INVALID_MID_HOP_CHAINID(); } diff --git a/packages/protocol/contracts/shared/tokenvault/BaseVault.sol b/packages/protocol/contracts/shared/tokenvault/BaseVault.sol index bc8201cec8d..6145e8eeb82 100644 --- a/packages/protocol/contracts/shared/tokenvault/BaseVault.sol +++ b/packages/protocol/contracts/shared/tokenvault/BaseVault.sol @@ -57,7 +57,7 @@ abstract contract BaseVault is returns (IBridge.Context memory ctx_) { ctx_ = IBridge(msg.sender).context(); - address selfOnSourceChain = resolve(ctx_.srcChainId, name(), false); + address selfOnSourceChain = resolveAddress(ctx_.srcChainId, name(), false); if (ctx_.from != selfOnSourceChain) revert VAULT_PERMISSION_DENIED(); } diff --git a/packages/protocol/contracts/shared/tokenvault/ERC1155Vault.sol b/packages/protocol/contracts/shared/tokenvault/ERC1155Vault.sol index 3a3f49208b1..9d79b2c84e1 100644 --- a/packages/protocol/contracts/shared/tokenvault/ERC1155Vault.sol +++ b/packages/protocol/contracts/shared/tokenvault/ERC1155Vault.sol @@ -60,7 +60,7 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable { destChainId: _op.destChainId, srcOwner: msg.sender, destOwner: _op.destOwner != address(0) ? _op.destOwner : msg.sender, - to: resolve(_op.destChainId, name(), false), + to: resolveAddress(_op.destChainId, name(), false), value: msg.value - _op.fee, fee: _op.fee, gasLimit: _op.gasLimit, @@ -69,8 +69,9 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable { // Send the message and obtain the message hash bytes32 msgHash; - (msgHash, message_) = - IBridge(resolve(LibStrings.B_BRIDGE, false)).sendMessage{ value: msg.value }(message); + (msgHash, message_) = IBridge(resolveAddress(LibStrings.B_BRIDGE, false)).sendMessage{ + value: msg.value + }(message); // Emit TokenSent event emit TokenSent({ @@ -291,7 +292,8 @@ contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable { (owner(), _ctoken.addr, _ctoken.chainId, _ctoken.symbol, _ctoken.name) ); - btoken_ = address(new ERC1967Proxy(resolve(LibStrings.B_BRIDGED_ERC1155, false), data)); + btoken_ = + address(new ERC1967Proxy(resolveAddress(LibStrings.B_BRIDGED_ERC1155, false), data)); bridgedToCanonical[btoken_] = _ctoken; canonicalToBridged[_ctoken.chainId][_ctoken.addr] = btoken_; diff --git a/packages/protocol/contracts/shared/tokenvault/ERC20Vault.sol b/packages/protocol/contracts/shared/tokenvault/ERC20Vault.sol index fec4e67afaa..7f5abf876d4 100644 --- a/packages/protocol/contracts/shared/tokenvault/ERC20Vault.sol +++ b/packages/protocol/contracts/shared/tokenvault/ERC20Vault.sol @@ -289,7 +289,7 @@ contract ERC20Vault is BaseVault { if (btokenDenylist[_op.token]) revert VAULT_BTOKEN_BLACKLISTED(); if (msg.value < _op.fee) revert VAULT_INSUFFICIENT_FEE(); - address bridge = resolve(LibStrings.B_BRIDGE, false); + address bridge = resolveAddress(LibStrings.B_BRIDGE, false); ( bytes memory data, @@ -305,7 +305,7 @@ contract ERC20Vault is BaseVault { destChainId: _op.destChainId, srcOwner: msg.sender, destOwner: _op.destOwner != address(0) ? _op.destOwner : msg.sender, - to: resolve(_op.destChainId, name(), false), + to: resolveAddress(_op.destChainId, name(), false), value: msg.value - _op.fee, fee: _op.fee, gasLimit: _op.gasLimit, @@ -408,7 +408,7 @@ contract ERC20Vault is BaseVault { function solve(SolverOp memory _op) external nonReentrant whenNotPaused { if (_op.l2BatchMetaHash != 0) { // Verify that the required L2 batch containing the intent transaction has been proposed - address taiko = resolve(LibStrings.B_TAIKO, false); + address taiko = resolveAddress(LibStrings.B_TAIKO, false); require(ITaiko(taiko).isOnL1(), VAULT_NOT_ON_L1()); bytes32 l2BatchMetaHash = ITaikoInbox(taiko).getBatch(_op.l2BatchId).metaHash; @@ -589,7 +589,7 @@ contract ERC20Vault is BaseVault { (owner(), ctoken.addr, ctoken.chainId, ctoken.decimals, ctoken.symbol, ctoken.name) ); - btoken = address(new ERC1967Proxy(resolve(LibStrings.B_BRIDGED_ERC20, false), data)); + btoken = address(new ERC1967Proxy(resolveAddress(LibStrings.B_BRIDGED_ERC20, false), data)); bridgedToCanonical[btoken] = ctoken; canonicalToBridged[ctoken.chainId][ctoken.addr] = btoken; @@ -604,7 +604,7 @@ contract ERC20Vault is BaseVault { } function _consumeTokenQuota(address _token, uint256 _amount) private { - address quotaManager = resolve(LibStrings.B_QUOTA_MANAGER, true); + address quotaManager = resolveAddress(LibStrings.B_QUOTA_MANAGER, true); if (quotaManager != address(0)) { IQuotaManager(quotaManager).consumeQuota(_token, _amount); } diff --git a/packages/protocol/contracts/shared/tokenvault/ERC721Vault.sol b/packages/protocol/contracts/shared/tokenvault/ERC721Vault.sol index 4d466624f3e..357e8a98262 100644 --- a/packages/protocol/contracts/shared/tokenvault/ERC721Vault.sol +++ b/packages/protocol/contracts/shared/tokenvault/ERC721Vault.sol @@ -58,7 +58,7 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver { destChainId: _op.destChainId, srcOwner: msg.sender, destOwner: _op.destOwner != address(0) ? _op.destOwner : msg.sender, - to: resolve(_op.destChainId, name(), false), + to: resolveAddress(_op.destChainId, name(), false), value: msg.value - _op.fee, fee: _op.fee, gasLimit: _op.gasLimit, @@ -66,8 +66,9 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver { }); bytes32 msgHash; - (msgHash, message_) = - IBridge(resolve(LibStrings.B_BRIDGE, false)).sendMessage{ value: msg.value }(message); + (msgHash, message_) = IBridge(resolveAddress(LibStrings.B_BRIDGE, false)).sendMessage{ + value: msg.value + }(message); emit TokenSent({ msgHash: msgHash, @@ -247,7 +248,8 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver { (owner(), _ctoken.addr, _ctoken.chainId, _ctoken.symbol, _ctoken.name) ); - btoken_ = address(new ERC1967Proxy(resolve(LibStrings.B_BRIDGED_ERC721, false), data)); + btoken_ = + address(new ERC1967Proxy(resolveAddress(LibStrings.B_BRIDGED_ERC721, false), data)); bridgedToCanonical[btoken_] = _ctoken; canonicalToBridged[_ctoken.chainId][_ctoken.addr] = btoken_; diff --git a/packages/protocol/script/layer1/based/DeployProtocolOnL1.s.sol b/packages/protocol/script/layer1/based/DeployProtocolOnL1.s.sol index be13ee22f2b..8689312c795 100644 --- a/packages/protocol/script/layer1/based/DeployProtocolOnL1.s.sol +++ b/packages/protocol/script/layer1/based/DeployProtocolOnL1.s.sol @@ -19,7 +19,7 @@ import "src/layer1/devnet/verifiers/OpVerifier.sol"; import "src/layer1/devnet/verifiers/DevnetVerifier.sol"; import "src/layer1/mainnet/MainnetInbox.sol"; import "src/layer1/based/TaikoInbox.sol"; -import "src/layer1/based/ForkRouter.sol"; +import "src/layer1/fork-router/ForkRouter.sol"; import "src/layer1/based/ForcedInclusionInbox.sol"; import "src/layer1/based/ForcedInclusionStore.sol"; import "src/layer1/mainnet/multirollup/MainnetBridge.sol"; @@ -69,12 +69,12 @@ contract DeployProtocolOnL1 is DeployCapability { // --------------------------------------------------------------- // Signal service need to authorize the new rollup - address signalServiceAddr = EssentialContract(sharedResolver).resolve( + address signalServiceAddr = EssentialContract(sharedResolver).resolveAddress( uint64(block.chainid), LibStrings.B_SIGNAL_SERVICE, false ); SignalService signalService = SignalService(signalServiceAddr); - address taikoInboxAddr = EssentialContract(rollupResolver).resolve( + address taikoInboxAddr = EssentialContract(rollupResolver).resolveAddress( uint64(block.chainid), LibStrings.B_TAIKO, false ); TaikoInbox taikoInbox = TaikoInbox(payable(taikoInboxAddr)); @@ -83,7 +83,7 @@ contract DeployProtocolOnL1 is DeployCapability { SignalService(signalServiceAddr).authorize(taikoInboxAddr, true); } - uint64 l2ChainId = taikoInbox.getConfig().chainId; + uint64 l2ChainId = taikoInbox.pacayaConfig().chainId; require(l2ChainId != block.chainid, "same chainid"); console2.log("------------------------------------------"); @@ -278,7 +278,7 @@ contract DeployProtocolOnL1 is DeployCapability { TaikoInbox taikoInbox = TaikoInbox(payable(taikoInboxAddr)); taikoInbox.init(owner, vm.envBytes32("L2_GENESIS_HASH")); - uint64 l2ChainId = taikoInbox.getConfig().chainId; + uint64 l2ChainId = taikoInbox.pacayaConfig().chainId; require(l2ChainId != block.chainid, "same chainid"); address opVerifier = deployProxy({ diff --git a/packages/protocol/test/layer1/Layer1Test.sol b/packages/protocol/test/layer1/Layer1Test.sol index 1c0ab79b6aa..dc8fca834da 100644 --- a/packages/protocol/test/layer1/Layer1Test.sol +++ b/packages/protocol/test/layer1/Layer1Test.sol @@ -30,7 +30,7 @@ contract ConfigurableInbox is TaikoInbox { __config = _config; } - function getConfig() public view override returns (ITaikoInbox.Config memory) { + function pacayaConfig() public view override returns (ITaikoInbox.Config memory) { return __config; } diff --git a/packages/protocol/test/layer1/based/ForcedInclusionInbox.t.sol b/packages/protocol/test/layer1/based/ForcedInclusionInbox.t.sol index e360b2f6c83..9ec925828bd 100644 --- a/packages/protocol/test/layer1/based/ForcedInclusionInbox.t.sol +++ b/packages/protocol/test/layer1/based/ForcedInclusionInbox.t.sol @@ -5,7 +5,7 @@ import "contracts/layer1/based/IForcedInclusionInbox.sol"; import "./ForcedInclusionInboxTestBase.sol"; contract ForcedInclusionInboxTest is ForcedInclusionInboxTestBase { - function getConfig() internal pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() internal pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: LibNetwork.TAIKO_MAINNET, maxUnverifiedBatches: 10, diff --git a/packages/protocol/test/layer1/based/ForcedInclusionInboxTestBase.sol b/packages/protocol/test/layer1/based/ForcedInclusionInboxTestBase.sol index 5ec8a9eafe0..de8410f400a 100644 --- a/packages/protocol/test/layer1/based/ForcedInclusionInboxTestBase.sol +++ b/packages/protocol/test/layer1/based/ForcedInclusionInboxTestBase.sol @@ -18,7 +18,7 @@ abstract contract ForcedInclusionInboxTestBase is InboxTestBase { genesisBlockProposedAt = block.timestamp; genesisBlockProposedIn = block.number; - inbox = deployInbox(correctBlockhash(0), getConfig()); + inbox = deployInbox(correctBlockhash(0), pacayaConfig()); forcedInclusionStore = deployForcedInclusionStore(100, 100, owner); forcedInclusionInbox = deployForcedInclusionInbox(); diff --git a/packages/protocol/test/layer1/based/ForkRouter.t.sol b/packages/protocol/test/layer1/based/ForkRouter.t.sol deleted file mode 100644 index acfa98a6343..00000000000 --- a/packages/protocol/test/layer1/based/ForkRouter.t.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "../Layer1Test.sol"; -import "src/layer1/based/ForkRouter.sol"; - -contract Fork is EssentialContract, IFork { - bytes32 private immutable __name; - bool private immutable __isActive; - - constructor(bytes32 _name, bool _isActive) EssentialContract(address(0)) { - __name = _name; - __isActive = _isActive; - } - - function init() external initializer { - __Essential_init(address(0)); - } - - function name() public view returns (bytes32) { - return __name; - } - - function isForkActive() external view override returns (bool) { - return __isActive; - } -} - -contract TestForkRouter is Layer1Test { - function test_ForkManager_default_routing() public transactBy(deployer) { - address fork1 = address(new Fork("fork1", true)); - - address router = deploy({ - name: "fork_router", - impl: address(new ForkRouter(address(0), fork1)), - data: abi.encodeCall(Fork.init, ()) - }); - - assertTrue(ForkRouter(payable(router)).isForkRouter()); - assertEq(Fork(router).name(), "fork1"); - - // If we upgrade the proxy's impl to a fork, then alling isForkRouter will throw, - // so we should never do this in production. - - Fork(router).upgradeTo(fork1); - vm.expectRevert(); - ForkRouter(payable(router)).isForkRouter(); - - address fork2 = address(new Fork("fork2", true)); - Fork(router).upgradeTo(address(new ForkRouter(fork1, fork2))); - assertEq(Fork(router).name(), "fork2"); - } - - function test_ForkManager_routing_to_old_fork() public transactBy(deployer) { - address fork1 = address(new Fork("fork1", false)); - address fork2 = address(new Fork("fork2", false)); - - address router = deploy({ - name: "fork_router", - impl: address(new ForkRouter(fork1, fork2)), - data: abi.encodeCall(Fork.init, ()) - }); - - assertTrue(ForkRouter(payable(router)).isForkRouter()); - assertEq(Fork(router).name(), "fork1"); - - fork2 = address(new Fork("fork2", true)); - Fork(router).upgradeTo(address(new ForkRouter(fork1, fork2))); - assertTrue(ForkRouter(payable(router)).isForkRouter()); - assertEq(Fork(router).name(), "fork2"); - } -} diff --git a/packages/protocol/test/layer1/based/InboxTestBase.sol b/packages/protocol/test/layer1/based/InboxTestBase.sol index 406a983df9f..9736265c8f7 100644 --- a/packages/protocol/test/layer1/based/InboxTestBase.sol +++ b/packages/protocol/test/layer1/based/InboxTestBase.sol @@ -15,7 +15,7 @@ abstract contract InboxTestBase is Layer1Test { uint256 genesisBlockProposedIn; uint256 private __blocksPerBatch; - function getConfig() internal view virtual returns (ITaikoInbox.Config memory); + function pacayaConfig() internal view virtual returns (ITaikoInbox.Config memory); modifier transactBy(address transactor) override { vm.deal(transactor, 100 ether); @@ -37,7 +37,7 @@ abstract contract InboxTestBase is Layer1Test { __blocksPerBatch = 1; - inbox = deployInbox(correctBlockhash(0), getConfig()); + inbox = deployInbox(correctBlockhash(0), pacayaConfig()); signalService = deploySignalService(address(new SignalService(address(resolver)))); signalService.authorize(address(inbox), true); @@ -180,8 +180,8 @@ abstract contract InboxTestBase is Layer1Test { // console2.log("stats2.numBatches:", stats2.numBatches); // console2.log("getConfig().maxUnverifiedBatches:", getConfig().maxUnverifiedBatches); - uint64 firstBatchId = stats2.numBatches > getConfig().maxUnverifiedBatches - ? stats2.numBatches - getConfig().maxUnverifiedBatches + uint64 firstBatchId = stats2.numBatches > pacayaConfig().maxUnverifiedBatches + ? stats2.numBatches - pacayaConfig().maxUnverifiedBatches : 0; for (uint64 i = firstBatchId; i < stats2.numBatches; ++i) { @@ -200,7 +200,7 @@ abstract contract InboxTestBase is Layer1Test { console2.log(unicode"│ |── verifiedTransitionId:", batch.verifiedTransitionId); for (uint24 j = 1; j < batch.nextTransitionId; ++j) { - ITaikoInbox.TransitionState memory ts = inbox.getTransition(batch.batchId, j); + ITaikoInbox.TransitionState memory ts = inbox.getTransitionById(batch.batchId, j); console2.log(unicode"│ |── transition#", j); console2.log( unicode"│ │ |── parentHash:", diff --git a/packages/protocol/test/layer1/based/InboxTest_BondMechanics.t.sol b/packages/protocol/test/layer1/based/InboxTest_BondMechanics.t.sol index 2326894da3a..369bf82dfd2 100644 --- a/packages/protocol/test/layer1/based/InboxTest_BondMechanics.t.sol +++ b/packages/protocol/test/layer1/based/InboxTest_BondMechanics.t.sol @@ -5,7 +5,7 @@ import "contracts/layer1/based/ITaikoInbox.sol"; import "./InboxTestBase.sol"; contract InboxTest_BondMechanics is InboxTestBase { - function getConfig() internal pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() internal pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: LibNetwork.TAIKO_MAINNET, maxUnverifiedBatches: 10, @@ -43,7 +43,7 @@ contract InboxTest_BondMechanics is InboxTestBase { setupBondTokenState(Alice, initialBondBalance, bondBalance); - ITaikoInbox.Config memory config = getConfig(); + ITaikoInbox.Config memory config = pacayaConfig(); vm.prank(Alice); uint64[] memory batchIds = _proposeBatchesWithDefaultParameters(1); @@ -66,7 +66,7 @@ contract InboxTest_BondMechanics is InboxTestBase { setupBondTokenState(Alice, initialBondBalance, bondBalance); - ITaikoInbox.Config memory config = getConfig(); + ITaikoInbox.Config memory config = pacayaConfig(); vm.prank(Alice); uint64[] memory batchIds = _proposeBatchesWithDefaultParameters(1); @@ -88,14 +88,14 @@ contract InboxTest_BondMechanics is InboxTestBase { setupBondTokenState(Alice, initialBondBalance, bondBalance); - ITaikoInbox.Config memory config = getConfig(); + ITaikoInbox.Config memory config = pacayaConfig(); vm.prank(Alice); uint64[] memory batchIds = _proposeBatchesWithDefaultParameters(1); uint96 livenessBond = config.livenessBondBase + config.livenessBondPerBlock; assertEq(inbox.bondBalanceOf(Alice), bondBalance - livenessBond); - vm.warp(block.timestamp + getConfig().provingWindow + 1); + vm.warp(block.timestamp + pacayaConfig().provingWindow + 1); vm.prank(Alice); _proveBatchesWithCorrectTransitions(batchIds); @@ -110,14 +110,14 @@ contract InboxTest_BondMechanics is InboxTestBase { setupBondTokenState(Alice, initialBondBalance, bondBalance); - ITaikoInbox.Config memory config = getConfig(); + ITaikoInbox.Config memory config = pacayaConfig(); uint96 livenessBond = config.livenessBondBase + config.livenessBondPerBlock; vm.prank(Alice); uint64[] memory batchIds = _proposeBatchesWithDefaultParameters(1); assertEq(inbox.bondBalanceOf(Alice), bondBalance - livenessBond); - vm.warp(block.timestamp + getConfig().provingWindow + 1); + vm.warp(block.timestamp + pacayaConfig().provingWindow + 1); vm.prank(Bob); _proveBatchesWithCorrectTransitions(batchIds); @@ -133,7 +133,7 @@ contract InboxTest_BondMechanics is InboxTestBase { ITaikoInbox.Batch memory batch = inbox.getBatch(meta.batchId); - ITaikoInbox.Config memory config = getConfig(); + ITaikoInbox.Config memory config = pacayaConfig(); uint96 livenessBond = config.livenessBondBase + config.livenessBondPerBlock * 2; assertEq(batch.livenessBond, livenessBond); } diff --git a/packages/protocol/test/layer1/based/InboxTest_BondToken.t.sol b/packages/protocol/test/layer1/based/InboxTest_BondToken.t.sol index 23d22ac7208..0172141da1c 100644 --- a/packages/protocol/test/layer1/based/InboxTest_BondToken.t.sol +++ b/packages/protocol/test/layer1/based/InboxTest_BondToken.t.sol @@ -5,7 +5,7 @@ import "contracts/layer1/based/ITaikoInbox.sol"; import "./InboxTestBase.sol"; contract InboxTest_BondToken is InboxTestBase { - function getConfig() internal pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() internal pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: LibNetwork.TAIKO_MAINNET, maxUnverifiedBatches: 10, diff --git a/packages/protocol/test/layer1/based/InboxTest_CalldataForTxList.t.sol b/packages/protocol/test/layer1/based/InboxTest_CalldataForTxList.t.sol index 65a7e0466e0..5ef51f60c2f 100644 --- a/packages/protocol/test/layer1/based/InboxTest_CalldataForTxList.t.sol +++ b/packages/protocol/test/layer1/based/InboxTest_CalldataForTxList.t.sol @@ -5,7 +5,7 @@ import "contracts/layer1/based/ITaikoInbox.sol"; import "./InboxTestBase.sol"; contract InboxTest_CalldataForTxList is InboxTestBase { - function getConfig() internal pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() internal pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: LibNetwork.TAIKO_MAINNET, maxUnverifiedBatches: 10, diff --git a/packages/protocol/test/layer1/based/InboxTest_EtherAsBond.t.sol b/packages/protocol/test/layer1/based/InboxTest_EtherAsBond.t.sol index 87ca6ed45a7..ba1b6405e7d 100644 --- a/packages/protocol/test/layer1/based/InboxTest_EtherAsBond.t.sol +++ b/packages/protocol/test/layer1/based/InboxTest_EtherAsBond.t.sol @@ -5,7 +5,7 @@ import "contracts/layer1/based/ITaikoInbox.sol"; import "./InboxTestBase.sol"; contract InboxTest_EtherAsBond is InboxTestBase { - function getConfig() internal pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() internal pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: LibNetwork.TAIKO_MAINNET, maxUnverifiedBatches: 10, diff --git a/packages/protocol/test/layer1/based/InboxTest_Params.t.sol b/packages/protocol/test/layer1/based/InboxTest_Params.t.sol index 6cb25ade808..bf27a6f7905 100644 --- a/packages/protocol/test/layer1/based/InboxTest_Params.t.sol +++ b/packages/protocol/test/layer1/based/InboxTest_Params.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.24; import "./InboxTestBase.sol"; contract InboxTest_Params is InboxTestBase { - function getConfig() internal pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() internal pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: LibNetwork.TAIKO_MAINNET, maxUnverifiedBatches: 10, @@ -49,7 +49,7 @@ contract InboxTest_Params is InboxTestBase { external transactBy(Alice) { - ITaikoInbox.Config memory config = inbox.getConfig(); + ITaikoInbox.Config memory config = inbox.pacayaConfig(); // Advance the block number to create the appropriate test scenario vm.roll(config.maxAnchorHeightOffset + 2); diff --git a/packages/protocol/test/layer1/based/InboxTest_ProposeAndProve.t.sol b/packages/protocol/test/layer1/based/InboxTest_ProposeAndProve.t.sol index de25aeee3f1..7417bd003b3 100644 --- a/packages/protocol/test/layer1/based/InboxTest_ProposeAndProve.t.sol +++ b/packages/protocol/test/layer1/based/InboxTest_ProposeAndProve.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.24; import "./InboxTestBase.sol"; contract InboxTest_ProposeAndProve is InboxTestBase { - function getConfig() internal pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() internal pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: LibNetwork.TAIKO_MAINNET, maxUnverifiedBatches: 10, @@ -228,15 +228,15 @@ contract InboxTest_ProposeAndProve is InboxTestBase { assertEq(ts.stateRoot, bytes32(uint256(0))); vm.expectRevert(ITaikoInbox.TransitionNotFound.selector); - ts = inbox.getTransition(9, uint24(0)); + ts = inbox.getTransitionById(9, uint24(0)); - ts = inbox.getTransition(9, uint24(1)); + ts = inbox.getTransitionById(9, uint24(1)); assertEq(ts.parentHash, correctBlockhash(8)); assertEq(ts.blockHash, correctBlockhash(9)); assertEq(ts.stateRoot, bytes32(uint256(0))); vm.expectRevert(ITaikoInbox.TransitionNotFound.selector); - ts = inbox.getTransition(9, ts.parentHash); + ts = inbox.getTransitionByParentHash(9, ts.parentHash); (batchId, blockId, ts) = inbox.getLastSyncedTransition(); assertEq(batchId, 5); @@ -265,7 +265,7 @@ contract InboxTest_ProposeAndProve is InboxTestBase { assertEq(batch.lastBlockTimestamp, block.timestamp); assertEq(batch.anchorBlockId, block.number - 1); assertEq(batch.nextTransitionId, 2); - if (i % getConfig().stateRootSyncInternal == 0 || i == stats2.lastVerifiedBatchId) { + if (i % pacayaConfig().stateRootSyncInternal == 0 || i == stats2.lastVerifiedBatchId) { assertEq(batch.verifiedTransitionId, 1); } else { assertEq(batch.verifiedTransitionId, 0); @@ -330,7 +330,7 @@ contract InboxTest_ProposeAndProve is InboxTestBase { assertEq(batch.lastBlockId, i * 7); assertEq(batch.anchorBlockId, block.number - 1); assertEq(batch.nextTransitionId, 2); - if (i % getConfig().stateRootSyncInternal == 0 || i == stats2.lastVerifiedBatchId) { + if (i % pacayaConfig().stateRootSyncInternal == 0 || i == stats2.lastVerifiedBatchId) { assertEq(batch.verifiedTransitionId, 1); } else { assertEq(batch.verifiedTransitionId, 0); @@ -379,7 +379,7 @@ contract InboxTest_ProposeAndProve is InboxTestBase { assertEq(batch.lastBlockTimestamp, block.timestamp); assertEq(batch.anchorBlockId, block.number - 1); assertEq(batch.nextTransitionId, 3); - if (i % getConfig().stateRootSyncInternal == 0 || i == stats2.lastVerifiedBatchId) { + if (i % pacayaConfig().stateRootSyncInternal == 0 || i == stats2.lastVerifiedBatchId) { assertEq(batch.verifiedTransitionId, 2); } else { assertEq(batch.verifiedTransitionId, 0); diff --git a/packages/protocol/test/layer1/based/InboxTest_StopBatch.t.sol b/packages/protocol/test/layer1/based/InboxTest_StopBatch.t.sol index 9793cb2895f..00e687b3e91 100644 --- a/packages/protocol/test/layer1/based/InboxTest_StopBatch.t.sol +++ b/packages/protocol/test/layer1/based/InboxTest_StopBatch.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.24; import "./InboxTestBase.sol"; contract InboxTest_StopBatch is InboxTestBase { - function getConfig() internal pure override returns (ITaikoInbox.Config memory) { + function pacayaConfig() internal pure override returns (ITaikoInbox.Config memory) { return ITaikoInbox.Config({ chainId: LibNetwork.TAIKO_MAINNET, maxUnverifiedBatches: 10, @@ -42,6 +42,6 @@ contract InboxTest_StopBatch is InboxTestBase { WhenLogAllBatchesAndTransitions { ITaikoInbox.Stats2 memory _stats2 = inbox.getStats2(); - assertEq(getConfig().maxBatchesToVerify * 9, _stats2.lastVerifiedBatchId); + assertEq(pacayaConfig().maxBatchesToVerify * 9, _stats2.lastVerifiedBatchId); } } diff --git a/packages/protocol/test/layer1/based/helpers/StubInbox.sol b/packages/protocol/test/layer1/based/helpers/StubInbox.sol index ec0f32b0720..86c498e7b32 100644 --- a/packages/protocol/test/layer1/based/helpers/StubInbox.sol +++ b/packages/protocol/test/layer1/based/helpers/StubInbox.sol @@ -28,7 +28,7 @@ contract StubInbox is ITaikoInbox { function getBatch(uint64 _batchId) external view virtual returns (ITaikoInbox.Batch memory) { } - function getTransition( + function getTransitionById( uint64 _batchId, uint24 _tid ) @@ -38,7 +38,7 @@ contract StubInbox is ITaikoInbox { returns (ITaikoInbox.TransitionState memory) { } - function getTransition( + function getTransitionByParentHash( uint64 _batchId, bytes32 _parentHash ) @@ -69,5 +69,5 @@ contract StubInbox is ITaikoInbox { function getStats2() external view returns (Stats2 memory) { } - function getConfig() external pure virtual returns (ITaikoInbox.Config memory) { } + function pacayaConfig() external pure virtual returns (ITaikoInbox.Config memory) { } } diff --git a/packages/protocol/test/layer1/fork-router/ForkRouter.t.sol b/packages/protocol/test/layer1/fork-router/ForkRouter.t.sol new file mode 100644 index 00000000000..1a7a4466ed9 --- /dev/null +++ b/packages/protocol/test/layer1/fork-router/ForkRouter.t.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "../Layer1Test.sol"; +import "src/layer1/fork-router/ForkRouter.sol"; + +contract Fork is EssentialContract { + bytes32 private immutable __name; + + constructor(bytes32 _name) EssentialContract(address(0)) { + __name = _name; + } + + function init() external initializer { + __Essential_init(msg.sender); + } + + function name() public view returns (bytes32) { + return __name; + } +} + +contract ForkRouter_RouteToOldFork is ForkRouter { + constructor(address _fork1, address _fork2) ForkRouter(_fork1, _fork2) { } + + function shouldRouteToOldFork(bytes4 _selector) public pure override returns (bool) { + return _selector == Fork.name.selector; + } +} + +contract TestForkManager is Layer1Test { + address fork1 = address(new Fork("fork1")); + address fork2 = address(new Fork("fork2")); + + function test_ForkManager_default_routing() public transactBy(deployer) { + address proxy = deploy({ + name: "main_proxy", + impl: address(new ForkRouter(address(0), fork1)), + data: abi.encodeCall(Fork.init, ()) + }); + + assertEq(Fork(proxy).name(), "fork1"); + + Fork(proxy).upgradeTo(fork2); + Fork(proxy).upgradeTo(address(new ForkRouter(fork1, fork2))); + assertEq(Fork(proxy).name(), "fork2"); + Fork(proxy).upgradeTo(address(new ForkRouter(fork2, fork1))); + assertEq(Fork(proxy).name(), "fork1"); + } + + function test_ForkManager_routing_to_old_fork() public transactBy(deployer) { + address proxy = deploy({ + name: "main_proxy", + impl: address(new ForkRouter_RouteToOldFork(fork1, fork2)), + data: abi.encodeCall(Fork.init, ()) + }); + + assertEq(Fork(proxy).name(), "fork1"); + Fork(proxy).upgradeTo(address(new ForkRouter(fork1, fork2))); + assertEq(Fork(proxy).name(), "fork2"); + } +} diff --git a/packages/protocol/test/layer1/preconf/mocks/MockTaikoInbox.sol b/packages/protocol/test/layer1/preconf/mocks/MockTaikoInbox.sol index 3548522701a..37609199129 100644 --- a/packages/protocol/test/layer1/preconf/mocks/MockTaikoInbox.sol +++ b/packages/protocol/test/layer1/preconf/mocks/MockTaikoInbox.sol @@ -32,6 +32,8 @@ contract MockTaikoInbox is EssentialContract { extraData: bytes32(0), coinbase: params.coinbase == address(0) ? params.proposer : params.coinbase, gasLimit: 0, // Mock value + lastBlockId: 0, + lastBlockTimestamp: 0, proposedIn: uint64(block.number), anchorBlockId: params.anchorBlockId, anchorBlockHash: bytes32(0), // Mock value diff --git a/packages/protocol/test/shared/DeployCapability.sol b/packages/protocol/test/shared/DeployCapability.sol index 67c9b6274b5..90544d39c02 100644 --- a/packages/protocol/test/shared/DeployCapability.sol +++ b/packages/protocol/test/shared/DeployCapability.sol @@ -81,7 +81,9 @@ abstract contract DeployCapability is Script { register({ registerTo: registerTo, name: name, - addr: EssentialContract(readFrom).resolve(uint64(block.chainid), bytes32(bytes(name)), true), + addr: EssentialContract(readFrom).resolveAddress( + uint64(block.chainid), bytes32(bytes(name)), true + ), chainId: uint64(block.chainid) }); }