From 0f063922ce9377acf2d6cb6965e2037d0407ca72 Mon Sep 17 00:00:00 2001 From: Daniel Wang <99078276+dantaik@users.noreply.github.com> Date: Fri, 2 Jun 2023 13:19:54 +0800 Subject: [PATCH] chore(protocol): remove tokenomics and format solidity file (#13822) (#13829) Co-authored-by: dantaik Co-authored-by: dave | d1onys1us <13951458+d1onys1us@users.noreply.github.com> --- packages/protocol/.solhint.json | 2 +- .../protocol/contracts/L1/TaikoConfig.sol | 14 +- packages/protocol/contracts/L1/TaikoData.sol | 18 +- .../protocol/contracts/L1/TaikoErrors.sol | 4 +- .../protocol/contracts/L1/TaikoEvents.sol | 14 +- packages/protocol/contracts/L1/TaikoL1.sol | 185 ++-- packages/protocol/contracts/L1/TaikoToken.sol | 76 +- .../contracts/L1/libs/LibEthDepositing.sol | 51 +- .../contracts/L1/libs/LibProposing.sol | 79 +- .../protocol/contracts/L1/libs/LibProving.sol | 112 ++- .../contracts/L1/libs/LibTokenomics.sol | 107 -- .../protocol/contracts/L1/libs/LibUtils.sol | 49 +- .../contracts/L1/libs/LibVerifying.sol | 91 +- .../protocol/contracts/L2/LibL2Consts.sol | 2 +- packages/protocol/contracts/L2/TaikoL2.sol | 98 +- .../protocol/contracts/L2/TaikoL2Signer.sol | 46 +- packages/protocol/contracts/bridge/Bridge.sol | 93 +- .../contracts/bridge/BridgedERC20.sol | 55 +- .../protocol/contracts/bridge/EtherVault.sol | 24 +- .../protocol/contracts/bridge/IBridge.sol | 28 +- .../protocol/contracts/bridge/TokenVault.sol | 83 +- .../contracts/bridge/libs/LibBridgeData.sol | 19 +- .../contracts/bridge/libs/LibBridgeInvoke.sol | 15 +- .../bridge/libs/LibBridgeProcess.sol | 50 +- .../bridge/libs/LibBridgeRelease.sol | 26 +- .../contracts/bridge/libs/LibBridgeRetry.sol | 41 +- .../contracts/bridge/libs/LibBridgeSend.sol | 47 +- .../contracts/bridge/libs/LibBridgeStatus.sol | 52 +- .../contracts/common/AddressManager.sol | 41 +- .../contracts/common/AddressResolver.sol | 25 +- .../contracts/common/EssentialContract.sol | 21 +- .../contracts/common/ICrossChainSync.sol | 14 +- .../contracts/common/IMintableERC20.sol | 2 +- .../protocol/contracts/common/Proxied.sol | 3 +- .../protocol/contracts/gov/TaikoGovernor.sol | 44 +- .../protocol/contracts/libs/Lib1559Math.sol | 20 +- .../protocol/contracts/libs/LibAddress.sol | 2 +- .../contracts/libs/LibBlockHeader.sol | 16 +- .../protocol/contracts/libs/LibTrieProof.sol | 33 +- .../contracts/libs/LibUint512Math.sol | 16 +- .../contracts/signal/ISignalService.sol | 19 +- .../contracts/signal/SignalService.sol | 52 +- .../test/ExampleStaticAddressManager.sol | 15 +- .../contracts/test/L1/TestTaikoL1.sol | 17 +- .../test/L1/TestTaikoL1EnableTokenomics.sol | 17 +- .../protocol/contracts/test/TestContracts.sol | 26 +- .../contracts/test/bridge/TestHeaderSync.sol | 2 +- .../test/bridge/libs/TestLibBridgeData.sol | 25 +- .../test/bridge/libs/TestLibBridgeInvoke.sol | 15 +- .../test/bridge/libs/TestLibBridgeProcess.sol | 19 +- .../test/bridge/libs/TestLibBridgeRetry.sol | 24 +- .../test/bridge/libs/TestLibBridgeSend.sol | 16 +- .../contracts/test/erc20/FreeMintERC20.sol | 4 +- .../test/erc20/MayFailFreeMintERC20.sol | 19 +- .../contracts/test/erc20/RegularERC20.sol | 2 +- .../test/libs/TestLibBlockHeader.sol | 16 +- .../contracts/test/libs/TestLibTrieProof.sol | 2 +- .../test/thirdparty/TestLibMerkleTrie.sol | 14 +- .../test/thirdparty/TestLibRLPReader.sol | 2 +- .../test/thirdparty/TestLibRLPWriter.sol | 26 +- .../thirdparty/TestLibSecureMerkleTrie.sol | 18 +- .../test/thirdparty/TestMessageSender.sol | 11 +- .../contracts/thirdparty/LibBytesUtils.sol | 65 +- .../thirdparty/LibFixedPointMath.sol | 70 +- .../contracts/thirdparty/LibMerkleTrie.sol | 114 ++- .../contracts/thirdparty/LibRLPReader.sol | 109 ++- .../contracts/thirdparty/LibRLPWriter.sol | 51 +- .../thirdparty/LibSecureMerkleTrie.sol | 26 +- .../TransparentUpgradeableProxy.sol | 93 +- packages/protocol/foundry.toml | 6 +- packages/protocol/package.json | 26 +- packages/protocol/script/DeployOnL1.s.sol | 87 +- .../script/DetermineNewProofTimeIssued.s.sol | 21 - packages/protocol/script/test_deploy_on_l1.sh | 2 - packages/protocol/test/Bridge.t.sol | 109 ++- packages/protocol/test/EtherVault.t.sol | 21 +- packages/protocol/test/GasComparison.t.sol | 68 +- packages/protocol/test/Lib1559Math.t.sol | 46 +- .../protocol/test/LibFixedPointMath.t.sol | 20 +- packages/protocol/test/LibLn.sol | 215 ---- packages/protocol/test/SignalService.t.sol | 54 +- .../protocol/test/SignalServiceCalc.t.sol | 8 +- packages/protocol/test/Taiko1559Params.t.sol | 21 +- packages/protocol/test/TaikoL1.sim.sol | 535 +++++----- packages/protocol/test/TaikoL1.t.sol | 151 ++- .../test/TaikoL1LibTokenomicsMainnet.t.sol | 285 ------ .../test/TaikoL1LibTokenomicsTestnet.t.sol | 919 ------------------ packages/protocol/test/TaikoL1Oracle.t.sol | 413 ++++---- packages/protocol/test/TaikoL1TestBase.t.sol | 80 +- packages/protocol/test/TaikoL2.t.sol | 72 +- packages/protocol/test/TaikoToken.t.sol | 38 +- packages/protocol/test/TokenVault.t.sol | 99 +- .../test/genesis/GenerateGenesis.g.sol | 112 ++- .../contract-documentation/L1/TaikoData.md | 14 +- .../contract-documentation/L1/TaikoErrors.md | 6 - .../contract-documentation/L1/TaikoL1.md | 50 +- .../common/AddressResolver.md | 12 +- 97 files changed, 2844 insertions(+), 3253 deletions(-) delete mode 100644 packages/protocol/contracts/L1/libs/LibTokenomics.sol delete mode 100644 packages/protocol/script/DetermineNewProofTimeIssued.s.sol delete mode 100644 packages/protocol/test/LibLn.sol delete mode 100644 packages/protocol/test/TaikoL1LibTokenomicsMainnet.t.sol delete mode 100644 packages/protocol/test/TaikoL1LibTokenomicsTestnet.t.sol diff --git a/packages/protocol/.solhint.json b/packages/protocol/.solhint.json index 1ccc385aed2..1ab2a8962fc 100644 --- a/packages/protocol/.solhint.json +++ b/packages/protocol/.solhint.json @@ -4,7 +4,7 @@ "avoid-low-level-calls": "off", "compiler-version": ["error", "^0.8.18"], "func-visibility": ["warn", { "ignoreConstructors": true }], - "max-line-length": ["warn", 100], + "max-line-length": "off", "no-empty-blocks": "off", "no-inline-assembly": "off", "not-rely-on-time": "off", diff --git a/packages/protocol/contracts/L1/TaikoConfig.sol b/packages/protocol/contracts/L1/TaikoConfig.sol index 071954821ce..ca4529407c1 100644 --- a/packages/protocol/contracts/L1/TaikoConfig.sol +++ b/packages/protocol/contracts/L1/TaikoConfig.sol @@ -6,39 +6,39 @@ pragma solidity ^0.8.18; -import {TaikoData} from "../L1/TaikoData.sol"; +import { TaikoData } from "../L1/TaikoData.sol"; library TaikoConfig { function getConfig() internal pure returns (TaikoData.Config memory) { return TaikoData.Config({ chainId: 167, // Two weeks if avg block time is 10 seconds - maxNumProposedBlocks: 120960, - ringBufferSize: 120960 + 10, + maxNumProposedBlocks: 120_960, + ringBufferSize: 120_960 + 10, // Each time one more block is verified, there will be ~20k // more gas cost. maxVerificationsPerTx: 10, // Set it to 6M, since its the upper limit of the Alpha-2 // testnet's circuits. - blockMaxGasLimit: 6000000, + blockMaxGasLimit: 6_000_000, // Set it to 79 (+1 TaikoL2.anchor transaction = 80), // and 80 is the upper limit of the Alpha-2 testnet's circuits. maxTransactionsPerBlock: 79, minEthDepositsPerBlock: 8, maxEthDepositsPerBlock: 32, - maxEthDepositAmount: 10000 ether, + maxEthDepositAmount: 10_000 ether, minEthDepositAmount: 1 ether, // Set it to 120KB, since 128KB is the upper size limit // of a geth transaction, so using 120KB for the proposed // transactions list calldata, 8K for the remaining tx fields. - maxBytesPerTxList: 120000, + maxBytesPerTxList: 120_000, proofCooldownPeriod: 30 minutes, systemProofCooldownPeriod: 15 minutes, // Only need 1 real zkp per 10 blocks. // If block number is N, then only when N % 10 == 0, the real ZKP // is needed. For mainnet, this must be 0 or 1. realProofSkipSize: 10, - ethDepositGas: 21000, + ethDepositGas: 21_000, ethDepositMaxFee: 1 ether / 10, txListCacheExpiry: 0, relaySignalRoot: false diff --git a/packages/protocol/contracts/L1/TaikoData.sol b/packages/protocol/contracts/L1/TaikoData.sol index 956690766b9..f7be7519898 100644 --- a/packages/protocol/contracts/L1/TaikoData.sol +++ b/packages/protocol/contracts/L1/TaikoData.sol @@ -32,14 +32,10 @@ library TaikoData { struct StateVariables { uint64 blockFee; - uint64 accBlockFees; uint64 genesisHeight; uint64 genesisTimestamp; uint64 numBlocks; - uint64 proofTimeIssued; - uint64 proofTimeTarget; uint64 lastVerifiedBlockId; - uint64 accProposedAt; uint64 nextEthDepositToProcess; uint64 numEthDeposits; } @@ -121,11 +117,11 @@ library TaikoData { struct State { // Ring buffer for proposed blocks and a some recent verified blocks. mapping(uint256 blockId_mode_ringBufferSize => Block) blocks; - // solhint-disable-next-line max-line-length mapping( uint256 blockId => mapping( - bytes32 parentHash => mapping(uint32 parentGasUsed => uint256 forkChoiceId) + bytes32 parentHash + => mapping(uint32 parentGasUsed => uint256 forkChoiceId) ) ) forkChoiceIds; mapping(address account => uint256 balance) taikoTokenBalances; @@ -135,19 +131,19 @@ library TaikoData { // Slot 7: never or rarely changed uint64 genesisHeight; uint64 genesisTimestamp; - uint16 adjustmentQuotient; + uint16 __reserved70; uint48 __reserved71; uint64 __reserved72; // Slot 8 - uint64 accProposedAt; - uint64 accBlockFees; + uint64 __reserved80; + uint64 __reserved81; uint64 numBlocks; uint64 nextEthDepositToProcess; // Slot 9 uint64 blockFee; - uint64 proofTimeIssued; + uint64 __reserved90; uint64 lastVerifiedBlockId; - uint64 proofTimeTarget; + uint64 __reserved91; // Reserved uint256[42] __gap; } diff --git a/packages/protocol/contracts/L1/TaikoErrors.sol b/packages/protocol/contracts/L1/TaikoErrors.sol index a94a128bc24..cec92dcf110 100644 --- a/packages/protocol/contracts/L1/TaikoErrors.sol +++ b/packages/protocol/contracts/L1/TaikoErrors.sol @@ -7,12 +7,12 @@ pragma solidity ^0.8.18; abstract contract TaikoErrors { - // The following custom errors must match the definitions in other V1 libraries. + // The following custom errors must match the definitions in other V1 + // libraries. error L1_ALREADY_PROVEN(); error L1_BLOCK_ID(); error L1_EVIDENCE_MISMATCH(bytes32 expected, bytes32 actual); error L1_FORK_CHOICE_NOT_FOUND(); - error L1_INSUFFICIENT_TOKEN(); error L1_INVALID_CONFIG(); error L1_INVALID_ETH_DEPOSIT(); error L1_INVALID_EVIDENCE(); diff --git a/packages/protocol/contracts/L1/TaikoEvents.sol b/packages/protocol/contracts/L1/TaikoEvents.sol index 3ddcaa99306..7904d9aaf88 100644 --- a/packages/protocol/contracts/L1/TaikoEvents.sol +++ b/packages/protocol/contracts/L1/TaikoEvents.sol @@ -6,11 +6,14 @@ pragma solidity ^0.8.18; -import {TaikoData} from "./TaikoData.sol"; +import { TaikoData } from "./TaikoData.sol"; abstract contract TaikoEvents { - // The following events must match the definitions in corresponding L1 libraries. - event BlockProposed(uint256 indexed id, TaikoData.BlockMetadata meta, uint64 blockFee); + // The following events must match the definitions in corresponding L1 + // libraries. + event BlockProposed( + uint256 indexed id, TaikoData.BlockMetadata meta, uint64 blockFee + ); event BlockProven( uint256 indexed id, @@ -26,6 +29,9 @@ abstract contract TaikoEvents { event EthDeposited(TaikoData.EthDeposit deposit); event ProofParamsChanged( - uint64 proofTimeTarget, uint64 proofTimeIssued, uint64 blockFee, uint16 adjustmentQuotient + uint64 proofTimeTarget, + uint64 proofTimeIssued, + uint64 blockFee, + uint16 adjustmentQuotient ); } diff --git a/packages/protocol/contracts/L1/TaikoL1.sol b/packages/protocol/contracts/L1/TaikoL1.sol index 0e7302a2dae..06f769aa980 100644 --- a/packages/protocol/contracts/L1/TaikoL1.sol +++ b/packages/protocol/contracts/L1/TaikoL1.sol @@ -6,23 +6,27 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../common/AddressResolver.sol"; -import {EssentialContract} from "../common/EssentialContract.sol"; -import {ICrossChainSync} from "../common/ICrossChainSync.sol"; -import {Proxied} from "../common/Proxied.sol"; -import {LibEthDepositing} from "./libs/LibEthDepositing.sol"; -import {LibTokenomics} from "./libs/LibTokenomics.sol"; -import {LibProposing} from "./libs/LibProposing.sol"; -import {LibProving} from "./libs/LibProving.sol"; -import {LibUtils} from "./libs/LibUtils.sol"; -import {LibVerifying} from "./libs/LibVerifying.sol"; -import {TaikoConfig} from "./TaikoConfig.sol"; -import {TaikoErrors} from "./TaikoErrors.sol"; -import {TaikoData} from "./TaikoData.sol"; -import {TaikoEvents} from "./TaikoEvents.sol"; +import { AddressResolver } from "../common/AddressResolver.sol"; +import { EssentialContract } from "../common/EssentialContract.sol"; +import { ICrossChainSync } from "../common/ICrossChainSync.sol"; +import { Proxied } from "../common/Proxied.sol"; +import { LibEthDepositing } from "./libs/LibEthDepositing.sol"; +import { LibProposing } from "./libs/LibProposing.sol"; +import { LibProving } from "./libs/LibProving.sol"; +import { LibUtils } from "./libs/LibUtils.sol"; +import { LibVerifying } from "./libs/LibVerifying.sol"; +import { TaikoConfig } from "./TaikoConfig.sol"; +import { TaikoErrors } from "./TaikoErrors.sol"; +import { TaikoData } from "./TaikoData.sol"; +import { TaikoEvents } from "./TaikoEvents.sol"; /// @custom:security-contact hello@taiko.xyz -contract TaikoL1 is EssentialContract, ICrossChainSync, TaikoEvents, TaikoErrors { +contract TaikoL1 is + EssentialContract, + ICrossChainSync, + TaikoEvents, + TaikoErrors +{ using LibUtils for TaikoData.State; TaikoData.State public state; @@ -38,28 +42,21 @@ contract TaikoL1 is EssentialContract, ICrossChainSync, TaikoEvents, TaikoErrors * @param _addressManager The AddressManager address. * @param _genesisBlockHash The block hash of the genesis block. * @param _initBlockFee Initial (reasonable) block fee value. - * @param _initProofTimeTarget Initial (reasonable) proof submission time target. - * @param _initProofTimeIssued Initial proof time issued corresponding - * with the initial block fee. - * @param _adjustmentQuotient Block fee calculation adjustment quotient. */ function init( address _addressManager, bytes32 _genesisBlockHash, - uint64 _initBlockFee, - uint64 _initProofTimeTarget, - uint64 _initProofTimeIssued, - uint16 _adjustmentQuotient - ) external initializer { + uint64 _initBlockFee + ) + external + initializer + { EssentialContract._init(_addressManager); LibVerifying.init({ state: state, config: getConfig(), genesisBlockHash: _genesisBlockHash, - initBlockFee: _initBlockFee, - initProofTimeTarget: _initProofTimeTarget, - initProofTimeIssued: _initProofTimeIssued, - adjustmentQuotient: _adjustmentQuotient + initBlockFee: _initBlockFee }); } @@ -74,7 +71,10 @@ contract TaikoL1 is EssentialContract, ICrossChainSync, TaikoEvents, TaikoErrors * `n` transactions in `txList`, then there will be up to `n + 1` * transactions in the L2 block. */ - function proposeBlock(bytes calldata input, bytes calldata txList) + function proposeBlock( + bytes calldata input, + bytes calldata txList + ) external nonReentrant returns (TaikoData.BlockMetadata memory meta) @@ -104,7 +104,13 @@ contract TaikoL1 is EssentialContract, ICrossChainSync, TaikoEvents, TaikoErrors * to select the right implementation version. * @param input An abi-encoded TaikoData.BlockEvidence object. */ - function proveBlock(uint256 blockId, bytes calldata input) external nonReentrant { + function proveBlock( + uint256 blockId, + bytes calldata input + ) + external + nonReentrant + { TaikoData.Config memory config = getConfig(); LibProving.proveBlock({ state: state, @@ -137,55 +143,10 @@ contract TaikoL1 is EssentialContract, ICrossChainSync, TaikoEvents, TaikoErrors }); } - /** - * Change proof parameters (time target and time issued) - to avoid complex/risky upgrades in case need to change relatively frequently. - * @param newProofTimeTarget New proof time target. - * @param newProofTimeIssued New proof time issued. If set to type(uint64).max, let it be unchanged. - * @param newBlockFee New blockfee. If set to type(uint64).max, let it be unchanged. - * @param newAdjustmentQuotient New adjustment quotient. If set to type(uint16).max, let it be unchanged. - */ - function setProofParams( - uint64 newProofTimeTarget, - uint64 newProofTimeIssued, - uint64 newBlockFee, - uint16 newAdjustmentQuotient - ) external onlyOwner { - if (newProofTimeTarget == 0 || newProofTimeIssued == 0) { - revert L1_INVALID_PARAM(); - } - - state.proofTimeTarget = newProofTimeTarget; - // Special case in a way - that we leave the proofTimeIssued unchanged - // because we think provers will adjust behavior. - if (newProofTimeIssued != type(uint64).max) { - state.proofTimeIssued = newProofTimeIssued; - } - // Special case in a way - that we leave the blockFee unchanged - // because the level we are at is fine. - if (newBlockFee != type(uint64).max) { - state.blockFee = newBlockFee; - } - // Special case in a way - that we leave the adjustmentQuotient unchanged - // because we the 'slowlyness' of the curve is fine. - if (newAdjustmentQuotient != type(uint16).max) { - state.adjustmentQuotient = newAdjustmentQuotient; - } - - emit ProofParamsChanged( - newProofTimeTarget, newProofTimeIssued, newBlockFee, newAdjustmentQuotient - ); - } - - function depositTaikoToken(uint256 amount) external nonReentrant { - LibTokenomics.depositTaikoToken(state, AddressResolver(this), amount); - } - - function withdrawTaikoToken(uint256 amount) external nonReentrant { - LibTokenomics.withdrawTaikoToken(state, AddressResolver(this), amount); - } - function depositEtherToL2() public payable { - LibEthDepositing.depositEtherToL2(state, getConfig(), AddressResolver(this)); + LibEthDepositing.depositEtherToL2( + state, getConfig(), AddressResolver(this) + ); } function getTaikoTokenBalance(address addr) public view returns (uint256) { @@ -196,23 +157,26 @@ contract TaikoL1 is EssentialContract, ICrossChainSync, TaikoEvents, TaikoErrors return state.blockFee; } - function getProofReward(uint64 proofTime) public view returns (uint64) { - return LibTokenomics.getProofReward(state, proofTime); - } - function getBlock(uint256 blockId) public view returns (bytes32 _metaHash, address _proposer, uint64 _proposedAt) { - TaikoData.Block storage blk = - LibProposing.getBlock({state: state, config: getConfig(), blockId: blockId}); + TaikoData.Block storage blk = LibProposing.getBlock({ + state: state, + config: getConfig(), + blockId: blockId + }); _metaHash = blk.metaHash; _proposer = blk.proposer; _proposedAt = blk.proposedAt; } - function getForkChoice(uint256 blockId, bytes32 parentHash, uint32 parentGasUsed) + function getForkChoice( + uint256 blockId, + bytes32 parentHash, + uint32 parentGasUsed + ) public view returns (TaikoData.ForkChoice memory) @@ -226,24 +190,53 @@ contract TaikoL1 is EssentialContract, ICrossChainSync, TaikoEvents, TaikoErrors }); } - function getCrossChainBlockHash(uint256 blockId) public view override returns (bytes32) { - (bool found, TaikoData.Block storage blk) = - LibUtils.getL2ChainData({state: state, config: getConfig(), blockId: blockId}); - return found ? blk.forkChoices[blk.verifiedForkChoiceId].blockHash : bytes32(0); + function getCrossChainBlockHash(uint256 blockId) + public + view + override + returns (bytes32) + { + (bool found, TaikoData.Block storage blk) = LibUtils.getL2ChainData({ + state: state, + config: getConfig(), + blockId: blockId + }); + return found + ? blk.forkChoices[blk.verifiedForkChoiceId].blockHash + : bytes32(0); } - function getCrossChainSignalRoot(uint256 blockId) public view override returns (bytes32) { - (bool found, TaikoData.Block storage blk) = - LibUtils.getL2ChainData({state: state, config: getConfig(), blockId: blockId}); + function getCrossChainSignalRoot(uint256 blockId) + public + view + override + returns (bytes32) + { + (bool found, TaikoData.Block storage blk) = LibUtils.getL2ChainData({ + state: state, + config: getConfig(), + blockId: blockId + }); - return found ? blk.forkChoices[blk.verifiedForkChoiceId].signalRoot : bytes32(0); + return found + ? blk.forkChoices[blk.verifiedForkChoiceId].signalRoot + : bytes32(0); } - function getStateVariables() public view returns (TaikoData.StateVariables memory) { + function getStateVariables() + public + view + returns (TaikoData.StateVariables memory) + { return state.getStateVariables(); } - function getConfig() public pure virtual returns (TaikoData.Config memory) { + function getConfig() + public + pure + virtual + returns (TaikoData.Config memory) + { return TaikoConfig.getConfig(); } @@ -252,4 +245,4 @@ contract TaikoL1 is EssentialContract, ICrossChainSync, TaikoEvents, TaikoErrors } } -contract ProxiedTaikoL1 is Proxied, TaikoL1 {} +contract ProxiedTaikoL1 is Proxied, TaikoL1 { } diff --git a/packages/protocol/contracts/L1/TaikoToken.sol b/packages/protocol/contracts/L1/TaikoToken.sol index e115885115e..5c5483ae67d 100644 --- a/packages/protocol/contracts/L1/TaikoToken.sol +++ b/packages/protocol/contracts/L1/TaikoToken.sol @@ -6,21 +6,21 @@ pragma solidity ^0.8.18; -import {ERC20Upgradeable} from +import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; -import {ERC20BurnableUpgradeable} from +import { ERC20BurnableUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol"; -import {ERC20SnapshotUpgradeable} from +import { ERC20SnapshotUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20SnapshotUpgradeable.sol"; -import {PausableUpgradeable} from +import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; -import {ERC20PermitUpgradeable} from +import { ERC20PermitUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol"; -import {ERC20VotesUpgradeable} from +import { ERC20VotesUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; -import {EssentialContract} from "../common/EssentialContract.sol"; -import {Proxied} from "../common/Proxied.sol"; +import { EssentialContract } from "../common/EssentialContract.sol"; +import { Proxied } from "../common/Proxied.sol"; library LibTaikoTokenConfig { uint8 public constant DECIMALS = uint8(8); @@ -53,7 +53,10 @@ contract TaikoToken is string calldata _symbol, address[] calldata _premintRecipients, uint256[] calldata _premintAmounts - ) public initializer { + ) + public + initializer + { EssentialContract._init(_addressManager); __ERC20_init(_name, _symbol); __ERC20Burnable_init(); @@ -79,20 +82,43 @@ contract TaikoToken is _unpause(); } - function mint(address to, uint256 amount) public onlyFromNamed("proto_broker") { + function mint( + address to, + uint256 amount + ) + public + onlyFromNamed("proto_broker") + { _mint(to, amount); } - function burn(address from, uint256 amount) public onlyFromNamed("proto_broker") { + function burn( + address from, + uint256 amount + ) + public + onlyFromNamed("proto_broker") + { _burn(from, amount); } - function transfer(address to, uint256 amount) public override returns (bool) { + function transfer( + address to, + uint256 amount + ) + public + override + returns (bool) + { if (to == address(this)) revert TKO_INVALID_ADDR(); return ERC20Upgradeable.transfer(to, amount); } - function transferFrom(address from, address to, uint256 amount) + function transferFrom( + address from, + address to, + uint256 amount + ) public override returns (bool) @@ -109,7 +135,11 @@ contract TaikoToken is INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ - function _beforeTokenTransfer(address from, address to, uint256 amount) + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal override(ERC20Upgradeable, ERC20SnapshotUpgradeable) whenNotPaused @@ -118,14 +148,21 @@ contract TaikoToken is } // The following functions are overrides required by Solidity. - function _afterTokenTransfer(address from, address to, uint256 amount) + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal override(ERC20Upgradeable, ERC20VotesUpgradeable) { super._afterTokenTransfer(from, to, amount); } - function _mint(address to, uint256 amount) + function _mint( + address to, + uint256 amount + ) internal override(ERC20Upgradeable, ERC20VotesUpgradeable) { @@ -136,7 +173,10 @@ contract TaikoToken is emit Mint(to, amount); } - function _burn(address from, uint256 amount) + function _burn( + address from, + uint256 amount + ) internal override(ERC20Upgradeable, ERC20VotesUpgradeable) { @@ -145,4 +185,4 @@ contract TaikoToken is } } -contract ProxiedTaikoToken is Proxied, TaikoToken {} +contract ProxiedTaikoToken is Proxied, TaikoToken { } diff --git a/packages/protocol/contracts/L1/libs/LibEthDepositing.sol b/packages/protocol/contracts/L1/libs/LibEthDepositing.sol index 501d960dff4..ef09e7e54a7 100644 --- a/packages/protocol/contracts/L1/libs/LibEthDepositing.sol +++ b/packages/protocol/contracts/L1/libs/LibEthDepositing.sol @@ -6,12 +6,12 @@ pragma solidity ^0.8.18; -import {LibAddress} from "../../libs/LibAddress.sol"; -import {LibMath} from "../../libs/LibMath.sol"; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {SafeCastUpgradeable} from +import { LibAddress } from "../../libs/LibAddress.sol"; +import { LibMath } from "../../libs/LibMath.sol"; +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; -import {TaikoData} from "../TaikoData.sol"; +import { TaikoData } from "../TaikoData.sol"; library LibEthDepositing { using LibAddress for address; @@ -26,13 +26,20 @@ library LibEthDepositing { TaikoData.State storage state, TaikoData.Config memory config, AddressResolver resolver - ) internal { - if (msg.value < config.minEthDepositAmount || msg.value > config.maxEthDepositAmount) { + ) + internal + { + if ( + msg.value < config.minEthDepositAmount + || msg.value > config.maxEthDepositAmount + ) { revert L1_INVALID_ETH_DEPOSIT(); } - TaikoData.EthDeposit memory deposit = - TaikoData.EthDeposit({recipient: msg.sender, amount: uint96(msg.value)}); + TaikoData.EthDeposit memory deposit = TaikoData.EthDeposit({ + recipient: msg.sender, + amount: uint96(msg.value) + }); address to = resolver.resolve("ether_vault", true); if (to == address(0)) { @@ -48,7 +55,10 @@ library LibEthDepositing { TaikoData.State storage state, TaikoData.Config memory config, address beneficiary - ) internal returns (TaikoData.EthDeposit[] memory depositsProcessed) { + ) + internal + returns (TaikoData.EthDeposit[] memory depositsProcessed) + { // Allocate one extra slot for collecting fees on L2 depositsProcessed = new TaikoData.EthDeposit[]( config.maxEthDepositsPerBlock + 1 @@ -61,24 +71,29 @@ library LibEthDepositing { ) { unchecked { // When maxEthDepositsPerBlock is 32, the average gas cost per - // EthDeposit is about 2700 gas. We use 21000 so the proposer may - // earn a small profit if there are 32 deposits included + // EthDeposit is about 2700 gas. We use 21000 so the proposer + // may earn a small profit if there are 32 deposits included // in the block; if there are less EthDeposit to process, the // proposer may suffer a loss so the proposer should simply wait // for more EthDeposit be become available. - uint96 feePerDeposit = - uint96(config.ethDepositMaxFee.min(block.basefee * config.ethDepositGas)); + uint96 feePerDeposit = uint96( + config.ethDepositMaxFee.min( + block.basefee * config.ethDepositGas + ) + ); uint96 totalFee; uint64 i = state.nextEthDepositToProcess; while ( i < state.ethDeposits.length - && i < state.nextEthDepositToProcess + config.maxEthDepositsPerBlock + && state.nextEthDepositToProcess + + config.maxEthDepositsPerBlock > i ) { TaikoData.EthDeposit storage deposit = state.ethDeposits[i]; if (deposit.amount > feePerDeposit) { totalFee += feePerDeposit; depositsProcessed[j].recipient = deposit.recipient; - depositsProcessed[j].amount = deposit.amount - feePerDeposit; + depositsProcessed[j].amount = + deposit.amount - feePerDeposit; ++j; } else { totalFee += deposit.amount; @@ -114,8 +129,8 @@ library LibEthDepositing { bytes memory buffer = new bytes(32 * deposits.length); for (uint256 i; i < deposits.length;) { - uint256 encoded = - uint256(uint160(deposits[i].recipient)) << 96 | uint256(deposits[i].amount); + uint256 encoded = uint256(uint160(deposits[i].recipient)) << 96 + | uint256(deposits[i].amount); assembly { mstore(add(buffer, mul(32, add(1, i))), encoded) } diff --git a/packages/protocol/contracts/L1/libs/LibProposing.sol b/packages/protocol/contracts/L1/libs/LibProposing.sol index 794d34692d7..1d1305d844f 100644 --- a/packages/protocol/contracts/L1/libs/LibProposing.sol +++ b/packages/protocol/contracts/L1/libs/LibProposing.sol @@ -6,13 +6,13 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {LibAddress} from "../../libs/LibAddress.sol"; -import {LibEthDepositing} from "./LibEthDepositing.sol"; -import {LibUtils} from "./LibUtils.sol"; -import {SafeCastUpgradeable} from +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { LibAddress } from "../../libs/LibAddress.sol"; +import { LibEthDepositing } from "./LibEthDepositing.sol"; +import { LibUtils } from "./LibUtils.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; -import {TaikoData} from "../TaikoData.sol"; +import { TaikoData } from "../TaikoData.sol"; library LibProposing { using SafeCastUpgradeable for uint256; @@ -20,10 +20,11 @@ library LibProposing { using LibAddress for address payable; using LibUtils for TaikoData.State; - event BlockProposed(uint256 indexed id, TaikoData.BlockMetadata meta, uint64 blockFee); + event BlockProposed( + uint256 indexed id, TaikoData.BlockMetadata meta, uint64 blockFee + ); error L1_BLOCK_ID(); - error L1_INSUFFICIENT_TOKEN(); error L1_INVALID_METADATA(); error L1_TOO_MANY_BLOCKS(); error L1_TX_LIST_NOT_EXIST(); @@ -37,9 +38,16 @@ library LibProposing { AddressResolver resolver, TaikoData.BlockMetadataInput memory input, bytes calldata txList - ) internal returns (TaikoData.BlockMetadata memory meta) { - uint8 cacheTxListInfo = - _validateBlock({state: state, config: config, input: input, txList: txList}); + ) + internal + returns (TaikoData.BlockMetadata memory meta) + { + uint8 cacheTxListInfo = _validateBlock({ + state: state, + config: config, + input: input, + txList: txList + }); if (cacheTxListInfo != 0) { state.txListInfo[input.txListHash] = TaikoData.TxListInfo({ @@ -60,7 +68,8 @@ library LibProposing { meta.gasLimit = input.gasLimit; meta.beneficiary = input.beneficiary; meta.treasury = resolver.resolve(config.chainId, "treasury", false); - meta.depositsProcessed = LibEthDepositing.processDeposits(state, config, input.beneficiary); + meta.depositsProcessed = + LibEthDepositing.processDeposits(state, config, input.beneficiary); unchecked { meta.timestamp = uint64(block.timestamp); @@ -69,7 +78,8 @@ library LibProposing { meta.mixHash = bytes32(block.difficulty * state.numBlocks); } - TaikoData.Block storage blk = state.blocks[state.numBlocks % config.ringBufferSize]; + TaikoData.Block storage blk = + state.blocks[state.numBlocks % config.ringBufferSize]; blk.blockId = state.numBlocks; blk.proposedAt = meta.timestamp; @@ -78,16 +88,7 @@ library LibProposing { blk.metaHash = LibUtils.hashMetadata(meta); blk.proposer = msg.sender; - uint64 blockFee = state.blockFee; - if (state.taikoTokenBalances[msg.sender] < blockFee) { - revert L1_INSUFFICIENT_TOKEN(); - } - - unchecked { - state.taikoTokenBalances[msg.sender] -= blockFee; - state.accBlockFees += blockFee; - state.accProposedAt += meta.timestamp; - } + uint64 blockFee; emit BlockProposed(state.numBlocks, meta, blockFee); unchecked { @@ -99,7 +100,11 @@ library LibProposing { TaikoData.State storage state, TaikoData.Config memory config, uint256 blockId - ) internal view returns (TaikoData.Block storage blk) { + ) + internal + view + returns (TaikoData.Block storage blk) + { blk = state.blocks[blockId % config.ringBufferSize]; if (blk.blockId != blockId) revert L1_BLOCK_ID(); } @@ -109,13 +114,23 @@ library LibProposing { TaikoData.Config memory config, TaikoData.BlockMetadataInput memory input, bytes calldata txList - ) private view returns (uint8 cacheTxListInfo) { + ) + private + view + returns (uint8 cacheTxListInfo) + { if ( - input.beneficiary == address(0) || input.gasLimit == 0 - || input.gasLimit > config.blockMaxGasLimit + input.beneficiary == address(0) + // + || input.gasLimit == 0 + // + || input.gasLimit > config.blockMaxGasLimit ) revert L1_INVALID_METADATA(); - if (state.numBlocks >= state.lastVerifiedBlockId + config.maxNumProposedBlocks + 1) { + if ( + state.numBlocks + >= state.lastVerifiedBlockId + config.maxNumProposedBlocks + 1 + ) { revert L1_TOO_MANY_BLOCKS(); } @@ -138,13 +153,17 @@ library LibProposing { // caching is enabled if (size == 0) { // This blob shall have been submitted earlier - TaikoData.TxListInfo memory info = state.txListInfo[input.txListHash]; + TaikoData.TxListInfo memory info = + state.txListInfo[input.txListHash]; if (input.txListByteEnd > info.size) { revert L1_TX_LIST_RANGE(); } - if (info.size == 0 || info.validSince + config.txListCacheExpiry < timeNow) { + if ( + info.size == 0 + || info.validSince + config.txListCacheExpiry < timeNow + ) { revert L1_TX_LIST_NOT_EXIST(); } } else { diff --git a/packages/protocol/contracts/L1/libs/LibProving.sol b/packages/protocol/contracts/L1/libs/LibProving.sol index 99502dcaf45..0f17ac69c4a 100644 --- a/packages/protocol/contracts/L1/libs/LibProving.sol +++ b/packages/protocol/contracts/L1/libs/LibProving.sol @@ -6,10 +6,10 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {LibMath} from "../../libs/LibMath.sol"; -import {LibUtils} from "./LibUtils.sol"; -import {TaikoData} from "../../L1/TaikoData.sol"; +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { LibMath } from "../../libs/LibMath.sol"; +import { LibUtils } from "./LibUtils.sol"; +import { TaikoData } from "../../L1/TaikoData.sol"; library LibProving { using LibMath for uint256; @@ -43,18 +43,28 @@ library LibProving { AddressResolver resolver, uint256 blockId, TaikoData.BlockEvidence memory evidence - ) internal { + ) + internal + { if ( - evidence.parentHash == 0 || evidence.blockHash == 0 - || evidence.blockHash == evidence.parentHash || evidence.signalRoot == 0 - || evidence.gasUsed == 0 + evidence.parentHash == 0 + // + || evidence.blockHash == 0 + // + || evidence.blockHash == evidence.parentHash + // + || evidence.signalRoot == 0 + // + || evidence.gasUsed == 0 ) revert L1_INVALID_EVIDENCE(); - if (blockId <= state.lastVerifiedBlockId || blockId >= state.numBlocks) { + if (blockId <= state.lastVerifiedBlockId || blockId >= state.numBlocks) + { revert L1_BLOCK_ID(); } - TaikoData.Block storage blk = state.blocks[blockId % config.ringBufferSize]; + TaikoData.Block storage blk = + state.blocks[blockId % config.ringBufferSize]; // Check the metadata hash matches the proposed block's. This is // necessary to handle chain reorgs. @@ -76,7 +86,10 @@ library LibProving { revert L1_SYSTEM_PROVER_DISABLED(); } - if (config.realProofSkipSize <= 1 || blockId % config.realProofSkipSize == 0) { + if ( + config.realProofSkipSize <= 1 + || blockId % config.realProofSkipSize == 0 + ) { revert L1_SYSTEM_PROVER_PROHIBITED(); } } @@ -98,7 +111,10 @@ library LibProving { evidence.verifierId = 0; evidence.proof = new bytes(0); - if (specialProver != ecrecover(keccak256(abi.encode(evidence)), v, r, s)) { + if ( + specialProver + != ecrecover(keccak256(abi.encode(evidence)), v, r, s) + ) { revert L1_NOT_SPECIAL_PROVER(); } } @@ -106,8 +122,9 @@ library LibProving { TaikoData.ForkChoice storage fc; - uint256 fcId = - LibUtils.getForkChoiceId(state, blk, evidence.parentHash, evidence.parentGasUsed); + uint256 fcId = LibUtils.getForkChoiceId( + state, blk, evidence.parentHash, evidence.parentGasUsed + ); if (fcId == 0) { fcId = blk.nextForkChoiceId; @@ -120,15 +137,19 @@ library LibProving { if (fcId == 1) { // We only write the key when fcId is 1. - fc.key = LibUtils.keyForForkChoice(evidence.parentHash, evidence.parentGasUsed); + fc.key = LibUtils.keyForForkChoice( + evidence.parentHash, evidence.parentGasUsed + ); } else { - state.forkChoiceIds[blk.blockId][evidence.parentHash][evidence.parentGasUsed] = fcId; + state.forkChoiceIds[blk.blockId][evidence.parentHash][evidence + .parentGasUsed] = fcId; } } else if (evidence.prover == address(0)) { // This is the branch the oracle prover is trying to overwrite fc = blk.forkChoices[fcId]; if ( - fc.blockHash == evidence.blockHash && fc.signalRoot == evidence.signalRoot + fc.blockHash == evidence.blockHash + && fc.signalRoot == evidence.signalRoot && fc.gasUsed == evidence.gasUsed ) revert L1_SAME_PROOF(); } else { @@ -139,7 +160,8 @@ library LibProving { } if ( - fc.blockHash != evidence.blockHash || fc.signalRoot != evidence.signalRoot + fc.blockHash != evidence.blockHash + || fc.signalRoot != evidence.signalRoot || fc.gasUsed != evidence.gasUsed ) revert L1_INVALID_PROOF_OVERWRITE(); } @@ -148,20 +170,28 @@ library LibProving { fc.signalRoot = evidence.signalRoot; fc.gasUsed = evidence.gasUsed; fc.prover = evidence.prover; - - if (evidence.prover == address(1)) { - fc.provenAt = uint64(block.timestamp.max(blk.proposedAt + state.proofTimeTarget)); - } else { - fc.provenAt = uint64(block.timestamp); - } + fc.provenAt = uint64(block.timestamp); if (evidence.prover != address(0) && evidence.prover != address(1)) { uint256[10] memory inputs; - inputs[0] = uint256(uint160(address(resolver.resolve("signal_service", false)))); - inputs[1] = - uint256(uint160(address(resolver.resolve(config.chainId, "signal_service", false)))); - inputs[2] = uint256(uint160(address(resolver.resolve(config.chainId, "taiko", false)))); + inputs[0] = uint256( + uint160(address(resolver.resolve("signal_service", false))) + ); + inputs[1] = uint256( + uint160( + address( + resolver.resolve( + config.chainId, "signal_service", false + ) + ) + ) + ); + inputs[2] = uint256( + uint160( + address(resolver.resolve(config.chainId, "taiko", false)) + ) + ); inputs[3] = uint256(evidence.metaHash); inputs[4] = uint256(evidence.parentHash); @@ -169,7 +199,8 @@ library LibProving { inputs[6] = uint256(evidence.signalRoot); inputs[7] = uint256(evidence.graffiti); inputs[8] = (uint256(uint160(evidence.prover)) << 96) - | (uint256(evidence.parentGasUsed) << 64) | (uint256(evidence.gasUsed) << 32); + | (uint256(evidence.parentGasUsed) << 64) + | (uint256(evidence.gasUsed) << 32); // Also hash configs that will be used by circuits inputs[9] = uint256(config.blockMaxGasLimit) << 192 @@ -188,12 +219,19 @@ library LibProving { bytes16(0), bytes16(instance), // left 16 bytes of the given instance bytes16(0), - bytes16(uint128(uint256(instance))), // right 16 bytes of the given instance + bytes16(uint128(uint256(instance))), // right 16 bytes of + // the given instance evidence.proof ) ); - if (!verified || ret.length != 32 || bytes32(ret) != keccak256("taiko")) { + if ( + !verified + // + || ret.length != 32 + // + || bytes32(ret) != keccak256("taiko") + ) { revert L1_INVALID_PROOF(); } } @@ -214,11 +252,17 @@ library LibProving { uint256 blockId, bytes32 parentHash, uint32 parentGasUsed - ) internal view returns (TaikoData.ForkChoice storage fc) { - TaikoData.Block storage blk = state.blocks[blockId % config.ringBufferSize]; + ) + internal + view + returns (TaikoData.ForkChoice storage fc) + { + TaikoData.Block storage blk = + state.blocks[blockId % config.ringBufferSize]; if (blk.blockId != blockId) revert L1_BLOCK_ID(); - uint256 fcId = LibUtils.getForkChoiceId(state, blk, parentHash, parentGasUsed); + uint256 fcId = + LibUtils.getForkChoiceId(state, blk, parentHash, parentGasUsed); if (fcId == 0) revert L1_FORK_CHOICE_NOT_FOUND(); fc = blk.forkChoices[fcId]; } diff --git a/packages/protocol/contracts/L1/libs/LibTokenomics.sol b/packages/protocol/contracts/L1/libs/LibTokenomics.sol deleted file mode 100644 index 7ba81fbc9bc..00000000000 --- a/packages/protocol/contracts/L1/libs/LibTokenomics.sol +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: MIT -// _____ _ _ _ _ -// |_ _|_ _(_) |_____ | | __ _| |__ ___ -// | |/ _` | | / / _ \ | |__/ _` | '_ (_-< -// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/ - -pragma solidity ^0.8.18; - -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {LibMath} from "../../libs/LibMath.sol"; -import {SafeCastUpgradeable} from - "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; -import {TaikoData} from "../TaikoData.sol"; -import {TaikoToken} from "../TaikoToken.sol"; -import {LibFixedPointMath as Math} from "../../thirdparty/LibFixedPointMath.sol"; - -library LibTokenomics { - using LibMath for uint256; - - error L1_INSUFFICIENT_TOKEN(); - - function withdrawTaikoToken( - TaikoData.State storage state, - AddressResolver resolver, - uint256 amount - ) internal { - uint256 balance = state.taikoTokenBalances[msg.sender]; - if (balance < amount) revert L1_INSUFFICIENT_TOKEN(); - - unchecked { - state.taikoTokenBalances[msg.sender] -= amount; - } - - TaikoToken(resolver.resolve("taiko_token", false)).mint(msg.sender, amount); - } - - function depositTaikoToken( - TaikoData.State storage state, - AddressResolver resolver, - uint256 amount - ) internal { - if (amount > 0) { - TaikoToken(resolver.resolve("taiko_token", false)).burn(msg.sender, amount); - state.taikoTokenBalances[msg.sender] += amount; - } - } - - /** - * Get the block reward for a proof - * - * @param state The actual state data - * @param proofTime The actual proof time - * @return reward The reward given for the block proof - */ - function getProofReward(TaikoData.State storage state, uint64 proofTime) - internal - view - returns (uint64) - { - uint64 numBlocksUnverified = state.numBlocks - state.lastVerifiedBlockId - 1; - - if (numBlocksUnverified == 0) { - return 0; - } else { - uint64 totalNumProvingSeconds = - uint64(uint256(numBlocksUnverified) * block.timestamp - state.accProposedAt); - // If block timestamp is equal to state.accProposedAt (not really, - // but theoretically possible) there will be division by 0 error - if (totalNumProvingSeconds == 0) { - totalNumProvingSeconds = 1; - } - - return uint64((uint256(state.accBlockFees) * proofTime) / totalNumProvingSeconds); - } - } - - /** - * Calculate the newProofTimeIssued and blockFee - * - * @param state The actual state data - * @param proofTime The actual proof time - * @return newProofTimeIssued Accumulated proof time - * @return blockFee New block fee - */ - function getNewBlockFeeAndProofTimeIssued(TaikoData.State storage state, uint64 proofTime) - internal - view - returns (uint64 newProofTimeIssued, uint64 blockFee) - { - newProofTimeIssued = (state.proofTimeIssued > state.proofTimeTarget) - ? state.proofTimeIssued - state.proofTimeTarget - : uint64(0); - newProofTimeIssued += proofTime; - - uint256 x = (newProofTimeIssued * Math.SCALING_FACTOR_1E18) - / (state.proofTimeTarget * state.adjustmentQuotient); - - if (Math.MAX_EXP_INPUT <= x) { - x = Math.MAX_EXP_INPUT; - } - - uint256 result = (uint256(Math.exp(int256(x))) / Math.SCALING_FACTOR_1E18) - / (state.proofTimeTarget * state.adjustmentQuotient); - - blockFee = uint64(result.min(type(uint64).max)); - } -} diff --git a/packages/protocol/contracts/L1/libs/LibUtils.sol b/packages/protocol/contracts/L1/libs/LibUtils.sol index e3e4a47cb8f..e92c3e4559d 100644 --- a/packages/protocol/contracts/L1/libs/LibUtils.sol +++ b/packages/protocol/contracts/L1/libs/LibUtils.sol @@ -6,11 +6,11 @@ pragma solidity ^0.8.18; -import {LibMath} from "../../libs/LibMath.sol"; -import {LibEthDepositing} from "./LibEthDepositing.sol"; -import {SafeCastUpgradeable} from +import { LibMath } from "../../libs/LibMath.sol"; +import { LibEthDepositing } from "./LibEthDepositing.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; -import {TaikoData} from "../TaikoData.sol"; +import { TaikoData } from "../TaikoData.sol"; library LibUtils { using LibMath for uint256; @@ -21,7 +21,11 @@ library LibUtils { TaikoData.State storage state, TaikoData.Config memory config, uint256 blockId - ) internal view returns (bool found, TaikoData.Block storage blk) { + ) + internal + view + returns (bool found, TaikoData.Block storage blk) + { uint256 id = blockId == 0 ? state.lastVerifiedBlockId : blockId; blk = state.blocks[id % config.ringBufferSize]; found = (blk.blockId == id && blk.verifiedForkChoiceId != 0); @@ -32,8 +36,15 @@ library LibUtils { TaikoData.Block storage blk, bytes32 parentHash, uint32 parentGasUsed - ) internal view returns (uint256 fcId) { - if (blk.forkChoices[1].key == keyForForkChoice(parentHash, parentGasUsed)) { + ) + internal + view + returns (uint256 fcId) + { + if ( + blk.forkChoices[1].key + == keyForForkChoice(parentHash, parentGasUsed) + ) { fcId = 1; } else { fcId = state.forkChoiceIds[blk.blockId][parentHash][parentGasUsed]; @@ -51,20 +62,20 @@ library LibUtils { { return TaikoData.StateVariables({ blockFee: state.blockFee, - accBlockFees: state.accBlockFees, genesisHeight: state.genesisHeight, genesisTimestamp: state.genesisTimestamp, numBlocks: state.numBlocks, - proofTimeIssued: state.proofTimeIssued, - proofTimeTarget: state.proofTimeTarget, lastVerifiedBlockId: state.lastVerifiedBlockId, - accProposedAt: state.accProposedAt, nextEthDepositToProcess: state.nextEthDepositToProcess, numEthDeposits: uint64(state.ethDeposits.length) }); } - function movingAverage(uint256 maValue, uint256 newValue, uint256 maf) + function movingAverage( + uint256 maValue, + uint256 newValue, + uint256 maf + ) internal pure returns (uint256) @@ -89,11 +100,14 @@ library LibUtils { inputs[1] = uint256(meta.l1Hash); inputs[2] = uint256(meta.mixHash); - inputs[3] = uint256(LibEthDepositing.hashEthDeposits(meta.depositsProcessed)); + inputs[3] = + uint256(LibEthDepositing.hashEthDeposits(meta.depositsProcessed)); inputs[4] = uint256(meta.txListHash); - inputs[5] = (uint256(meta.txListByteStart) << 232) | (uint256(meta.txListByteEnd) << 208) - | (uint256(meta.gasLimit) << 176) | (uint256(uint160(meta.beneficiary)) << 16); + inputs[5] = (uint256(meta.txListByteStart) << 232) + | (uint256(meta.txListByteEnd) << 208) // + | (uint256(meta.gasLimit) << 176) + | (uint256(uint160(meta.beneficiary)) << 16); inputs[6] = (uint256(uint160(meta.treasury)) << 96); @@ -102,7 +116,10 @@ library LibUtils { } } - function keyForForkChoice(bytes32 parentHash, uint32 parentGasUsed) + function keyForForkChoice( + bytes32 parentHash, + uint32 parentGasUsed + ) internal pure returns (bytes32 key) diff --git a/packages/protocol/contracts/L1/libs/LibVerifying.sol b/packages/protocol/contracts/L1/libs/LibVerifying.sol index f69ac1ca510..b8fa75b9e17 100644 --- a/packages/protocol/contracts/L1/libs/LibVerifying.sol +++ b/packages/protocol/contracts/L1/libs/LibVerifying.sol @@ -6,13 +6,12 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {ISignalService} from "../../signal/ISignalService.sol"; -import {LibTokenomics} from "./LibTokenomics.sol"; -import {LibUtils} from "./LibUtils.sol"; -import {SafeCastUpgradeable} from +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { ISignalService } from "../../signal/ISignalService.sol"; +import { LibUtils } from "./LibUtils.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; -import {TaikoData} from "../../L1/TaikoData.sol"; +import { TaikoData } from "../../L1/TaikoData.sol"; library LibVerifying { using SafeCastUpgradeable for uint256; @@ -20,7 +19,9 @@ library LibVerifying { event BlockVerified(uint256 indexed id, bytes32 blockHash, uint64 reward); - event CrossChainSynced(uint256 indexed srcHeight, bytes32 blockHash, bytes32 signalRoot); + event CrossChainSynced( + uint256 indexed srcHeight, bytes32 blockHash, bytes32 signalRoot + ); error L1_INVALID_CONFIG(); @@ -28,23 +29,26 @@ library LibVerifying { TaikoData.State storage state, TaikoData.Config memory config, bytes32 genesisBlockHash, - uint64 initBlockFee, - uint64 initProofTimeTarget, - uint64 initProofTimeIssued, - uint16 adjustmentQuotient - ) internal { + uint64 initBlockFee + ) + internal + { if ( - config.chainId <= 1 || config.maxNumProposedBlocks == 1 + config.chainId <= 1 // + || config.maxNumProposedBlocks == 1 || config.ringBufferSize <= config.maxNumProposedBlocks + 1 - || config.blockMaxGasLimit == 0 || config.maxTransactionsPerBlock == 0 + || config.blockMaxGasLimit == 0 + || config.maxTransactionsPerBlock == 0 || config.maxBytesPerTxList == 0 // EIP-4844 blob size up to 128K - || config.maxBytesPerTxList > 128 * 1024 || config.maxEthDepositsPerBlock == 0 + || config.maxBytesPerTxList > 128 * 1024 + || config.maxEthDepositsPerBlock == 0 || config.maxEthDepositsPerBlock < config.minEthDepositsPerBlock // EIP-4844 blob deleted after 30 days - || config.txListCacheExpiry > 30 * 24 hours || config.ethDepositGas == 0 - || config.ethDepositMaxFee == 0 || config.ethDepositMaxFee >= type(uint96).max - || adjustmentQuotient == 0 || initProofTimeTarget == 0 || initProofTimeIssued == 0 + || config.txListCacheExpiry > 30 * 24 hours + || config.ethDepositGas == 0 // + || config.ethDepositMaxFee == 0 + || config.ethDepositMaxFee >= type(uint96).max ) revert L1_INVALID_CONFIG(); uint64 timeNow = uint64(block.timestamp); @@ -52,9 +56,6 @@ library LibVerifying { state.genesisTimestamp = timeNow; state.blockFee = initBlockFee; - state.proofTimeIssued = initProofTimeIssued; - state.proofTimeTarget = initProofTimeTarget; - state.adjustmentQuotient = adjustmentQuotient; state.numBlocks = 1; TaikoData.Block storage blk = state.blocks[0]; @@ -74,7 +75,9 @@ library LibVerifying { TaikoData.Config memory config, AddressResolver resolver, uint256 maxBlocks - ) internal { + ) + internal + { uint256 i = state.lastVerifiedBlockId; TaikoData.Block storage blk = state.blocks[i % config.ringBufferSize]; @@ -132,12 +135,15 @@ library LibVerifying { } if (config.relaySignalRoot) { - // Send the L2's signal root to the signal service so other TaikoL1 - // deployments, if they share the same signal service, can relay the - // signal to their corresponding TaikoL2 contract. - ISignalService(resolver.resolve("signal_service", false)).sendSignal(signalRoot); + // Send the L2's signal root to the signal service so other + // TaikoL1 deployments, if they share the same signal service, + // can relay the signal to their corresponding TaikoL2 contract. + ISignalService(resolver.resolve("signal_service", false)) + .sendSignal(signalRoot); } - emit CrossChainSynced(state.lastVerifiedBlockId, blockHash, signalRoot); + emit CrossChainSynced( + state.lastVerifiedBlockId, blockHash, signalRoot + ); } } @@ -147,41 +153,18 @@ library LibVerifying { TaikoData.ForkChoice storage fc, uint24 fcId, address systemProver - ) private { + ) + private + { uint64 proofTime; unchecked { proofTime = uint64(fc.provenAt - blk.proposedAt); } - uint64 reward = LibTokenomics.getProofReward(state, proofTime); - - (state.proofTimeIssued, state.blockFee) = - LibTokenomics.getNewBlockFeeAndProofTimeIssued(state, proofTime); - - unchecked { - state.accBlockFees -= reward; - state.accProposedAt -= blk.proposedAt; - } - - // reward the prover - if (reward != 0) { - address prover = fc.prover != address(1) ? fc.prover : systemProver; - - // systemProver may become address(0) after a block is proven - if (prover != address(0)) { - if (state.taikoTokenBalances[prover] == 0) { - // Reduce refund to 1 wei as a penalty if the proposer - // has 0 TKO outstanding balance. - state.taikoTokenBalances[prover] = 1; - } else { - state.taikoTokenBalances[prover] += reward; - } - } - } + uint64 reward; blk.nextForkChoiceId = 1; blk.verifiedForkChoiceId = fcId; - emit BlockVerified(blk.blockId, fc.blockHash, reward); } } diff --git a/packages/protocol/contracts/L2/LibL2Consts.sol b/packages/protocol/contracts/L2/LibL2Consts.sol index fa9cc92c193..4d30c169a2c 100644 --- a/packages/protocol/contracts/L2/LibL2Consts.sol +++ b/packages/protocol/contracts/L2/LibL2Consts.sol @@ -7,5 +7,5 @@ pragma solidity ^0.8.18; library LibL2Consts { - uint64 public constant ANCHOR_GAS_COST = 180000; // owner:david + uint64 public constant ANCHOR_GAS_COST = 180_000; // owner:david } diff --git a/packages/protocol/contracts/L2/TaikoL2.sol b/packages/protocol/contracts/L2/TaikoL2.sol index c7345e9855d..faea39850e5 100644 --- a/packages/protocol/contracts/L2/TaikoL2.sol +++ b/packages/protocol/contracts/L2/TaikoL2.sol @@ -6,14 +6,14 @@ pragma solidity ^0.8.18; -import {EssentialContract} from "../common/EssentialContract.sol"; -import {Proxied} from "../common/Proxied.sol"; -import {ICrossChainSync} from "../common/ICrossChainSync.sol"; -import {LibL2Consts} from "./LibL2Consts.sol"; -import {LibMath} from "../libs/LibMath.sol"; -import {Lib1559Math} from "../libs/Lib1559Math.sol"; -import {TaikoL2Signer} from "./TaikoL2Signer.sol"; -import {SafeCastUpgradeable} from +import { EssentialContract } from "../common/EssentialContract.sol"; +import { Proxied } from "../common/Proxied.sol"; +import { ICrossChainSync } from "../common/ICrossChainSync.sol"; +import { LibL2Consts } from "./LibL2Consts.sol"; +import { LibMath } from "../libs/LibMath.sol"; +import { Lib1559Math } from "../libs/Lib1559Math.sol"; +import { TaikoL2Signer } from "./TaikoL2Signer.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; /// @custom:security-contact hello@taiko.xyz @@ -97,7 +97,10 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { USER-FACING FUNCTIONS //////////////////////////////////////////////////////////////*/ - function init(address _addressManager, EIP1559Params calldata _param1559) + function init( + address _addressManager, + EIP1559Params calldata _param1559 + ) external initializer { @@ -108,8 +111,13 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { if (_param1559.gasIssuedPerSecond != 0) { if ( - _param1559.basefee == 0 || _param1559.gasExcessMax == 0 || _param1559.gasTarget == 0 - || _param1559.ratio2x1x == 0 + _param1559.basefee == 0 + // + || _param1559.gasExcessMax == 0 + // + || _param1559.gasTarget == 0 + // + || _param1559.ratio2x1x == 0 ) revert L2_INVALID_1559_PARAMS(); (uint128 xscale, uint128 yscale) = Lib1559Math.calculateScales({ @@ -154,12 +162,18 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { * This transaction shall be the first transaction in every L2 block. * * @param l1Hash The latest L1 block hash when this block was proposed. - * @param l1SignalRoot The latest value of the L1 "signal service storage root". + * @param l1SignalRoot The latest value of the L1 "signal service storage + * root". * @param l1Height The latest L1 block height when this block was proposed. * @param parentGasUsed the gas used in the parent block. */ - function anchor(bytes32 l1Hash, bytes32 l1SignalRoot, uint64 l1Height, uint64 parentGasUsed) + function anchor( + bytes32 l1Hash, + bytes32 l1SignalRoot, + uint64 l1Height, + uint64 parentGasUsed + ) external { if (msg.sender != GOLDEN_TOUCH_ADDRESS) revert L2_INVALID_SENDER(); @@ -187,22 +201,26 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { EIP1559Config memory config = getEIP1559Config(); if (config.gasIssuedPerSecond != 0) { (basefee, gasExcess) = _calcBasefee( - config, block.timestamp - parentTimestamp, uint64(block.gaslimit), parentGasUsed + config, + block.timestamp - parentTimestamp, + uint64(block.gaslimit), + parentGasUsed ); } // On L2, basefee is not burnt, but sent to a treasury instead. - // The circuits will need to verify the basefee recipient is the designated - // address. + // The circuits will need to verify the basefee recipient is the + // designated address. if (block.basefee != basefee) { revert L2_BASEFEE_MISMATCH(uint64(basefee), uint64(block.basefee)); } parentTimestamp = uint64(block.timestamp); - // We emit this event so circuits can grab its data to verify block variables. - // If plonk lookup table already has all these data, we can still use this - // event for debugging purpose. + // We emit this event so circuits can grab its data to verify block + // variables. + // If plonk lookup table already has all these data, we can still use + // this event for debugging purpose. emit Anchored({ number: uint64(block.number), basefee: uint64(basefee), @@ -215,20 +233,36 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { }); } - function getBasefee(uint32 timeSinceParent, uint64 gasLimit, uint64 parentGasUsed) + function getBasefee( + uint32 timeSinceParent, + uint64 gasLimit, + uint64 parentGasUsed + ) public view returns (uint256 _basefee) { - (_basefee,) = _calcBasefee(getEIP1559Config(), timeSinceParent, gasLimit, parentGasUsed); + (_basefee,) = _calcBasefee( + getEIP1559Config(), timeSinceParent, gasLimit, parentGasUsed + ); } - function getCrossChainBlockHash(uint256 number) public view override returns (bytes32) { + function getCrossChainBlockHash(uint256 number) + public + view + override + returns (bytes32) + { uint256 _number = number == 0 ? latestSyncedL1Height : number; return _l1VerifiedBlocks[_number].blockHash; } - function getCrossChainSignalRoot(uint256 number) public view override returns (bytes32) { + function getCrossChainSignalRoot(uint256 number) + public + view + override + returns (bytes32) + { uint256 _number = number == 0 ? latestSyncedL1Height : number; return _l1VerifiedBlocks[_number].signalRoot; } @@ -245,7 +279,12 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { /// @dev Overide this funciton to return a constant EIP1559Config object // to avoid reading from storage to reduce gas cost. - function getEIP1559Config() public view virtual returns (EIP1559Config memory) { + function getEIP1559Config() + public + view + virtual + returns (EIP1559Config memory) + { return _eip1559Config; } @@ -285,10 +324,15 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { uint256 timeSinceParent, uint64 gasLimit, uint64 parentGasUsed - ) private view returns (uint256 _basefee, uint64 _gasExcess) { + ) + private + view + returns (uint256 _basefee, uint64 _gasExcess) + { // Very important to cap _gasExcess uint64 unchecked { - uint64 parentGasUsedNet = parentGasUsed > LibL2Consts.ANCHOR_GAS_COST + uint64 parentGasUsedNet = parentGasUsed + > LibL2Consts.ANCHOR_GAS_COST ? parentGasUsed - LibL2Consts.ANCHOR_GAS_COST : 0; @@ -311,4 +355,4 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { } } -contract ProxiedTaikoL2 is Proxied, TaikoL2 {} +contract ProxiedTaikoL2 is Proxied, TaikoL2 { } diff --git a/packages/protocol/contracts/L2/TaikoL2Signer.sol b/packages/protocol/contracts/L2/TaikoL2Signer.sol index 809acfdd851..6a14eadab1d 100644 --- a/packages/protocol/contracts/L2/TaikoL2Signer.sol +++ b/packages/protocol/contracts/L2/TaikoL2Signer.sol @@ -6,22 +6,26 @@ pragma solidity ^0.8.18; -import {LibUint512Math} from "../libs/LibUint512Math.sol"; +import { LibUint512Math } from "../libs/LibUint512Math.sol"; abstract contract TaikoL2Signer { - address public constant GOLDEN_TOUCH_ADDRESS = 0x0000777735367b36bC9B61C50022d9D0700dB4Ec; + address public constant GOLDEN_TOUCH_ADDRESS = + 0x0000777735367b36bC9B61C50022d9D0700dB4Ec; uint256 public constant GOLDEN_TOUCH_PRIVATEKEY = 0x92954368afd3caa1f3ce3ead0069c1af414054aefe1ef9aeacc1bf426222ce38; - uint256 private constant GX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798; - uint256 private constant GY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8; + uint256 private constant GX = + 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798; + uint256 private constant GY = + 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8; uint256 private constant GX2 = 0xc6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5; uint256 private constant GY2 = 0x1ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a; - uint256 private constant N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141; + uint256 private constant N = + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141; // ( // uint256 GX_MUL_GOLDEN_TOUCH_PRIVATEKEY_LOW, @@ -47,7 +51,10 @@ abstract contract TaikoL2Signer { error L2_INVALID_GOLDEN_TOUCH_K(); - function signAnchor(bytes32 digest, uint8 k) + function signAnchor( + bytes32 digest, + uint8 k + ) public view returns (uint8 v, uint256 r, uint256 s) @@ -56,18 +63,22 @@ abstract contract TaikoL2Signer { r = k == 1 ? GX : GX2; - uint256 low256 = - k == 1 ? GX_MUL_GOLDEN_TOUCH_PRIVATEKEY_LOW : GX2_MUL_GOLDEN_TOUCH_PRIVATEKEY_LOW; + uint256 low256 = k == 1 + ? GX_MUL_GOLDEN_TOUCH_PRIVATEKEY_LOW + : GX2_MUL_GOLDEN_TOUCH_PRIVATEKEY_LOW; - uint256 high256 = - k == 1 ? GX_MUL_GOLDEN_TOUCH_PRIVATEKEY_HIGH : GX2_MUL_GOLDEN_TOUCH_PRIVATEKEY_HIGH; + uint256 high256 = k == 1 + ? GX_MUL_GOLDEN_TOUCH_PRIVATEKEY_HIGH + : GX2_MUL_GOLDEN_TOUCH_PRIVATEKEY_HIGH; - (low256, high256) = LibUint512Math.add(low256, high256, uint256(digest), 0); + (low256, high256) = + LibUint512Math.add(low256, high256, uint256(digest), 0); if (k == 1) { s = _expmod(low256, high256, 1, N); } else { - (low256, high256) = LibUint512Math.mul(K_2_INVM_N, _expmod(low256, high256, 1, N)); + (low256, high256) = + LibUint512Math.mul(K_2_INVM_N, _expmod(low256, high256, 1, N)); s = _expmod(low256, high256, 1, N); } @@ -77,7 +88,12 @@ abstract contract TaikoL2Signer { } } - function _expmod(uint256 baseLow, uint256 baseHigh, uint256 e, uint256 m) + function _expmod( + uint256 baseLow, + uint256 baseHigh, + uint256 e, + uint256 m + ) private view returns (uint256 o) @@ -94,7 +110,9 @@ abstract contract TaikoL2Signer { mstore(add(p, 0xa0), e) // Exponent mstore(add(p, 0xc0), m) // Modulus - if iszero(staticcall(sub(gas(), 2000), 0x05, p, 0xe0, p, 0x20)) { revert(0, 0) } + if iszero(staticcall(sub(gas(), 2000), 0x05, p, 0xe0, p, 0x20)) { + revert(0, 0) + } // data o := mload(p) } diff --git a/packages/protocol/contracts/bridge/Bridge.sol b/packages/protocol/contracts/bridge/Bridge.sol index a7de3ef3d99..b0c315fd139 100644 --- a/packages/protocol/contracts/bridge/Bridge.sol +++ b/packages/protocol/contracts/bridge/Bridge.sol @@ -6,17 +6,17 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../common/AddressResolver.sol"; -import {EssentialContract} from "../common/EssentialContract.sol"; -import {Proxied} from "../common/Proxied.sol"; -import {IBridge} from "./IBridge.sol"; -import {BridgeErrors} from "./BridgeErrors.sol"; -import {LibBridgeData} from "./libs/LibBridgeData.sol"; -import {LibBridgeProcess} from "./libs/LibBridgeProcess.sol"; -import {LibBridgeRelease} from "./libs/LibBridgeRelease.sol"; -import {LibBridgeRetry} from "./libs/LibBridgeRetry.sol"; -import {LibBridgeSend} from "./libs/LibBridgeSend.sol"; -import {LibBridgeStatus} from "./libs/LibBridgeStatus.sol"; +import { AddressResolver } from "../common/AddressResolver.sol"; +import { EssentialContract } from "../common/EssentialContract.sol"; +import { Proxied } from "../common/Proxied.sol"; +import { IBridge } from "./IBridge.sol"; +import { BridgeErrors } from "./BridgeErrors.sol"; +import { LibBridgeData } from "./libs/LibBridgeData.sol"; +import { LibBridgeProcess } from "./libs/LibBridgeProcess.sol"; +import { LibBridgeRelease } from "./libs/LibBridgeRelease.sol"; +import { LibBridgeRetry } from "./libs/LibBridgeRetry.sol"; +import { LibBridgeSend } from "./libs/LibBridgeSend.sol"; +import { LibBridgeStatus } from "./libs/LibBridgeStatus.sol"; /** * Bridge contract which is deployed on both L1 and L2. Mostly a thin wrapper @@ -38,7 +38,9 @@ contract Bridge is EssentialContract, IBridge, BridgeErrors { //////////////////////////////////////////////////////////////*/ event MessageStatusChanged( - bytes32 indexed msgHash, LibBridgeStatus.MessageStatus status, address transactor + bytes32 indexed msgHash, + LibBridgeStatus.MessageStatus status, + address transactor ); event DestChainEnabled(uint256 indexed chainId, bool enabled); @@ -50,7 +52,8 @@ contract Bridge is EssentialContract, IBridge, BridgeErrors { /// Allow Bridge to receive ETH from the TaikoL1, TokenVault or EtherVault. receive() external payable { if ( - msg.sender != resolve("token_vault", true) && msg.sender != resolve("ether_vault", true) + msg.sender != resolve("token_vault", true) + && msg.sender != resolve("ether_vault", true) && msg.sender != resolve("taiko", true) && msg.sender != owner() ) { revert B_CANNOT_RECEIVE(); @@ -75,7 +78,10 @@ contract Bridge is EssentialContract, IBridge, BridgeErrors { }); } - function releaseEther(IBridge.Message calldata message, bytes calldata proof) + function releaseEther( + IBridge.Message calldata message, + bytes calldata proof + ) external nonReentrant { @@ -87,7 +93,13 @@ contract Bridge is EssentialContract, IBridge, BridgeErrors { }); } - function processMessage(Message calldata message, bytes calldata proof) external nonReentrant { + function processMessage( + Message calldata message, + bytes calldata proof + ) + external + nonReentrant + { return LibBridgeProcess.processMessage({ state: _state, resolver: AddressResolver(this), @@ -96,7 +108,13 @@ contract Bridge is EssentialContract, IBridge, BridgeErrors { }); } - function retryMessage(Message calldata message, bool isLastAttempt) external nonReentrant { + function retryMessage( + Message calldata message, + bool isLastAttempt + ) + external + nonReentrant + { return LibBridgeRetry.retryMessage({ state: _state, resolver: AddressResolver(this), @@ -105,11 +123,20 @@ contract Bridge is EssentialContract, IBridge, BridgeErrors { }); } - function isMessageSent(bytes32 msgHash) public view virtual returns (bool) { + function isMessageSent(bytes32 msgHash) + public + view + virtual + returns (bool) + { return LibBridgeSend.isMessageSent(AddressResolver(this), msgHash); } - function isMessageReceived(bytes32 msgHash, uint256 srcChainId, bytes calldata proof) + function isMessageReceived( + bytes32 msgHash, + uint256 srcChainId, + bytes calldata proof + ) public view virtual @@ -124,7 +151,11 @@ contract Bridge is EssentialContract, IBridge, BridgeErrors { }); } - function isMessageFailed(bytes32 msgHash, uint256 destChainId, bytes calldata proof) + function isMessageFailed( + bytes32 msgHash, + uint256 destChainId, + bytes calldata proof + ) public view virtual @@ -156,17 +187,31 @@ contract Bridge is EssentialContract, IBridge, BridgeErrors { return _state.etherReleased[msgHash]; } - function isDestChainEnabled(uint256 _chainId) public view returns (bool enabled) { - (enabled,) = LibBridgeSend.isDestChainEnabled(AddressResolver(this), _chainId); + function isDestChainEnabled(uint256 _chainId) + public + view + returns (bool enabled) + { + (enabled,) = + LibBridgeSend.isDestChainEnabled(AddressResolver(this), _chainId); } - function hashMessage(Message calldata message) public pure override returns (bytes32) { + function hashMessage(Message calldata message) + public + pure + override + returns (bytes32) + { return LibBridgeData.hashMessage(message); } - function getMessageStatusSlot(bytes32 msgHash) public pure returns (bytes32) { + function getMessageStatusSlot(bytes32 msgHash) + public + pure + returns (bytes32) + { return LibBridgeStatus.getMessageStatusSlot(msgHash); } } -contract ProxiedBridge is Proxied, Bridge {} +contract ProxiedBridge is Proxied, Bridge { } diff --git a/packages/protocol/contracts/bridge/BridgedERC20.sol b/packages/protocol/contracts/bridge/BridgedERC20.sol index 9f8ffc7ed10..51fd0b44725 100644 --- a/packages/protocol/contracts/bridge/BridgedERC20.sol +++ b/packages/protocol/contracts/bridge/BridgedERC20.sol @@ -10,12 +10,12 @@ import { IERC20Upgradeable, ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; -import {IERC20MetadataUpgradeable} from +import { IERC20MetadataUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; -import {EssentialContract} from "../common/EssentialContract.sol"; -import {Proxied} from "../common/Proxied.sol"; -import {BridgeErrors} from "./BridgeErrors.sol"; +import { EssentialContract } from "../common/EssentialContract.sol"; +import { Proxied } from "../common/Proxied.sol"; +import { BridgeErrors } from "./BridgeErrors.sol"; /// @custom:security-contact hello@taiko.xyz contract BridgedERC20 is @@ -55,35 +55,60 @@ contract BridgedERC20 is uint8 _decimals, string memory _symbol, string memory _name - ) external initializer { + ) + external + initializer + { if ( - _srcToken == address(0) || _srcChainId == 0 || _srcChainId == block.chainid - || bytes(_symbol).length == 0 || bytes(_name).length == 0 + _srcToken == address(0) + // + || _srcChainId == 0 + // + || _srcChainId == block.chainid + // + || bytes(_symbol).length == 0 + // + || bytes(_name).length == 0 ) { revert B_INIT_PARAM_ERROR(); } EssentialContract._init(_addressManager); - ERC20Upgradeable.__ERC20_init({name_: _name, symbol_: _symbol}); + ERC20Upgradeable.__ERC20_init({ name_: _name, symbol_: _symbol }); srcToken = _srcToken; srcChainId = _srcChainId; srcDecimals = _decimals; } /// @dev only a TokenVault can call this function - function bridgeMintTo(address account, uint256 amount) public onlyFromNamed("token_vault") { + function bridgeMintTo( + address account, + uint256 amount + ) + public + onlyFromNamed("token_vault") + { _mint(account, amount); emit BridgeMint(account, amount); } /// @dev only a TokenVault can call this function - function bridgeBurnFrom(address account, uint256 amount) public onlyFromNamed("token_vault") { + function bridgeBurnFrom( + address account, + uint256 amount + ) + public + onlyFromNamed("token_vault") + { _burn(account, amount); emit BridgeBurn(account, amount); } /// @dev any address can call this // caller must have at least amount to call this - function transfer(address to, uint256 amount) + function transfer( + address to, + uint256 amount + ) public override(ERC20Upgradeable, IERC20Upgradeable) returns (bool) @@ -97,7 +122,11 @@ contract BridgedERC20 is /// @dev any address can call this // caller must have allowance of at least 'amount' // for 'from's tokens. - function transferFrom(address from, address to, uint256 amount) + function transferFrom( + address from, + address to, + uint256 amount + ) public override(ERC20Upgradeable, IERC20Upgradeable) returns (bool) @@ -124,4 +153,4 @@ contract BridgedERC20 is } } -contract ProxiedBridgedERC20 is Proxied, BridgedERC20 {} +contract ProxiedBridgedERC20 is Proxied, BridgedERC20 { } diff --git a/packages/protocol/contracts/bridge/EtherVault.sol b/packages/protocol/contracts/bridge/EtherVault.sol index 982a9aab84b..a225bf85915 100644 --- a/packages/protocol/contracts/bridge/EtherVault.sol +++ b/packages/protocol/contracts/bridge/EtherVault.sol @@ -6,13 +6,14 @@ pragma solidity ^0.8.18; -import {SafeERC20Upgradeable} from +import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; -import {Create2Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/Create2Upgradeable.sol"; -import {EssentialContract} from "../common/EssentialContract.sol"; -import {Proxied} from "../common/Proxied.sol"; -import {LibAddress} from "../libs/LibAddress.sol"; -import {BridgeErrors} from "./BridgeErrors.sol"; +import { Create2Upgradeable } from + "@openzeppelin/contracts-upgradeable/utils/Create2Upgradeable.sol"; +import { EssentialContract } from "../common/EssentialContract.sol"; +import { Proxied } from "../common/Proxied.sol"; +import { LibAddress } from "../libs/LibAddress.sol"; +import { BridgeErrors } from "./BridgeErrors.sol"; /** * @custom:security-contact hello@taiko.xyz @@ -81,7 +82,14 @@ contract EtherVault is EssentialContract, BridgeErrors { * @param recipient Address to receive Ether. * @param amount Amount of ether to send. */ - function releaseEther(address recipient, uint256 amount) public onlyAuthorized nonReentrant { + function releaseEther( + address recipient, + uint256 amount + ) + public + onlyAuthorized + nonReentrant + { if (recipient == address(0)) { revert B_EV_DO_NOT_BURN(); } @@ -111,4 +119,4 @@ contract EtherVault is EssentialContract, BridgeErrors { } } -contract ProxiedEtherVault is Proxied, EtherVault {} +contract ProxiedEtherVault is Proxied, EtherVault { } diff --git a/packages/protocol/contracts/bridge/IBridge.sol b/packages/protocol/contracts/bridge/IBridge.sol index c369fcb13a9..5b0c7f1b1c7 100644 --- a/packages/protocol/contracts/bridge/IBridge.sol +++ b/packages/protocol/contracts/bridge/IBridge.sol @@ -53,11 +53,18 @@ interface IBridge { /// Sends a message to the destination chain and takes custody /// of Ether required in this contract. All extra Ether will be refunded. - function sendMessage(Message memory message) external payable returns (bytes32 msgHash); + function sendMessage(Message memory message) + external + payable + returns (bytes32 msgHash); // Release Ether with a proof that the message processing on the destination // chain has been failed. - function releaseEther(IBridge.Message calldata message, bytes calldata proof) external; + function releaseEther( + IBridge.Message calldata message, + bytes calldata proof + ) + external; /// Checks if a msgHash has been stored on the bridge contract by the /// current address. @@ -65,13 +72,21 @@ interface IBridge { /// Checks if a msgHash has been received on the destination chain and /// sent by the src chain. - function isMessageReceived(bytes32 msgHash, uint256 srcChainId, bytes calldata proof) + function isMessageReceived( + bytes32 msgHash, + uint256 srcChainId, + bytes calldata proof + ) external view returns (bool); /// Checks if a msgHash has been failed on the destination chain. - function isMessageFailed(bytes32 msgHash, uint256 destChainId, bytes calldata proof) + function isMessageFailed( + bytes32 msgHash, + uint256 destChainId, + bytes calldata proof + ) external view returns (bool); @@ -79,5 +94,8 @@ interface IBridge { /// Returns the bridge state context. function context() external view returns (Context memory context); - function hashMessage(IBridge.Message calldata message) external pure returns (bytes32); + function hashMessage(IBridge.Message calldata message) + external + pure + returns (bytes32); } diff --git a/packages/protocol/contracts/bridge/TokenVault.sol b/packages/protocol/contracts/bridge/TokenVault.sol index 7dca4c021c2..ab9e6cf1294 100644 --- a/packages/protocol/contracts/bridge/TokenVault.sol +++ b/packages/protocol/contracts/bridge/TokenVault.sol @@ -10,15 +10,16 @@ import { IERC20Upgradeable, ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; -import {SafeERC20Upgradeable} from +import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; -import {Create2Upgradeable} from "@openzeppelin/contracts-upgradeable/utils/Create2Upgradeable.sol"; -import {EssentialContract} from "../common/EssentialContract.sol"; -import {Proxied} from "../common/Proxied.sol"; -import {TaikoToken} from "../L1/TaikoToken.sol"; -import {BridgedERC20} from "./BridgedERC20.sol"; -import {IBridge} from "./IBridge.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import { Create2Upgradeable } from + "@openzeppelin/contracts-upgradeable/utils/Create2Upgradeable.sol"; +import { EssentialContract } from "../common/EssentialContract.sol"; +import { Proxied } from "../common/Proxied.sol"; +import { TaikoToken } from "../L1/TaikoToken.sol"; +import { BridgedERC20 } from "./BridgedERC20.sol"; +import { IBridge } from "./IBridge.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; /** * This vault holds all ERC20 tokens (but not Ether) that users have deposited. @@ -56,15 +57,19 @@ contract TokenVault is EssentialContract { mapping(address tokenAddress => bool isBridged) public isBridgedToken; // Mappings from bridged tokens to their canonical tokens. - mapping(address bridgedAddress => CanonicalERC20 canonicalErc20) public bridgedToCanonical; + mapping(address bridgedAddress => CanonicalERC20 canonicalErc20) public + bridgedToCanonical; // Mappings from canonical tokens to their bridged tokens. // Also storing chainId for tokens across other chains aside from Ethereum. - mapping(uint256 chainId => mapping(address canonicalAddress => address bridgedAddress)) public - canonicalToBridged; + mapping( + uint256 chainId + => mapping(address canonicalAddress => address bridgedAddress) + ) public canonicalToBridged; // Tracks the token and amount associated with a message hash. - mapping(bytes32 msgHash => MessageDeposit messageDeposit) public messageDeposits; + mapping(bytes32 msgHash => MessageDeposit messageDeposit) public + messageDeposits; uint256[47] private __gap; @@ -99,7 +104,10 @@ contract TokenVault is EssentialContract { ); event ERC20Released( - bytes32 indexed msgHash, address indexed from, address token, uint256 amount + bytes32 indexed msgHash, + address indexed from, + address token, + uint256 amount ); event ERC20Received( @@ -156,8 +164,14 @@ contract TokenVault is EssentialContract { uint256 processingFee, address refundAddress, string memory memo - ) external payable nonReentrant { - if (to == address(0) || to == resolve(destChainId, "token_vault", false)) { + ) + external + payable + nonReentrant + { + if ( + to == address(0) || to == resolve(destChainId, "token_vault", false) + ) { revert TOKENVAULT_INVALID_TO(); } @@ -197,7 +211,11 @@ contract TokenVault is EssentialContract { message.owner = msg.sender; message.to = resolve(destChainId, "token_vault", false); message.data = abi.encodeWithSelector( - TokenVault.receiveERC20.selector, canonicalToken, message.owner, to, _amount + TokenVault.receiveERC20.selector, + canonicalToken, + message.owner, + to, + _amount ); message.gasLimit = gasLimit; message.processingFee = processingFee; @@ -205,7 +223,9 @@ contract TokenVault is EssentialContract { message.refundAddress = refundAddress; message.memo = memo; - bytes32 msgHash = IBridge(resolve("bridge", false)).sendMessage{value: msg.value}(message); + bytes32 msgHash = IBridge(resolve("bridge", false)).sendMessage{ + value: msg.value + }(message); // record the deposit for this message messageDeposits[msgHash] = MessageDeposit(token, _amount); @@ -229,7 +249,10 @@ contract TokenVault is EssentialContract { * @param proof The proof from the destination chain to show the message * has failed. */ - function releaseERC20(IBridge.Message calldata message, bytes calldata proof) + function releaseERC20( + IBridge.Message calldata message, + bytes calldata proof + ) external nonReentrant { @@ -258,7 +281,12 @@ contract TokenVault is EssentialContract { } } - emit ERC20Released({msgHash: msgHash, from: message.owner, token: token, amount: amount}); + emit ERC20Released({ + msgHash: msgHash, + from: message.owner, + token: token, + amount: amount + }); } /** @@ -277,7 +305,11 @@ contract TokenVault is EssentialContract { address from, address to, uint256 amount - ) external nonReentrant onlyFromNamed("bridge") { + ) + external + nonReentrant + onlyFromNamed("bridge") + { IBridge.Context memory ctx = IBridge(msg.sender).context(); if (ctx.sender != resolve(ctx.srcChainId, "token_vault", false)) { revert TOKENVAULT_INVALID_SENDER(); @@ -310,7 +342,8 @@ contract TokenVault is EssentialContract { private returns (address) { - address token = canonicalToBridged[canonicalToken.chainId][canonicalToken.addr]; + address token = + canonicalToBridged[canonicalToken.chainId][canonicalToken.addr]; return token != address(0) ? token : _deployBridgedToken(canonicalToken); } @@ -327,7 +360,8 @@ contract TokenVault is EssentialContract { 0, // amount of Ether to send keccak256( bytes.concat( - bytes32(canonicalToken.chainId), bytes32(uint256(uint160(canonicalToken.addr))) + bytes32(canonicalToken.chainId), + bytes32(uint256(uint160(canonicalToken.addr))) ) ), type(BridgedERC20).creationCode @@ -349,7 +383,8 @@ contract TokenVault is EssentialContract { isBridgedToken[bridgedToken] = true; bridgedToCanonical[bridgedToken] = canonicalToken; - canonicalToBridged[canonicalToken.chainId][canonicalToken.addr] = bridgedToken; + canonicalToBridged[canonicalToken.chainId][canonicalToken.addr] = + bridgedToken; emit BridgedERC20Deployed({ srcChainId: canonicalToken.chainId, @@ -362,4 +397,4 @@ contract TokenVault is EssentialContract { } } -contract ProxiedTokenVault is Proxied, TokenVault {} +contract ProxiedTokenVault is Proxied, TokenVault { } diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeData.sol b/packages/protocol/contracts/bridge/libs/LibBridgeData.sol index 00942328984..13adfb40d8c 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeData.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeData.sol @@ -6,11 +6,11 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {BlockHeader} from "../../libs/LibBlockHeader.sol"; -import {IBridge} from "../IBridge.sol"; -import {LibAddress} from "../../libs/LibAddress.sol"; -import {LibMath} from "../../libs/LibMath.sol"; +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { BlockHeader } from "../../libs/LibBlockHeader.sol"; +import { IBridge } from "../IBridge.sol"; +import { LibAddress } from "../../libs/LibAddress.sol"; +import { LibMath } from "../../libs/LibMath.sol"; /** * Stores message metadata on the Bridge. @@ -30,7 +30,8 @@ library LibBridgeData { bytes32 internal constant MESSAGE_HASH_PLACEHOLDER = bytes32(uint256(1)); uint256 internal constant CHAINID_PLACEHOLDER = type(uint256).max; - address internal constant SRC_CHAIN_SENDER_PLACEHOLDER = address(uint160(uint256(1))); + address internal constant SRC_CHAIN_SENDER_PLACEHOLDER = + address(uint160(uint256(1))); // Note: These events must match the ones defined in Bridge.sol. event MessageSent(bytes32 indexed msgHash, IBridge.Message message); @@ -39,7 +40,11 @@ library LibBridgeData { /** * @return msgHash The keccak256 hash of the message. */ - function hashMessage(IBridge.Message memory message) internal pure returns (bytes32) { + function hashMessage(IBridge.Message memory message) + internal + pure + returns (bytes32) + { return keccak256(abi.encode(message)); } } diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeInvoke.sol b/packages/protocol/contracts/bridge/libs/LibBridgeInvoke.sol index 046da569b9a..68cf3e88f3c 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeInvoke.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeInvoke.sol @@ -6,9 +6,9 @@ pragma solidity ^0.8.18; -import {IBridge} from "../IBridge.sol"; -import {LibAddress} from "../../libs/LibAddress.sol"; -import {LibBridgeData} from "./LibBridgeData.sol"; +import { IBridge } from "../IBridge.sol"; +import { LibAddress } from "../../libs/LibAddress.sol"; +import { LibBridgeData } from "./LibBridgeData.sol"; library LibBridgeInvoke { using LibAddress for address; @@ -25,7 +25,10 @@ library LibBridgeInvoke { IBridge.Message calldata message, bytes32 msgHash, uint256 gasLimit - ) internal returns (bool success) { + ) + internal + returns (bool success) + { if (gasLimit == 0) { revert B_GAS_LIMIT(); } @@ -36,7 +39,9 @@ library LibBridgeInvoke { srcChainId: message.srcChainId }); - (success,) = message.to.call{value: message.callValue, gas: gasLimit}(message.data); + (success,) = message.to.call{ value: message.callValue, gas: gasLimit }( + message.data + ); state.ctx = IBridge.Context({ msgHash: LibBridgeData.MESSAGE_HASH_PLACEHOLDER, diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol b/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol index 6597e9885cc..2d0b771092c 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeProcess.sol @@ -6,15 +6,15 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {EtherVault} from "../EtherVault.sol"; -import {IBridge} from "../IBridge.sol"; -import {ISignalService} from "../../signal/ISignalService.sol"; -import {LibAddress} from "../../libs/LibAddress.sol"; -import {LibBridgeData} from "./LibBridgeData.sol"; -import {LibBridgeInvoke} from "./LibBridgeInvoke.sol"; -import {LibBridgeStatus} from "./LibBridgeStatus.sol"; -import {LibMath} from "../../libs/LibMath.sol"; +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { EtherVault } from "../EtherVault.sol"; +import { IBridge } from "../IBridge.sol"; +import { ISignalService } from "../../signal/ISignalService.sol"; +import { LibAddress } from "../../libs/LibAddress.sol"; +import { LibBridgeData } from "./LibBridgeData.sol"; +import { LibBridgeInvoke } from "./LibBridgeInvoke.sol"; +import { LibBridgeStatus } from "./LibBridgeStatus.sol"; +import { LibMath } from "../../libs/LibMath.sol"; /** * Process bridge messages on the destination chain. @@ -48,8 +48,11 @@ library LibBridgeProcess { AddressResolver resolver, IBridge.Message calldata message, bytes calldata proof - ) internal { - // If the gas limit is set to zero, only the owner can process the message. + ) + internal + { + // If the gas limit is set to zero, only the owner can process the + // message. if (message.gasLimit == 0 && msg.sender != message.owner) { revert B_FORBIDDEN(); } @@ -61,14 +64,19 @@ library LibBridgeProcess { // The message status must be "NEW"; "RETRIABLE" is handled in // LibBridgeRetry.sol. bytes32 msgHash = message.hashMessage(); - if (LibBridgeStatus.getMessageStatus(msgHash) != LibBridgeStatus.MessageStatus.NEW) { + if ( + LibBridgeStatus.getMessageStatus(msgHash) + != LibBridgeStatus.MessageStatus.NEW + ) { revert B_STATUS_MISMATCH(); } // Message must have been "received" on the destChain (current chain) - address srcBridge = resolver.resolve(message.srcChainId, "bridge", false); + address srcBridge = + resolver.resolve(message.srcChainId, "bridge", false); if ( - !ISignalService(resolver.resolve("signal_service", false)).isSignalReceived({ + !ISignalService(resolver.resolve("signal_service", false)) + .isSignalReceived({ srcChainId: message.srcChainId, app: srcBridge, signal: msgHash, @@ -78,7 +86,8 @@ library LibBridgeProcess { revert B_SIGNAL_NOT_RECEIVED(); } - uint256 allValue = message.depositValue + message.callValue + message.processingFee; + uint256 allValue = + message.depositValue + message.callValue + message.processingFee; // We retrieve the necessary ether from EtherVault if receiving on // Taiko, otherwise it is already available in this Bridge. address ethVault = resolver.resolve("ether_vault", true); @@ -92,7 +101,8 @@ library LibBridgeProcess { LibBridgeStatus.MessageStatus status; uint256 refundAmount; - // if the user is sending to the bridge or zero-address, just process as DONE + // if the user is sending to the bridge or zero-address, just process as + // DONE // and refund the owner if (message.to == address(this) || message.to == address(0)) { // For these two special addresses, the call will not be actually @@ -101,7 +111,8 @@ library LibBridgeProcess { refundAmount = message.callValue; } else { // use the specified message gas limit if not called by the owner - uint256 gasLimit = msg.sender == message.owner ? gasleft() : message.gasLimit; + uint256 gasLimit = + msg.sender == message.owner ? gasleft() : message.gasLimit; bool success = LibBridgeInvoke.invokeMessageCall({ state: state, @@ -121,8 +132,9 @@ library LibBridgeProcess { // Mark the status as DONE or RETRIABLE. LibBridgeStatus.updateMessageStatus(msgHash, status); - address refundAddress = - message.refundAddress == address(0) ? message.owner : message.refundAddress; + address refundAddress = message.refundAddress == address(0) + ? message.owner + : message.refundAddress; // if sender is the refundAddress if (msg.sender == refundAddress) { diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeRelease.sol b/packages/protocol/contracts/bridge/libs/LibBridgeRelease.sol index b01beb3df06..5efd2f47fef 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeRelease.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeRelease.sol @@ -6,11 +6,11 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {EtherVault} from "../EtherVault.sol"; -import {IBridge} from "../IBridge.sol"; -import {LibBridgeData} from "./LibBridgeData.sol"; -import {LibBridgeStatus} from "./LibBridgeStatus.sol"; +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { EtherVault } from "../EtherVault.sol"; +import { IBridge } from "../IBridge.sol"; +import { LibBridgeData } from "./LibBridgeData.sol"; +import { LibBridgeStatus } from "./LibBridgeStatus.sol"; library LibBridgeRelease { using LibBridgeData for IBridge.Message; @@ -33,7 +33,9 @@ library LibBridgeRelease { AddressResolver resolver, IBridge.Message calldata message, bytes calldata proof - ) internal { + ) + internal + { if (message.owner == address(0)) { revert B_OWNER_IS_NULL(); } @@ -48,7 +50,11 @@ library LibBridgeRelease { revert B_ETHER_RELEASED_ALREADY(); } - if (!LibBridgeStatus.isMessageFailed(resolver, msgHash, message.destChainId, proof)) { + if ( + !LibBridgeStatus.isMessageFailed( + resolver, msgHash, message.destChainId, proof + ) + ) { revert B_MSG_NOT_FAILED(); } @@ -60,10 +66,12 @@ library LibBridgeRelease { address ethVault = resolver.resolve("ether_vault", true); // if on Taiko if (ethVault != address(0)) { - EtherVault(payable(ethVault)).releaseEther(message.owner, releaseAmount); + EtherVault(payable(ethVault)).releaseEther( + message.owner, releaseAmount + ); } else { // if on Ethereum - (bool success,) = message.owner.call{value: releaseAmount}(""); + (bool success,) = message.owner.call{ value: releaseAmount }(""); if (!success) { revert B_FAILED_TRANSFER(); } diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeRetry.sol b/packages/protocol/contracts/bridge/libs/LibBridgeRetry.sol index bbee7dd1c41..c2f427baf5d 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeRetry.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeRetry.sol @@ -6,13 +6,13 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {EtherVault} from "../EtherVault.sol"; -import {IBridge} from "../IBridge.sol"; -import {LibAddress} from "../../libs/LibAddress.sol"; -import {LibBridgeData} from "./LibBridgeData.sol"; -import {LibBridgeInvoke} from "./LibBridgeInvoke.sol"; -import {LibBridgeStatus} from "./LibBridgeStatus.sol"; +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { EtherVault } from "../EtherVault.sol"; +import { IBridge } from "../IBridge.sol"; +import { LibAddress } from "../../libs/LibAddress.sol"; +import { LibBridgeData } from "./LibBridgeData.sol"; +import { LibBridgeInvoke } from "./LibBridgeInvoke.sol"; +import { LibBridgeStatus } from "./LibBridgeStatus.sol"; /** * Retry bridge messages. @@ -45,15 +45,20 @@ library LibBridgeRetry { AddressResolver resolver, IBridge.Message calldata message, bool isLastAttempt - ) internal { - // If the gasLimit is not set to 0 or isLastAttempt is true, the + ) + internal + { + // If the gasLimit is set to 0 or isLastAttempt is true, the // address calling this function must be message.owner. if (message.gasLimit == 0 || isLastAttempt) { if (msg.sender != message.owner) revert B_DENIED(); } bytes32 msgHash = message.hashMessage(); - if (LibBridgeStatus.getMessageStatus(msgHash) != LibBridgeStatus.MessageStatus.RETRIABLE) { + if ( + LibBridgeStatus.getMessageStatus(msgHash) + != LibBridgeStatus.MessageStatus.RETRIABLE + ) { revert B_MSG_NON_RETRIABLE(); } @@ -65,7 +70,8 @@ library LibBridgeRetry { // successful invocation if ( LibBridgeInvoke - // The message.gasLimit only apply for processMessage, if it fails + // The message.gasLimit only apply for processMessage, if it + // fails // then whoever calls retryMessage will use the tx's gasLimit. .invokeMessageCall({ state: state, @@ -74,12 +80,17 @@ library LibBridgeRetry { gasLimit: gasleft() }) ) { - LibBridgeStatus.updateMessageStatus(msgHash, LibBridgeStatus.MessageStatus.DONE); + LibBridgeStatus.updateMessageStatus( + msgHash, LibBridgeStatus.MessageStatus.DONE + ); } else if (isLastAttempt) { - LibBridgeStatus.updateMessageStatus(msgHash, LibBridgeStatus.MessageStatus.FAILED); + LibBridgeStatus.updateMessageStatus( + msgHash, LibBridgeStatus.MessageStatus.FAILED + ); - address refundAddress = - message.refundAddress == address(0) ? message.owner : message.refundAddress; + address refundAddress = message.refundAddress == address(0) + ? message.owner + : message.refundAddress; refundAddress.sendEther(message.callValue); } else { diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeSend.sol b/packages/protocol/contracts/bridge/libs/LibBridgeSend.sol index 569e5c4272a..66b4c36a155 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeSend.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeSend.sol @@ -6,11 +6,11 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {IBridge} from "../IBridge.sol"; -import {ISignalService} from "../../signal/ISignalService.sol"; -import {LibAddress} from "../../libs/LibAddress.sol"; -import {LibBridgeData} from "./LibBridgeData.sol"; +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { IBridge } from "../IBridge.sol"; +import { ISignalService } from "../../signal/ISignalService.sol"; +import { LibAddress } from "../../libs/LibAddress.sol"; +import { LibBridgeData } from "./LibBridgeData.sol"; /** * Entry point for starting a bridge transaction. @@ -45,7 +45,10 @@ library LibBridgeSend { LibBridgeData.State storage state, AddressResolver resolver, IBridge.Message memory message - ) internal returns (bytes32 msgHash) { + ) + internal + returns (bytes32 msgHash) + { if (message.owner == address(0)) { revert B_OWNER_IS_NULL(); } @@ -60,7 +63,8 @@ library LibBridgeSend { revert B_WRONG_TO_ADDRESS(); } - uint256 expectedAmount = message.depositValue + message.callValue + message.processingFee; + uint256 expectedAmount = + message.depositValue + message.callValue + message.processingFee; if (expectedAmount != msg.value) { revert B_INCORRECT_VALUE(); @@ -79,11 +83,16 @@ library LibBridgeSend { msgHash = message.hashMessage(); // Store a key which is the hash of this contract address and the // msgHash, with a value of 1. - ISignalService(resolver.resolve("signal_service", false)).sendSignal(msgHash); + ISignalService(resolver.resolve("signal_service", false)).sendSignal( + msgHash + ); emit LibBridgeData.MessageSent(msgHash, message); } - function isDestChainEnabled(AddressResolver resolver, uint256 chainId) + function isDestChainEnabled( + AddressResolver resolver, + uint256 chainId + ) internal view returns (bool enabled, address destBridge) @@ -92,15 +101,16 @@ library LibBridgeSend { enabled = destBridge != address(0); } - function isMessageSent(AddressResolver resolver, bytes32 msgHash) + function isMessageSent( + AddressResolver resolver, + bytes32 msgHash + ) internal view returns (bool) { - return ISignalService(resolver.resolve("signal_service", false)).isSignalSent({ - app: address(this), - signal: msgHash - }); + return ISignalService(resolver.resolve("signal_service", false)) + .isSignalSent({ app: address(this), signal: msgHash }); } function isMessageReceived( @@ -108,9 +118,14 @@ library LibBridgeSend { bytes32 msgHash, uint256 srcChainId, bytes calldata proof - ) internal view returns (bool) { + ) + internal + view + returns (bool) + { address srcBridge = resolver.resolve(srcChainId, "bridge", false); - return ISignalService(resolver.resolve("signal_service", false)).isSignalReceived({ + return ISignalService(resolver.resolve("signal_service", false)) + .isSignalReceived({ srcChainId: srcChainId, app: srcBridge, signal: msgHash, diff --git a/packages/protocol/contracts/bridge/libs/LibBridgeStatus.sol b/packages/protocol/contracts/bridge/libs/LibBridgeStatus.sol index 2c34a557201..1c80582b726 100644 --- a/packages/protocol/contracts/bridge/libs/LibBridgeStatus.sol +++ b/packages/protocol/contracts/bridge/libs/LibBridgeStatus.sol @@ -6,11 +6,11 @@ pragma solidity ^0.8.18; -import {AddressResolver} from "../../common/AddressResolver.sol"; -import {BlockHeader, LibBlockHeader} from "../../libs/LibBlockHeader.sol"; -import {ICrossChainSync} from "../../common/ICrossChainSync.sol"; -import {LibBridgeData} from "./LibBridgeData.sol"; -import {LibTrieProof} from "../../libs/LibTrieProof.sol"; +import { AddressResolver } from "../../common/AddressResolver.sol"; +import { BlockHeader, LibBlockHeader } from "../../libs/LibBlockHeader.sol"; +import { ICrossChainSync } from "../../common/ICrossChainSync.sol"; +import { LibBridgeData } from "./LibBridgeData.sol"; +import { LibTrieProof } from "../../libs/LibTrieProof.sol"; library LibBridgeStatus { using LibBlockHeader for BlockHeader; @@ -22,7 +22,9 @@ library LibBridgeStatus { FAILED } - event MessageStatusChanged(bytes32 indexed msgHash, MessageStatus status, address transactor); + event MessageStatusChanged( + bytes32 indexed msgHash, MessageStatus status, address transactor + ); error B_MSG_HASH_NULL(); error B_WRONG_CHAIN_ID(); @@ -33,14 +35,23 @@ library LibBridgeStatus { * @param msgHash The messageHash of the message. * @param status The status of the message. */ - function updateMessageStatus(bytes32 msgHash, MessageStatus status) internal { + function updateMessageStatus( + bytes32 msgHash, + MessageStatus status + ) + internal + { if (getMessageStatus(msgHash) != status) { _setMessageStatus(msgHash, status); emit MessageStatusChanged(msgHash, status, msg.sender); } } - function getMessageStatus(bytes32 msgHash) internal view returns (MessageStatus) { + function getMessageStatus(bytes32 msgHash) + internal + view + returns (MessageStatus) + { bytes32 slot = getMessageStatusSlot(msgHash); uint256 value; assembly { @@ -54,7 +65,11 @@ library LibBridgeStatus { bytes32 msgHash, uint256 destChainId, bytes calldata proof - ) internal view returns (bool) { + ) + internal + view + returns (bool) + { if (destChainId == block.chainid) { revert B_WRONG_CHAIN_ID(); } @@ -62,12 +77,17 @@ library LibBridgeStatus { revert B_MSG_HASH_NULL(); } - LibBridgeData.StatusProof memory sp = abi.decode(proof, (LibBridgeData.StatusProof)); + LibBridgeData.StatusProof memory sp = + abi.decode(proof, (LibBridgeData.StatusProof)); - bytes32 syncedHeaderHash = ICrossChainSync(resolver.resolve("taiko", false)) - .getCrossChainBlockHash(sp.header.height); + bytes32 syncedHeaderHash = ICrossChainSync( + resolver.resolve("taiko", false) + ).getCrossChainBlockHash(sp.header.height); - if (syncedHeaderHash == 0 || syncedHeaderHash != sp.header.hashBlockHeader()) { + if ( + syncedHeaderHash == 0 + || syncedHeaderHash != sp.header.hashBlockHeader() + ) { return false; } @@ -80,7 +100,11 @@ library LibBridgeStatus { }); } - function getMessageStatusSlot(bytes32 msgHash) internal pure returns (bytes32) { + function getMessageStatusSlot(bytes32 msgHash) + internal + pure + returns (bytes32) + { return keccak256(bytes.concat(bytes("MESSAGE_STATUS"), msgHash)); } diff --git a/packages/protocol/contracts/common/AddressManager.sol b/packages/protocol/contracts/common/AddressManager.sol index 5a55a2d5367..c43943580f9 100644 --- a/packages/protocol/contracts/common/AddressManager.sol +++ b/packages/protocol/contracts/common/AddressManager.sol @@ -6,8 +6,9 @@ pragma solidity ^0.8.18; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import {Proxied} from "./Proxied.sol"; +import { OwnableUpgradeable } from + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { Proxied } from "./Proxied.sol"; /** * @notice Interface to set and get an address for a name. @@ -19,7 +20,12 @@ interface IAddressManager { * @param name Name to associate an address with. * @param newAddress Address to associate with the name. */ - function setAddress(uint256 domain, bytes32 name, address newAddress) external; + function setAddress( + uint256 domain, + bytes32 name, + address newAddress + ) + external; /** * Retrieves the address associated with a given name. @@ -27,15 +33,25 @@ interface IAddressManager { * @param name Name to retrieve an address for. * @return Address associated with the given name. */ - function getAddress(uint256 domain, bytes32 name) external view returns (address); + function getAddress( + uint256 domain, + bytes32 name + ) + external + view + returns (address); } /// @custom:security-contact hello@taiko.xyz contract AddressManager is OwnableUpgradeable, IAddressManager { - mapping(uint256 domain => mapping(bytes32 name => address addr)) private addresses; + mapping(uint256 domain => mapping(bytes32 name => address addr)) private + addresses; event AddressSet( - uint256 indexed _domain, bytes32 indexed _name, address _newAddress, address _oldAddress + uint256 indexed _domain, + bytes32 indexed _name, + address _newAddress, + address _oldAddress ); error EOAOwnerAddressNotAllowed(); @@ -45,7 +61,11 @@ contract AddressManager is OwnableUpgradeable, IAddressManager { OwnableUpgradeable.__Ownable_init(); } - function setAddress(uint256 domain, bytes32 name, address newAddress) + function setAddress( + uint256 domain, + bytes32 name, + address newAddress + ) external virtual onlyOwner @@ -60,7 +80,10 @@ contract AddressManager is OwnableUpgradeable, IAddressManager { emit AddressSet(domain, name, newAddress, oldAddress); } - function getAddress(uint256 domain, bytes32 name) + function getAddress( + uint256 domain, + bytes32 name + ) external view virtual @@ -70,4 +93,4 @@ contract AddressManager is OwnableUpgradeable, IAddressManager { } } -contract ProxiedAddressManager is Proxied, AddressManager {} +contract ProxiedAddressManager is Proxied, AddressManager { } diff --git a/packages/protocol/contracts/common/AddressResolver.sol b/packages/protocol/contracts/common/AddressResolver.sol index 4f4c8d99fd9..7cd1b01f4d0 100644 --- a/packages/protocol/contracts/common/AddressResolver.sol +++ b/packages/protocol/contracts/common/AddressResolver.sol @@ -6,8 +6,8 @@ pragma solidity ^0.8.18; -import {IAddressManager} from "./AddressManager.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import { IAddressManager } from "./AddressManager.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; /** * This abstract contract provides a name-to-address lookup. Under the hood, @@ -20,6 +20,8 @@ abstract contract AddressResolver { uint256[49] private __gap; + event AddressManagerChanged(address addressManager); + error RESOLVER_DENIED(); error RESOLVER_INVALID_ADDR(); error RESOLVER_ZERO_ADDR(uint256 chainId, bytes32 name); @@ -29,8 +31,6 @@ abstract contract AddressResolver { _; } - event AddressManagerChanged(address addressManager); - /** * Resolves a name to an address on the current chain. * @@ -39,7 +39,10 @@ abstract contract AddressResolver { * @param allowZeroAddress True to allow zero address to be returned. * @return The name's corresponding address. */ - function resolve(bytes32 name, bool allowZeroAddress) + function resolve( + bytes32 name, + bool allowZeroAddress + ) public view virtual @@ -57,7 +60,11 @@ abstract contract AddressResolver { * @param allowZeroAddress True to allow zero address to be returned. * @return The name's corresponding address. */ - function resolve(uint256 chainId, bytes32 name, bool allowZeroAddress) + function resolve( + uint256 chainId, + bytes32 name, + bool allowZeroAddress + ) public view virtual @@ -80,7 +87,11 @@ abstract contract AddressResolver { _addressManager = IAddressManager(addressManager_); } - function _resolve(uint256 chainId, bytes32 name, bool allowZeroAddress) + function _resolve( + uint256 chainId, + bytes32 name, + bool allowZeroAddress + ) private view returns (address payable addr) diff --git a/packages/protocol/contracts/common/EssentialContract.sol b/packages/protocol/contracts/common/EssentialContract.sol index 9a22a997200..aa7ffd29ed9 100644 --- a/packages/protocol/contracts/common/EssentialContract.sol +++ b/packages/protocol/contracts/common/EssentialContract.sol @@ -6,11 +6,12 @@ pragma solidity ^0.8.18; -import {IAddressManager} from "./AddressManager.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import {ReentrancyGuardUpgradeable} from +import { IAddressManager } from "./AddressManager.sol"; +import { OwnableUpgradeable } from + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; -import {AddressResolver} from "./AddressResolver.sol"; +import { AddressResolver } from "./AddressResolver.sol"; /** * @dev This abstract contract serves as the base contract for many core @@ -21,12 +22,6 @@ abstract contract EssentialContract is OwnableUpgradeable, AddressResolver { - function _init(address _addressManager) internal virtual override { - ReentrancyGuardUpgradeable.__ReentrancyGuard_init(); - OwnableUpgradeable.__Ownable_init(); - AddressResolver._init(_addressManager); - } - /** * Sets a new AddressManager's address. * @@ -38,4 +33,10 @@ abstract contract EssentialContract is emit AddressManagerChanged(newAddressManager); } + + function _init(address _addressManager) internal virtual override { + ReentrancyGuardUpgradeable.__ReentrancyGuard_init(); + OwnableUpgradeable.__Ownable_init(); + AddressResolver._init(_addressManager); + } } diff --git a/packages/protocol/contracts/common/ICrossChainSync.sol b/packages/protocol/contracts/common/ICrossChainSync.sol index 90ec4631c0c..53d0a24a942 100644 --- a/packages/protocol/contracts/common/ICrossChainSync.sol +++ b/packages/protocol/contracts/common/ICrossChainSync.sol @@ -12,14 +12,19 @@ pragma solidity ^0.8.18; */ interface ICrossChainSync { - event CrossChainSynced(uint256 indexed srcHeight, bytes32 blockHash, bytes32 signalRoot); + event CrossChainSynced( + uint256 indexed srcHeight, bytes32 blockHash, bytes32 signalRoot + ); /** * @notice Returns the cross-chain block hash at the given block number. * @param number The block number. Use 0 for the latest block. * @return The cross-chain block hash. */ - function getCrossChainBlockHash(uint256 number) external view returns (bytes32); + function getCrossChainBlockHash(uint256 number) + external + view + returns (bytes32); /** * @notice Returns the cross-chain signal service storage root at the given @@ -27,5 +32,8 @@ interface ICrossChainSync { * @param number The block number. Use 0 for the latest block. * @return The cross-chain signal service storage root. */ - function getCrossChainSignalRoot(uint256 number) external view returns (bytes32); + function getCrossChainSignalRoot(uint256 number) + external + view + returns (bytes32); } diff --git a/packages/protocol/contracts/common/IMintableERC20.sol b/packages/protocol/contracts/common/IMintableERC20.sol index 5a637bcfcd0..017bd7cac60 100644 --- a/packages/protocol/contracts/common/IMintableERC20.sol +++ b/packages/protocol/contracts/common/IMintableERC20.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.18; -import {IERC20Upgradeable} from +import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; interface IMintableERC20 is IERC20Upgradeable { diff --git a/packages/protocol/contracts/common/Proxied.sol b/packages/protocol/contracts/common/Proxied.sol index fd166c495ec..8e0aa370a90 100644 --- a/packages/protocol/contracts/common/Proxied.sol +++ b/packages/protocol/contracts/common/Proxied.sol @@ -6,7 +6,8 @@ pragma solidity ^0.8.18; -import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { Initializable } from + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; abstract contract Proxied is Initializable { /// @custom:oz-upgrades-unsafe-allow constructor diff --git a/packages/protocol/contracts/gov/TaikoGovernor.sol b/packages/protocol/contracts/gov/TaikoGovernor.sol index 4901ef70299..039c68a267f 100644 --- a/packages/protocol/contracts/gov/TaikoGovernor.sol +++ b/packages/protocol/contracts/gov/TaikoGovernor.sol @@ -10,11 +10,11 @@ import { GovernorUpgradeable, IGovernorUpgradeable } from "@openzeppelin/contracts-upgradeable/governance/GovernorUpgradeable.sol"; -import {GovernorSettingsUpgradeable} from +import { GovernorSettingsUpgradeable } from "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorSettingsUpgradeable.sol"; -import {GovernorCountingSimpleUpgradeable} from +import { GovernorCountingSimpleUpgradeable } from "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorCountingSimpleUpgradeable.sol"; -import {GovernorVotesUpgradeable} from +import { GovernorVotesUpgradeable } from "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesUpgradeable.sol"; import { GovernorVotesQuorumFractionUpgradeable, @@ -26,12 +26,14 @@ import { TimelockControllerUpgradeable } from "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorTimelockControlUpgradeable.sol"; -import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { Initializable } from + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { OwnableUpgradeable } from + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import {LibTaikoTokenConfig} from "../L1/TaikoToken.sol"; -import {EssentialContract} from "../common/EssentialContract.sol"; -import {Proxied} from "../common/Proxied.sol"; +import { LibTaikoTokenConfig } from "../L1/TaikoToken.sol"; +import { EssentialContract } from "../common/EssentialContract.sol"; +import { Proxied } from "../common/Proxied.sol"; /// @custom:security-contact hello@taiko.xyz contract TaikoGovernor is @@ -51,11 +53,20 @@ contract TaikoGovernor is address _addressManager, IVotesUpgradeable _token, TimelockControllerUpgradeable _timelock - ) public initializer { + ) + public + initializer + { EssentialContract._init(_addressManager); __Governor_init("TaikoGovernor"); - __GovernorSettings_init(1, /* 1 block */ 100800, /* 2 week */ LibTaikoTokenConfig.DECIMALS); + __GovernorSettings_init( + 1, + /* 1 block */ + 100_800, + /* 2 week */ + LibTaikoTokenConfig.DECIMALS + ); __GovernorCountingSimple_init(); __GovernorVotes_init(_token); __GovernorVotesQuorumFraction_init(5); @@ -68,7 +79,11 @@ contract TaikoGovernor is uint256[] memory values, bytes[] memory calldatas, string memory description - ) public override(GovernorUpgradeable, IGovernorUpgradeable) returns (uint256) { + ) + public + override(GovernorUpgradeable, IGovernorUpgradeable) + returns (uint256) + { return super.propose(targets, values, calldatas, description); } @@ -136,7 +151,10 @@ contract TaikoGovernor is uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash - ) internal override(GovernorUpgradeable, GovernorTimelockControlUpgradeable) { + ) + internal + override(GovernorUpgradeable, GovernorTimelockControlUpgradeable) + { super._execute(proposalId, targets, values, calldatas, descriptionHash); } @@ -163,4 +181,4 @@ contract TaikoGovernor is } } -contract ProxiedTaikoGovernor is Proxied, TaikoGovernor {} +contract ProxiedTaikoGovernor is Proxied, TaikoGovernor { } diff --git a/packages/protocol/contracts/libs/Lib1559Math.sol b/packages/protocol/contracts/libs/Lib1559Math.sol index 4cd0bc7dc93..f3dc00edd6b 100644 --- a/packages/protocol/contracts/libs/Lib1559Math.sol +++ b/packages/protocol/contracts/libs/Lib1559Math.sol @@ -6,8 +6,8 @@ pragma solidity ^0.8.18; -import {LibFixedPointMath} from "../thirdparty/LibFixedPointMath.sol"; -import {SafeCastUpgradeable} from +import { LibFixedPointMath } from "../thirdparty/LibFixedPointMath.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; library Lib1559Math { @@ -16,7 +16,12 @@ library Lib1559Math { error M1559_UNEXPECTED_CHANGE(uint64 expected, uint64 actual); error M1559_OUT_OF_STOCK(); - function calculateScales(uint64 xExcessMax, uint64 price, uint64 target, uint64 ratio2x1x) + function calculateScales( + uint64 xExcessMax, + uint64 price, + uint64 target, + uint64 ratio2x1x + ) internal pure returns (uint128 xscale, uint128 yscale) @@ -34,14 +39,19 @@ library Lib1559Math { // 2*target gas and the other one has target gas. uint256 price1x = calculatePrice(xscale, yscale, x, target); uint256 price2x = calculatePrice(xscale, yscale, x, target * 2); - uint64 ratio = uint64((price2x * 10000) / price1x); + uint64 ratio = uint64((price2x * 10_000) / price1x); if (ratio2x1x != ratio) { revert M1559_UNEXPECTED_CHANGE(ratio2x1x, ratio); } } - function calculatePrice(uint128 xscale, uint128 yscale, uint64 xExcess, uint64 xPurchase) + function calculatePrice( + uint128 xscale, + uint128 yscale, + uint64 xExcess, + uint64 xPurchase + ) internal pure returns (uint256) diff --git a/packages/protocol/contracts/libs/LibAddress.sol b/packages/protocol/contracts/libs/LibAddress.sol index 4157b2a8887..53457a3dd38 100644 --- a/packages/protocol/contracts/libs/LibAddress.sol +++ b/packages/protocol/contracts/libs/LibAddress.sol @@ -19,7 +19,7 @@ library LibAddress { */ function sendEther(address to, uint256 amount) internal { if (amount == 0 || to == address(0)) return; - (bool success,) = payable(to).call{value: amount}(""); + (bool success,) = payable(to).call{ value: amount }(""); require(success, "ETH transfer failed"); } diff --git a/packages/protocol/contracts/libs/LibBlockHeader.sol b/packages/protocol/contracts/libs/LibBlockHeader.sol index 61719621be8..f7572f144c4 100644 --- a/packages/protocol/contracts/libs/LibBlockHeader.sol +++ b/packages/protocol/contracts/libs/LibBlockHeader.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.18; -import {LibRLPWriter} from "../thirdparty/LibRLPWriter.sol"; +import { LibRLPWriter } from "../thirdparty/LibRLPWriter.sol"; struct BlockHeader { bytes32 parentHash; @@ -32,12 +32,20 @@ library LibBlockHeader { bytes32 public constant EMPTY_OMMERS_HASH = 0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347; - function hashBlockHeader(BlockHeader memory header) internal pure returns (bytes32) { - bytes memory rlpHeader = LibRLPWriter.writeList(getBlockHeaderRLPItemsList(header, 0)); + function hashBlockHeader(BlockHeader memory header) + internal + pure + returns (bytes32) + { + bytes memory rlpHeader = + LibRLPWriter.writeList(getBlockHeaderRLPItemsList(header, 0)); return keccak256(rlpHeader); } - function getBlockHeaderRLPItemsList(BlockHeader memory header, uint256 extraCapacity) + function getBlockHeaderRLPItemsList( + BlockHeader memory header, + uint256 extraCapacity + ) internal pure returns (bytes[] memory list) diff --git a/packages/protocol/contracts/libs/LibTrieProof.sol b/packages/protocol/contracts/libs/LibTrieProof.sol index 3f2c5438ac8..9ef7e61dce3 100644 --- a/packages/protocol/contracts/libs/LibTrieProof.sol +++ b/packages/protocol/contracts/libs/LibTrieProof.sol @@ -6,9 +6,9 @@ pragma solidity ^0.8.18; -import {LibRLPReader} from "../thirdparty/LibRLPReader.sol"; -import {LibRLPWriter} from "../thirdparty/LibRLPWriter.sol"; -import {LibSecureMerkleTrie} from "../thirdparty/LibSecureMerkleTrie.sol"; +import { LibRLPReader } from "../thirdparty/LibRLPReader.sol"; +import { LibRLPWriter } from "../thirdparty/LibRLPWriter.sol"; +import { LibSecureMerkleTrie } from "../thirdparty/LibSecureMerkleTrie.sol"; /** * @title LibTrieProof @@ -41,20 +41,31 @@ library LibTrieProof { bytes32 slot, bytes32 value, bytes calldata mkproof - ) public pure returns (bool verified) { - (bytes memory accountProof, bytes memory storageProof) = abi.decode(mkproof, (bytes, bytes)); + ) + public + pure + returns (bool verified) + { + (bytes memory accountProof, bytes memory storageProof) = + abi.decode(mkproof, (bytes, bytes)); - (bool exists, bytes memory rlpAccount) = - LibSecureMerkleTrie.get(abi.encodePacked(addr), accountProof, stateRoot); + (bool exists, bytes memory rlpAccount) = LibSecureMerkleTrie.get( + abi.encodePacked(addr), accountProof, stateRoot + ); require(exists, "LTP:invalid account proof"); - LibRLPReader.RLPItem[] memory accountState = LibRLPReader.readList(rlpAccount); - bytes32 storageRoot = - LibRLPReader.readBytes32(accountState[ACCOUNT_FIELD_INDEX_STORAGE_HASH]); + LibRLPReader.RLPItem[] memory accountState = + LibRLPReader.readList(rlpAccount); + bytes32 storageRoot = LibRLPReader.readBytes32( + accountState[ACCOUNT_FIELD_INDEX_STORAGE_HASH] + ); verified = LibSecureMerkleTrie.verifyInclusionProof( - abi.encodePacked(slot), LibRLPWriter.writeBytes32(value), storageProof, storageRoot + abi.encodePacked(slot), + LibRLPWriter.writeBytes32(value), + storageProof, + storageRoot ); } } diff --git a/packages/protocol/contracts/libs/LibUint512Math.sol b/packages/protocol/contracts/libs/LibUint512Math.sol index 8092409e56b..e5a6b1ee6d9 100644 --- a/packages/protocol/contracts/libs/LibUint512Math.sol +++ b/packages/protocol/contracts/libs/LibUint512Math.sol @@ -30,7 +30,14 @@ library LibUint512Math { * Optimized full 512 bit multiplication in Solidity. * Taken from: https://xn--2-umb.com/17/full-mul/index.html */ - function mul(uint256 a, uint256 b) internal pure returns (uint256 r0, uint256 r1) { + function mul( + uint256 a, + uint256 b + ) + internal + pure + returns (uint256 r0, uint256 r1) + { assembly { let mm := mulmod(a, b, not(0)) r0 := mul(a, b) @@ -42,7 +49,12 @@ library LibUint512Math { * Simple 512-bit addition. Taken from: * https://xn--2-umb.com/17/512-bit-division/#add-subtract-two-512-bit-numbers */ - function add(uint256 a0, uint256 a1, uint256 b0, uint256 b1) + function add( + uint256 a0, + uint256 a1, + uint256 b0, + uint256 b1 + ) internal pure returns (uint256 r0, uint256 r1) diff --git a/packages/protocol/contracts/signal/ISignalService.sol b/packages/protocol/contracts/signal/ISignalService.sol index f23ab6389f1..9130733659d 100644 --- a/packages/protocol/contracts/signal/ISignalService.sol +++ b/packages/protocol/contracts/signal/ISignalService.sol @@ -13,7 +13,9 @@ interface ISignalService { * @param signal The signal to send. * @return storageSlot The slot in storage that this signal is persisted. */ - function sendSignal(bytes32 signal) external returns (bytes32 storageSlot); + function sendSignal(bytes32 signal) + external + returns (bytes32 storageSlot); /** * Check if a signal has been sent (key stored with a value of 1). @@ -21,7 +23,13 @@ interface ISignalService { * @param app The address that sent this message. * @param signal The signal to check. */ - function isSignalSent(address app, bytes32 signal) external view returns (bool); + function isSignalSent( + address app, + bytes32 signal + ) + external + view + returns (bool); /** * Check if signal has been received on the destination chain (current). @@ -31,7 +39,12 @@ interface ISignalService { * @param signal The signal to check. * @param proof The proof of the signal being sent on the source chain. */ - function isSignalReceived(uint256 srcChainId, address app, bytes32 signal, bytes calldata proof) + function isSignalReceived( + uint256 srcChainId, + address app, + bytes32 signal, + bytes calldata proof + ) external view returns (bool); diff --git a/packages/protocol/contracts/signal/SignalService.sol b/packages/protocol/contracts/signal/SignalService.sol index 11433616495..64e74fabbf8 100644 --- a/packages/protocol/contracts/signal/SignalService.sol +++ b/packages/protocol/contracts/signal/SignalService.sol @@ -6,11 +6,11 @@ pragma solidity ^0.8.18; -import {EssentialContract} from "../common/EssentialContract.sol"; -import {Proxied} from "../common/Proxied.sol"; -import {ISignalService} from "./ISignalService.sol"; -import {ICrossChainSync} from "../common/ICrossChainSync.sol"; -import {LibSecureMerkleTrie} from "../thirdparty/LibSecureMerkleTrie.sol"; +import { EssentialContract } from "../common/EssentialContract.sol"; +import { Proxied } from "../common/Proxied.sol"; +import { ISignalService } from "./ISignalService.sol"; +import { ICrossChainSync } from "../common/ICrossChainSync.sol"; +import { LibSecureMerkleTrie } from "../thirdparty/LibSecureMerkleTrie.sol"; /// @custom:security-contact hello@taiko.xyz contract SignalService is ISignalService, EssentialContract { @@ -39,7 +39,14 @@ contract SignalService is ISignalService, EssentialContract { } } - function isSignalSent(address app, bytes32 signal) public view returns (bool) { + function isSignalSent( + address app, + bytes32 signal + ) + public + view + returns (bool) + { if (app == address(0)) { revert B_NULL_APP_ADDR(); } @@ -56,7 +63,12 @@ contract SignalService is ISignalService, EssentialContract { return value == 1; } - function isSignalReceived(uint256 srcChainId, address app, bytes32 signal, bytes calldata proof) + function isSignalReceived( + uint256 srcChainId, + address app, + bytes32 signal, + bytes calldata proof + ) public view returns (bool) @@ -68,11 +80,14 @@ contract SignalService is ISignalService, EssentialContract { SignalProof memory sp = abi.decode(proof, (SignalProof)); // Resolve the TaikoL1 or TaikoL2 contract if on Ethereum or Taiko. - bytes32 syncedSignalRoot = - ICrossChainSync(resolve("taiko", false)).getCrossChainSignalRoot(sp.height); + bytes32 syncedSignalRoot = ICrossChainSync(resolve("taiko", false)) + .getCrossChainSignalRoot(sp.height); return LibSecureMerkleTrie.verifyInclusionProof( - bytes.concat(getSignalSlot(app, signal)), hex"01", sp.proof, syncedSignalRoot + bytes.concat(getSignalSlot(app, signal)), + hex"01", + sp.proof, + syncedSignalRoot ); } @@ -81,13 +96,22 @@ contract SignalService is ISignalService, EssentialContract { * @param signal The signal to store. * @return signalSlot The storage key for the signal on the signal service. */ - function getSignalSlot(address app, bytes32 signal) public pure returns (bytes32 signalSlot) { + function getSignalSlot( + address app, + bytes32 signal + ) + public + pure + returns (bytes32 signalSlot) + { // Equivilance to `keccak256(abi.encodePacked(app, signal))` assembly { - // Load the free memory pointer and allocate memory for the concatenated arguments + // Load the free memory pointer and allocate memory for the + // concatenated arguments let ptr := mload(0x40) - // Store the app address and signal bytes32 value in the allocated memory + // Store the app address and signal bytes32 value in the allocated + // memory mstore(ptr, app) mstore(add(ptr, 32), signal) @@ -100,4 +124,4 @@ contract SignalService is ISignalService, EssentialContract { } } -contract ProxiedSignalService is Proxied, SignalService {} +contract ProxiedSignalService is Proxied, SignalService { } diff --git a/packages/protocol/contracts/test/ExampleStaticAddressManager.sol b/packages/protocol/contracts/test/ExampleStaticAddressManager.sol index b5e87f2363b..5cbe591b753 100644 --- a/packages/protocol/contracts/test/ExampleStaticAddressManager.sol +++ b/packages/protocol/contracts/test/ExampleStaticAddressManager.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.18; -import {AddressManager} from "../common/AddressManager.sol"; +import { AddressManager } from "../common/AddressManager.sol"; /** * @title ExampleStaticAddressManager @@ -15,7 +15,13 @@ import {AddressManager} from "../common/AddressManager.sol"; * SSLOAD easily. */ contract ExampleStaticAddressManager is AddressManager { - function setAddress(uint256, /*domain*/ bytes32, /*nameHash*/ address /*newAddress*/ ) + function setAddress( + uint256, + /*domain*/ + bytes32, + /*nameHash*/ + address /*newAddress*/ + ) external pure override @@ -25,7 +31,10 @@ contract ExampleStaticAddressManager is AddressManager { /// @dev This function must be a pure function in order to avoid /// reading from storage. - function getAddress(uint256 domain, bytes32 nameHash) + function getAddress( + uint256 domain, + bytes32 nameHash + ) external pure override diff --git a/packages/protocol/contracts/test/L1/TestTaikoL1.sol b/packages/protocol/contracts/test/L1/TestTaikoL1.sol index 8421e81fd07..053c7fc76e7 100644 --- a/packages/protocol/contracts/test/L1/TestTaikoL1.sol +++ b/packages/protocol/contracts/test/L1/TestTaikoL1.sol @@ -6,12 +6,17 @@ pragma solidity ^0.8.18; -import {TaikoL1} from "../../L1/TaikoL1.sol"; -import {TaikoData} from "../../L1/TaikoData.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import { TaikoL1 } from "../../L1/TaikoL1.sol"; +import { TaikoData } from "../../L1/TaikoData.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; contract TestTaikoL1 is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() + public + pure + override + returns (TaikoData.Config memory config) + { config.chainId = 167; // up to 2048 pending blocks config.maxNumProposedBlocks = 4; @@ -19,8 +24,8 @@ contract TestTaikoL1 is TaikoL1 { // This number is calculated from maxNumProposedBlocks to make // the 'the maximum value of the multiplier' close to 20.0 config.maxVerificationsPerTx = 0; - config.blockMaxGasLimit = 30000000; + config.blockMaxGasLimit = 30_000_000; config.maxTransactionsPerBlock = 20; - config.maxBytesPerTxList = 120000; + config.maxBytesPerTxList = 120_000; } } diff --git a/packages/protocol/contracts/test/L1/TestTaikoL1EnableTokenomics.sol b/packages/protocol/contracts/test/L1/TestTaikoL1EnableTokenomics.sol index 53fa69e4653..92e7f4dd3c3 100644 --- a/packages/protocol/contracts/test/L1/TestTaikoL1EnableTokenomics.sol +++ b/packages/protocol/contracts/test/L1/TestTaikoL1EnableTokenomics.sol @@ -6,12 +6,17 @@ pragma solidity ^0.8.18; -import {TaikoL1} from "../../L1/TaikoL1.sol"; -import {TaikoData} from "../../L1/TaikoData.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import { TaikoL1 } from "../../L1/TaikoL1.sol"; +import { TaikoData } from "../../L1/TaikoData.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; contract TestTaikoL1EnableTokenomics is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() + public + pure + override + returns (TaikoData.Config memory config) + { config.chainId = 167; // up to 2048 pending blocks config.maxNumProposedBlocks = 6; @@ -19,8 +24,8 @@ contract TestTaikoL1EnableTokenomics is TaikoL1 { // This number is calculated from maxNumProposedBlocks to make // the 'the maximum value of the multiplier' close to 20.0 config.maxVerificationsPerTx = 0; // dont verify blocks automatically - config.blockMaxGasLimit = 30000000; + config.blockMaxGasLimit = 30_000_000; config.maxTransactionsPerBlock = 20; - config.maxBytesPerTxList = 120000; + config.maxBytesPerTxList = 120_000; } } diff --git a/packages/protocol/contracts/test/TestContracts.sol b/packages/protocol/contracts/test/TestContracts.sol index 106daa05dae..8df2f7d5cd4 100644 --- a/packages/protocol/contracts/test/TestContracts.sol +++ b/packages/protocol/contracts/test/TestContracts.sol @@ -6,14 +6,14 @@ pragma solidity ^0.8.18; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import {SignalService} from "../signal/SignalService.sol"; -import {TokenVault} from "../bridge/TokenVault.sol"; -import {EtherVault} from "../bridge/EtherVault.sol"; -import {BridgedERC20} from "../bridge/BridgedERC20.sol"; -import {Bridge} from "../bridge/Bridge.sol"; -import {TaikoToken} from "../L1/TaikoToken.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { SignalService } from "../signal/SignalService.sol"; +import { TokenVault } from "../bridge/TokenVault.sol"; +import { EtherVault } from "../bridge/EtherVault.sol"; +import { BridgedERC20 } from "../bridge/BridgedERC20.sol"; +import { Bridge } from "../bridge/Bridge.sol"; +import { TaikoToken } from "../L1/TaikoToken.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; // The old implementation that is also used in hardhat tests. @@ -23,15 +23,15 @@ contract TestERC20 is ERC20 { } } -contract TestSignalService is SignalService {} +contract TestSignalService is SignalService { } -contract TestTokenVault is TokenVault {} +contract TestTokenVault is TokenVault { } -contract TestEtherVault is EtherVault {} +contract TestEtherVault is EtherVault { } -contract TestBridgedERC20 is BridgedERC20 {} +contract TestBridgedERC20 is BridgedERC20 { } -contract TestBridge is Bridge {} +contract TestBridge is Bridge { } contract TestTaikoToken is TaikoToken { function mintAnyone(address account, uint256 amount) public { diff --git a/packages/protocol/contracts/test/bridge/TestHeaderSync.sol b/packages/protocol/contracts/test/bridge/TestHeaderSync.sol index 2bfcd5f4d87..7ec369b1548 100644 --- a/packages/protocol/contracts/test/bridge/TestHeaderSync.sol +++ b/packages/protocol/contracts/test/bridge/TestHeaderSync.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.18; -import {ICrossChainSync} from "../../common/ICrossChainSync.sol"; +import { ICrossChainSync } from "../../common/ICrossChainSync.sol"; // TODO(roger): remove this file. If you need extra functionality in // the Bridge contract, create a TestBridge.sol contract instead. diff --git a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeData.sol b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeData.sol index b78783da580..ffcc7f39b65 100644 --- a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeData.sol +++ b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeData.sol @@ -6,22 +6,35 @@ pragma solidity ^0.8.18; -import {LibBridgeData} from "../../../bridge/libs/LibBridgeData.sol"; -import {LibBridgeStatus} from "../../../bridge/libs/LibBridgeStatus.sol"; -import {IBridge} from "../../../bridge/IBridge.sol"; +import { LibBridgeData } from "../../../bridge/libs/LibBridgeData.sol"; +import { LibBridgeStatus } from "../../../bridge/libs/LibBridgeStatus.sol"; +import { IBridge } from "../../../bridge/IBridge.sol"; // TODO(roger): remove this file. If you need extra functionality in // the Bridge contract, create a TestBridge.sol contract instead. contract TestLibBridgeData { - function updateMessageStatus(bytes32 signal, LibBridgeStatus.MessageStatus status) public { + function updateMessageStatus( + bytes32 signal, + LibBridgeStatus.MessageStatus status + ) + public + { LibBridgeStatus.updateMessageStatus(signal, status); } - function getMessageStatus(bytes32 signal) public view returns (LibBridgeStatus.MessageStatus) { + function getMessageStatus(bytes32 signal) + public + view + returns (LibBridgeStatus.MessageStatus) + { return LibBridgeStatus.getMessageStatus(signal); } - function hashMessage(IBridge.Message memory message) public pure returns (bytes32) { + function hashMessage(IBridge.Message memory message) + public + pure + returns (bytes32) + { return LibBridgeData.hashMessage(message); } } diff --git a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeInvoke.sol b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeInvoke.sol index 09b2172b151..1db4f042b00 100644 --- a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeInvoke.sol +++ b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeInvoke.sol @@ -6,9 +6,9 @@ pragma solidity ^0.8.18; -import {LibBridgeInvoke} from "../../../bridge/libs/LibBridgeInvoke.sol"; -import {LibBridgeData} from "../../../bridge/libs/LibBridgeData.sol"; -import {IBridge} from "../../../bridge/IBridge.sol"; +import { LibBridgeInvoke } from "../../../bridge/libs/LibBridgeInvoke.sol"; +import { LibBridgeData } from "../../../bridge/libs/LibBridgeData.sol"; +import { IBridge } from "../../../bridge/IBridge.sol"; // TODO(roger): remove this file. If you need extra functionality in // the Bridge contract, create a TestBridge.sol contract instead. @@ -17,11 +17,16 @@ contract TestLibBridgeInvoke { event MessageInvoked(bytes32 signal, bool success); - function invokeMessageCall(IBridge.Message calldata message, bytes32 signal, uint256 gasLimit) + function invokeMessageCall( + IBridge.Message calldata message, + bytes32 signal, + uint256 gasLimit + ) public payable { - bool success = LibBridgeInvoke.invokeMessageCall(state, message, signal, gasLimit); + bool success = + LibBridgeInvoke.invokeMessageCall(state, message, signal, gasLimit); emit MessageInvoked(signal, success); } } diff --git a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeProcess.sol b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeProcess.sol index 90e4cef3ebe..8913c1fd377 100644 --- a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeProcess.sol +++ b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeProcess.sol @@ -6,11 +6,11 @@ pragma solidity ^0.8.18; -import {EssentialContract} from "../../../common/EssentialContract.sol"; -import {LibBridgeProcess} from "../../../bridge/libs/LibBridgeProcess.sol"; -import {LibBridgeData} from "../../../bridge/libs/LibBridgeData.sol"; -import {IBridge} from "../../../bridge/IBridge.sol"; -import {AddressResolver} from "../../../common/AddressResolver.sol"; +import { EssentialContract } from "../../../common/EssentialContract.sol"; +import { LibBridgeProcess } from "../../../bridge/libs/LibBridgeProcess.sol"; +import { LibBridgeData } from "../../../bridge/libs/LibBridgeData.sol"; +import { IBridge } from "../../../bridge/IBridge.sol"; +import { AddressResolver } from "../../../common/AddressResolver.sol"; // TODO(roger): remove this file. If you need extra functionality in // the Bridge contract, create a TestBridge.sol contract instead. @@ -21,10 +21,15 @@ contract TestLibBridgeProcess is EssentialContract { EssentialContract._init(_addressManager); } - function processMessage(IBridge.Message calldata message, bytes calldata proof) + function processMessage( + IBridge.Message calldata message, + bytes calldata proof + ) public payable { - LibBridgeProcess.processMessage(state, AddressResolver(this), message, proof); + LibBridgeProcess.processMessage( + state, AddressResolver(this), message, proof + ); } } diff --git a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol index 7d188216c7b..0b8744cada8 100644 --- a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol +++ b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeRetry.sol @@ -6,24 +6,32 @@ pragma solidity ^0.8.18; -import {EssentialContract} from "../../../common/EssentialContract.sol"; -import {LibBridgeData} from "../../../bridge/libs/LibBridgeData.sol"; -import {LibBridgeRetry} from "../../../bridge/libs/LibBridgeRetry.sol"; -import {IBridge} from "../../../bridge/IBridge.sol"; -import {AddressResolver} from "../../../common/AddressResolver.sol"; +import { EssentialContract } from "../../../common/EssentialContract.sol"; +import { LibBridgeData } from "../../../bridge/libs/LibBridgeData.sol"; +import { LibBridgeRetry } from "../../../bridge/libs/LibBridgeRetry.sol"; +import { IBridge } from "../../../bridge/IBridge.sol"; +import { AddressResolver } from "../../../common/AddressResolver.sol"; // TODO(roger): remove this file. If you need extra functionality in // the Bridge contract, create a TestBridge.sol contract instead. contract TestLibBridgeRetry is EssentialContract { LibBridgeData.State public state; - receive() external payable {} + receive() external payable { } function init(address _addressManager) external initializer { EssentialContract._init(_addressManager); } - function retryMessage(IBridge.Message calldata message, bool lastAttempt) public payable { - LibBridgeRetry.retryMessage(state, AddressResolver(this), message, lastAttempt); + function retryMessage( + IBridge.Message calldata message, + bool lastAttempt + ) + public + payable + { + LibBridgeRetry.retryMessage( + state, AddressResolver(this), message, lastAttempt + ); } } diff --git a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeSend.sol b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeSend.sol index 5a8482acbfd..e3e91244a8a 100644 --- a/packages/protocol/contracts/test/bridge/libs/TestLibBridgeSend.sol +++ b/packages/protocol/contracts/test/bridge/libs/TestLibBridgeSend.sol @@ -6,11 +6,11 @@ pragma solidity ^0.8.18; -import {EssentialContract} from "../../../common/EssentialContract.sol"; -import {LibBridgeSend} from "../../../bridge/libs/LibBridgeSend.sol"; -import {AddressResolver} from "../../../common/AddressResolver.sol"; -import {IBridge} from "../../../bridge/IBridge.sol"; -import {LibBridgeData} from "../../../bridge/libs/LibBridgeData.sol"; +import { EssentialContract } from "../../../common/EssentialContract.sol"; +import { LibBridgeSend } from "../../../bridge/libs/LibBridgeSend.sol"; +import { AddressResolver } from "../../../common/AddressResolver.sol"; +import { IBridge } from "../../../bridge/IBridge.sol"; +import { LibBridgeData } from "../../../bridge/libs/LibBridgeData.sol"; // TODO(roger): remove this file. If you need extra functionality in // the Bridge contract, create a TestBridge.sol contract instead. @@ -21,7 +21,11 @@ contract TestLibBridgeSend is EssentialContract { EssentialContract._init(_addressManager); } - function sendMessage(IBridge.Message memory message) public payable returns (bytes32 signal) { + function sendMessage(IBridge.Message memory message) + public + payable + returns (bytes32 signal) + { return LibBridgeSend.sendMessage(state, AddressResolver(this), message); } } diff --git a/packages/protocol/contracts/test/erc20/FreeMintERC20.sol b/packages/protocol/contracts/test/erc20/FreeMintERC20.sol index 80fd103c4d0..40e8163f7f8 100644 --- a/packages/protocol/contracts/test/erc20/FreeMintERC20.sol +++ b/packages/protocol/contracts/test/erc20/FreeMintERC20.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.18; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; // An ERC20 Token with a mint function anyone can call, for free, to receive // 5 tokens. @@ -15,7 +15,7 @@ contract FreeMintERC20 is ERC20 { error HasMinted(); - constructor(string memory name, string memory symbol) ERC20(name, symbol) {} + constructor(string memory name, string memory symbol) ERC20(name, symbol) { } function mint(address to) public { if (minters[to]) { diff --git a/packages/protocol/contracts/test/erc20/MayFailFreeMintERC20.sol b/packages/protocol/contracts/test/erc20/MayFailFreeMintERC20.sol index 8d024a73cef..a0affbeae4d 100644 --- a/packages/protocol/contracts/test/erc20/MayFailFreeMintERC20.sol +++ b/packages/protocol/contracts/test/erc20/MayFailFreeMintERC20.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.18; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; // An ERC20 token for testing the Taiko Bridge on testnets. // This token has 50% of failure on transfers so we can @@ -16,7 +16,7 @@ contract MayFailFreeMintERC20 is ERC20 { error HasMinted(); - constructor(string memory name, string memory symbol) ERC20(name, symbol) {} + constructor(string memory name, string memory symbol) ERC20(name, symbol) { } function mint(address to) public { if (minters[msg.sender]) { @@ -27,12 +27,23 @@ contract MayFailFreeMintERC20 is ERC20 { _mint(to, 50 * (10 ** decimals())); } - function transfer(address to, uint256 amount) public override returns (bool) { + function transfer( + address to, + uint256 amount + ) + public + override + returns (bool) + { _mayFail(); return ERC20.transfer(to, amount); } - function transferFrom(address from, address to, uint256 amount) + function transferFrom( + address from, + address to, + uint256 amount + ) public override returns (bool) diff --git a/packages/protocol/contracts/test/erc20/RegularERC20.sol b/packages/protocol/contracts/test/erc20/RegularERC20.sol index e4239c1cc52..96e2ddbe28f 100644 --- a/packages/protocol/contracts/test/erc20/RegularERC20.sol +++ b/packages/protocol/contracts/test/erc20/RegularERC20.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract RegularERC20 is ERC20 { constructor(uint256 initialSupply) ERC20("RegularERC20", "RGL") { diff --git a/packages/protocol/contracts/test/libs/TestLibBlockHeader.sol b/packages/protocol/contracts/test/libs/TestLibBlockHeader.sol index debd82059e6..b9c36d356dd 100644 --- a/packages/protocol/contracts/test/libs/TestLibBlockHeader.sol +++ b/packages/protocol/contracts/test/libs/TestLibBlockHeader.sol @@ -6,15 +6,23 @@ pragma solidity ^0.8.18; -import {LibBlockHeader, BlockHeader} from "../../libs/LibBlockHeader.sol"; -import {LibRLPWriter} from "../../thirdparty/LibRLPWriter.sol"; +import { LibBlockHeader, BlockHeader } from "../../libs/LibBlockHeader.sol"; +import { LibRLPWriter } from "../../thirdparty/LibRLPWriter.sol"; contract TestLibBlockHeader { - function hashBlockHeader(BlockHeader calldata header) public pure returns (bytes32) { + function hashBlockHeader(BlockHeader calldata header) + public + pure + returns (bytes32) + { return LibBlockHeader.hashBlockHeader(header); } - function rlpBlockHeader(BlockHeader calldata header) public pure returns (bytes memory) { + function rlpBlockHeader(BlockHeader calldata header) + public + pure + returns (bytes memory) + { bytes[] memory list = new bytes[](15); list[0] = LibRLPWriter.writeHash(header.parentHash); list[1] = LibRLPWriter.writeHash(header.ommersHash); diff --git a/packages/protocol/contracts/test/libs/TestLibTrieProof.sol b/packages/protocol/contracts/test/libs/TestLibTrieProof.sol index d549b8c342c..65aa0717d65 100644 --- a/packages/protocol/contracts/test/libs/TestLibTrieProof.sol +++ b/packages/protocol/contracts/test/libs/TestLibTrieProof.sol @@ -6,7 +6,7 @@ pragma solidity ^0.8.18; -import {LibTrieProof} from "../../libs/LibTrieProof.sol"; +import { LibTrieProof } from "../../libs/LibTrieProof.sol"; contract TestLibTrieProof { function writeStorageAt(bytes32 slot, bytes32 val) public { diff --git a/packages/protocol/contracts/test/thirdparty/TestLibMerkleTrie.sol b/packages/protocol/contracts/test/thirdparty/TestLibMerkleTrie.sol index de161303563..379e8fb0ab2 100644 --- a/packages/protocol/contracts/test/thirdparty/TestLibMerkleTrie.sol +++ b/packages/protocol/contracts/test/thirdparty/TestLibMerkleTrie.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; -import {LibMerkleTrie} from "../../thirdparty/LibMerkleTrie.sol"; +import { LibMerkleTrie } from "../../thirdparty/LibMerkleTrie.sol"; /** * @title TestLibMerkleTrie @@ -13,11 +13,19 @@ contract TestLibMerkleTrie { bytes memory _value, bytes memory _proof, bytes32 _root - ) public pure returns (bool) { + ) + public + pure + returns (bool) + { return LibMerkleTrie.verifyInclusionProof(_key, _value, _proof, _root); } - function get(bytes memory _key, bytes memory _proof, bytes32 _root) + function get( + bytes memory _key, + bytes memory _proof, + bytes32 _root + ) public pure returns (bool, bytes memory) diff --git a/packages/protocol/contracts/test/thirdparty/TestLibRLPReader.sol b/packages/protocol/contracts/test/thirdparty/TestLibRLPReader.sol index 7de89cae7c3..6a19b1df6cf 100644 --- a/packages/protocol/contracts/test/thirdparty/TestLibRLPReader.sol +++ b/packages/protocol/contracts/test/thirdparty/TestLibRLPReader.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.18; -import {LibRLPReader} from "../../thirdparty/LibRLPReader.sol"; +import { LibRLPReader } from "../../thirdparty/LibRLPReader.sol"; /** * @title TestLibRLPReader diff --git a/packages/protocol/contracts/test/thirdparty/TestLibRLPWriter.sol b/packages/protocol/contracts/test/thirdparty/TestLibRLPWriter.sol index c702e9079df..5d74fe9be65 100644 --- a/packages/protocol/contracts/test/thirdparty/TestLibRLPWriter.sol +++ b/packages/protocol/contracts/test/thirdparty/TestLibRLPWriter.sol @@ -2,25 +2,41 @@ pragma solidity ^0.8.18; -import {LibRLPWriter} from "../../thirdparty/LibRLPWriter.sol"; +import { LibRLPWriter } from "../../thirdparty/LibRLPWriter.sol"; /** * @title TestLibRLPWriter */ contract TestLibRLPWriter { - function writeBytes(bytes memory _in) public pure returns (bytes memory _out) { + function writeBytes(bytes memory _in) + public + pure + returns (bytes memory _out) + { return LibRLPWriter.writeBytes(_in); } - function writeList(bytes[] memory _in) public pure returns (bytes memory _out) { + function writeList(bytes[] memory _in) + public + pure + returns (bytes memory _out) + { return LibRLPWriter.writeList(_in); } - function writeString(string memory _in) public pure returns (bytes memory _out) { + function writeString(string memory _in) + public + pure + returns (bytes memory _out) + { return LibRLPWriter.writeString(_in); } - function writeAddress(address _in) public pure returns (bytes memory _out) { + function writeAddress(address _in) + public + pure + returns (bytes memory _out) + { return LibRLPWriter.writeAddress(_in); } diff --git a/packages/protocol/contracts/test/thirdparty/TestLibSecureMerkleTrie.sol b/packages/protocol/contracts/test/thirdparty/TestLibSecureMerkleTrie.sol index 6a09b4de3fc..d3e66e0180c 100644 --- a/packages/protocol/contracts/test/thirdparty/TestLibSecureMerkleTrie.sol +++ b/packages/protocol/contracts/test/thirdparty/TestLibSecureMerkleTrie.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.18; /* Library Imports */ -import {LibSecureMerkleTrie} from "../../thirdparty/LibSecureMerkleTrie.sol"; +import { LibSecureMerkleTrie } from "../../thirdparty/LibSecureMerkleTrie.sol"; /** * @title TestLibSecureMerkleTrie @@ -14,11 +14,21 @@ contract TestLibSecureMerkleTrie { bytes memory _value, bytes memory _proof, bytes32 _root - ) public pure returns (bool) { - return LibSecureMerkleTrie.verifyInclusionProof(_key, _value, _proof, _root); + ) + public + pure + returns (bool) + { + return LibSecureMerkleTrie.verifyInclusionProof( + _key, _value, _proof, _root + ); } - function get(bytes memory _key, bytes memory _proof, bytes32 _root) + function get( + bytes memory _key, + bytes memory _proof, + bytes32 _root + ) public pure returns (bool, bytes memory) diff --git a/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol b/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol index bc2ddfd044f..8dcacc2a667 100644 --- a/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol +++ b/packages/protocol/contracts/test/thirdparty/TestMessageSender.sol @@ -2,12 +2,17 @@ pragma solidity ^0.8.18; -import {IBridge} from "../../bridge/IBridge.sol"; +import { IBridge } from "../../bridge/IBridge.sol"; contract TestMessageSender { - bytes32 public signal = 0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab; + bytes32 public signal = + 0x3fd54831f488a22b28398de0c567a3b064b937f54f81739ae9bd545967f3abab; - function sendMessage(IBridge.Message calldata message) external payable returns (bytes32) { + function sendMessage(IBridge.Message calldata message) + external + payable + returns (bytes32) + { message; return signal; } diff --git a/packages/protocol/contracts/thirdparty/LibBytesUtils.sol b/packages/protocol/contracts/thirdparty/LibBytesUtils.sol index 22b60780b3f..b55cbdac091 100644 --- a/packages/protocol/contracts/thirdparty/LibBytesUtils.sol +++ b/packages/protocol/contracts/thirdparty/LibBytesUtils.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// Taken from https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/utils/LibBytesUtils.sol +// Taken from +// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/utils/LibBytesUtils.sol // (The MIT License) // // Copyright 2020-2021 Optimism @@ -34,7 +35,11 @@ library LibBytesUtils { INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ - function slice(bytes memory _bytes, uint256 _start, uint256 _length) + function slice( + bytes memory _bytes, + uint256 _start, + uint256 _length + ) internal pure returns (bytes memory) @@ -48,7 +53,8 @@ library LibBytesUtils { assembly { switch iszero(_length) case 0 { - // Get a location of some free memory and store it in tempBytes as + // Get a location of some free memory and store it in tempBytes + // as // Solidity does for memory variables. tempBytes := mload(0x40) @@ -66,13 +72,21 @@ library LibBytesUtils { // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. - let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) + let mc := + add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { - // The multiplication in the next line has the same exact purpose + // The multiplication in the next line has the same exact + // purpose // as the one above. - let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) + let cc := + add( + add( + add(_bytes, lengthmod), mul(0x20, iszero(lengthmod)) + ), + _start + ) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) @@ -81,10 +95,12 @@ library LibBytesUtils { mstore(tempBytes, _length) //update free-memory pointer - //allocating the array padded to 32 bytes like the compiler does now + //allocating the array padded to 32 bytes like the compiler does + // now mstore(0x40, and(add(mc, 31), not(31))) } - //if we want a zero-length slice let's just return a zero-length array + //if we want a zero-length slice let's just return a zero-length + // array default { tempBytes := mload(0x40) @@ -99,7 +115,14 @@ library LibBytesUtils { return tempBytes; } - function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) { + function slice( + bytes memory _bytes, + uint256 _start + ) + internal + pure + returns (bytes memory) + { if (_start >= _bytes.length) { return bytes(""); } @@ -116,14 +139,19 @@ library LibBytesUtils { return ret; } - return abi.decode(_bytes, (bytes32)); // will truncate if input length > 32 bytes + return abi.decode(_bytes, (bytes32)); // will truncate if input length > + // 32 bytes } function toUint256(bytes memory _bytes) internal pure returns (uint256) { return uint256(toBytes32(_bytes)); } - function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) { + function toNibbles(bytes memory _bytes) + internal + pure + returns (bytes memory) + { bytes memory nibbles = new bytes(_bytes.length * 2); for (uint256 i; i < _bytes.length; ++i) { @@ -134,7 +162,11 @@ library LibBytesUtils { return nibbles; } - function fromNibbles(bytes memory _bytes) internal pure returns (bytes memory) { + function fromNibbles(bytes memory _bytes) + internal + pure + returns (bytes memory) + { bytes memory ret = new bytes(_bytes.length / 2); for (uint256 i; i < ret.length; ++i) { @@ -144,7 +176,14 @@ library LibBytesUtils { return ret; } - function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) { + function equal( + bytes memory _bytes, + bytes memory _other + ) + internal + pure + returns (bool) + { return keccak256(_bytes) == keccak256(_other); } } diff --git a/packages/protocol/contracts/thirdparty/LibFixedPointMath.sol b/packages/protocol/contracts/thirdparty/LibFixedPointMath.sol index 741a54257df..4bd3740dd93 100644 --- a/packages/protocol/contracts/thirdparty/LibFixedPointMath.sol +++ b/packages/protocol/contracts/thirdparty/LibFixedPointMath.sol @@ -1,10 +1,12 @@ // SPDX-License-Identifier: UNLICENSED -// Taken from: https://github.com/recmo/experiment-solexp/blob/main/src/FixedPointMathLib.sol +// Taken from: +// https://github.com/recmo/experiment-solexp/blob/main/src/FixedPointMathLib.sol pragma solidity ^0.8.18; library LibFixedPointMath { - uint128 public constant MAX_EXP_INPUT = 135305999368893231588; - uint256 public constant SCALING_FACTOR_1E18 = 1e18; // For fixed point representation factor + uint128 public constant MAX_EXP_INPUT = 135_305_999_368_893_231_588; + uint256 public constant SCALING_FACTOR_1E18 = 1e18; // For fixed point + // representation factor error Overflow(); @@ -15,44 +17,53 @@ library LibFixedPointMath { // When the result is < 0.5 we return zero. This happens when // x <= floor(log(0.5e18) * 1e18) ~ -42e18 - if (x <= -42139678854452767551) { + if (x <= -42_139_678_854_452_767_551) { return 0; } // When the result is > (2**255 - 1) / 1e18 we can not represent it - // as an int256. This happens when x >= floor(log((2**255 -1) / 1e18) * 1e18) ~ 135. - if (x >= 135305999368893231589) revert Overflow(); + // as an int256. This happens when x >= floor(log((2**255 -1) / + // 1e18) * 1e18) ~ 135. + if (x >= 135_305_999_368_893_231_589) revert Overflow(); - // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96 - // for more intermediate precision and a binary basis. This base conversion + // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * + // 2**96 + // for more intermediate precision and a binary basis. This base + // conversion // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. x = (x << 78) / 5 ** 18; - // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers of two + // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out + // powers of two // such that exp(x) = exp(x') * 2**k, where k is an integer. // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). - int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96; - x = x - k * 54916777467707473351141471128; + int256 k = ( + (x << 96) / 54_916_777_467_707_473_351_141_471_128 + 2 ** 95 + ) >> 96; + x = x - k * 54_916_777_467_707_473_351_141_471_128; // k is in the range [-61, 195]. // Evaluate using a (6, 7)-term rational approximation // p is made monic, we will multiply by a scale factor later - int256 p = x + 2772001395605857295435445496992; - p = ((p * x) >> 96) + 44335888930127919016834873520032; - p = ((p * x) >> 96) + 398888492587501845352592340339721; - p = ((p * x) >> 96) + 1993839819670624470859228494792842; - p = p * x + (4385272521454847904632057985693276 << 96); - // We leave p in 2**192 basis so we don't need to scale it back up for the division. + int256 p = x + 2_772_001_395_605_857_295_435_445_496_992; + p = ((p * x) >> 96) + 44_335_888_930_127_919_016_834_873_520_032; + p = ((p * x) >> 96) + 398_888_492_587_501_845_352_592_340_339_721; + p = ((p * x) >> 96) + 1_993_839_819_670_624_470_859_228_494_792_842; + p = p * x + (4_385_272_521_454_847_904_632_057_985_693_276 << 96); + // We leave p in 2**192 basis so we don't need to scale it back up + // for the division. // Evaluate using using Knuth's scheme from p. 491. - int256 z = x + 750530180792738023273180420736; - z = ((z * x) >> 96) + 32788456221302202726307501949080; - int256 w = x - 2218138959503481824038194425854; - w = ((w * z) >> 96) + 892943633302991980437332862907700; - int256 q = z + w - 78174809823045304726920794422040; - q = ((q * w) >> 96) + 4203224763890128580604056984195872; + int256 z = x + 750_530_180_792_738_023_273_180_420_736; + z = ((z * x) >> 96) + 32_788_456_221_302_202_726_307_501_949_080; + int256 w = x - 2_218_138_959_503_481_824_038_194_425_854; + w = ((w * z) >> 96) + 892_943_633_302_991_980_437_332_862_907_700; + int256 q = z + w - 78_174_809_823_045_304_726_920_794_422_040; + q = ((q * w) >> 96) + 4_203_224_763_890_128_580_604_056_984_195_872; assembly { - // Div in assembly because solidity adds a zero check despite the `unchecked`. - // The q polynomial is known not to have zeros in the domain. (All roots are complex) + // Div in assembly because solidity adds a zero check despite + // the `unchecked`. + // The q polynomial is known not to have zeros in the domain. + // (All roots are complex) // No scaling required because p is already 2**96 too large. r := sdiv(p, q) } @@ -62,10 +73,15 @@ library LibFixedPointMath { // * the scale factor s = ~6.031367120..., // * the 2**k factor from the range reduction, and // * the 1e18 / 2**96 factor for base converison. - // We do all of this at once, with an intermediate result in 2**213 basis + // We do all of this at once, with an intermediate result in 2**213 + // basis // so the final right shift is always by a positive amount. r = int256( - (uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k) + ( + uint256(r) + * + 3_822_833_074_963_236_453_042_738_258_902_158_003_155_416_615_667 + ) >> uint256(195 - k) ); } } diff --git a/packages/protocol/contracts/thirdparty/LibMerkleTrie.sol b/packages/protocol/contracts/thirdparty/LibMerkleTrie.sol index f8b7d9d852a..4245e18025e 100644 --- a/packages/protocol/contracts/thirdparty/LibMerkleTrie.sol +++ b/packages/protocol/contracts/thirdparty/LibMerkleTrie.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// Taken from https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/trie/LibMerkleTrie.sol +// Taken from +// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/trie/LibMerkleTrie.sol // (The MIT License) // // Copyright 2020-2021 Optimism @@ -27,9 +28,9 @@ pragma solidity ^0.8.18; /* Library Imports */ -import {LibBytesUtils} from "./LibBytesUtils.sol"; -import {LibRLPReader} from "./LibRLPReader.sol"; -import {LibRLPWriter} from "./LibRLPWriter.sol"; +import { LibBytesUtils } from "./LibBytesUtils.sol"; +import { LibRLPReader } from "./LibRLPReader.sol"; +import { LibRLPWriter } from "./LibRLPWriter.sol"; /** * @title LibMerkleTrie @@ -62,7 +63,8 @@ library LibMerkleTrie { uint8 private constant TREE_RADIX = 16; // Branch nodes have TREE_RADIX elements plus an additional `value` slot. uint8 private constant BRANCH_NODE_LENGTH = TREE_RADIX + 1; - // Leaf nodes and extension nodes always have two elements, a `path` and a `value`. + // Leaf nodes and extension nodes always have two elements, a `path` and a + // `value`. uint8 private constant LEAF_OR_EXTENSION_NODE_LENGTH = 2; // Prefixes are prepended to the `path` within a leaf or extension node and @@ -92,14 +94,19 @@ library LibMerkleTrie { * of a list of RLP-encoded nodes that make a path down to the target node. * @param _root Known root of the Merkle trie. Used to verify that the * included proof is correctly constructed. - * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. + * @return _verified `true` if the k/v pair exists in the trie, `false` + * otherwise. */ function verifyInclusionProof( bytes memory _key, bytes memory _value, bytes memory _proof, bytes32 _root - ) internal pure returns (bool _verified) { + ) + internal + pure + returns (bool _verified) + { (bool exists, bytes memory value) = get(_key, _proof, _root); return (exists && LibBytesUtils.equal(_value, value)); @@ -113,7 +120,11 @@ library LibMerkleTrie { * @return _exists Whether or not the key exists. * @return _value Value of the key if it exists. */ - function get(bytes memory _key, bytes memory _proof, bytes32 _root) + function get( + bytes memory _key, + bytes memory _proof, + bytes32 _root + ) internal pure returns (bool _exists, bytes memory _value) @@ -126,7 +137,8 @@ library LibMerkleTrie { require(exists || isFinalNode, "Provided proof is invalid."); - bytes memory value = exists ? _getNodeValue(proof[pathLength - 1]) : bytes(""); + bytes memory value = + exists ? _getNodeValue(proof[pathLength - 1]) : bytes(""); return (exists, value); } @@ -144,10 +156,18 @@ library LibMerkleTrie { * @return _keyRemainder Portion of the key remaining after the walk. * @return _isFinalNode Whether or not we've hit a dead end. */ - function _walkNodePath(TrieNode[] memory _proof, bytes memory _key, bytes32 _root) + function _walkNodePath( + TrieNode[] memory _proof, + bytes memory _key, + bytes32 _root + ) private pure - returns (uint256 _pathLength, bytes memory _keyRemainder, bool _isFinalNode) + returns ( + uint256 _pathLength, + bytes memory _keyRemainder, + bool _isFinalNode + ) { uint256 pathLength; bytes memory key = LibBytesUtils.toNibbles(_key); @@ -163,21 +183,27 @@ library LibMerkleTrie { currentKeyIndex += currentKeyIncrement; // Keep track of the proof elements we actually need. - // It's expensive to resize arrays, so this simply reduces gas costs. + // It's expensive to resize arrays, so this simply reduces gas + // costs. pathLength += 1; if (currentKeyIndex == 0) { // First proof element is always the root node. - require(keccak256(currentNode.encoded) == currentNodeID, "Invalid root hash"); + require( + keccak256(currentNode.encoded) == currentNodeID, + "Invalid root hash" + ); } else if (currentNode.encoded.length >= 32) { // Nodes 32 bytes or larger are hashed inside branch nodes. require( - keccak256(currentNode.encoded) == currentNodeID, "Invalid large internal hash" + keccak256(currentNode.encoded) == currentNodeID, + "Invalid large internal hash" ); } else { // Nodes smaller than 31 bytes aren't hashed. require( - LibBytesUtils.toBytes32(currentNode.encoded) == currentNodeID, + LibBytesUtils.toBytes32(currentNode.encoded) + == currentNodeID, "Invalid internal node hash" ); } @@ -191,18 +217,23 @@ library LibMerkleTrie { // We're not at the end of the key yet. // Figure out what the next node ID should be and continue. uint8 branchKey = uint8(key[currentKeyIndex]); - LibRLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey]; + LibRLPReader.RLPItem memory nextNode = + currentNode.decoded[branchKey]; currentNodeID = _getNodeID(nextNode); currentKeyIncrement = 1; continue; } - } else if (currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH) { + } else if ( + currentNode.decoded.length == LEAF_OR_EXTENSION_NODE_LENGTH + ) { bytes memory path = _getNodePath(currentNode); uint8 prefix = uint8(path[0]); uint8 offset = 2 - (prefix % 2); bytes memory pathRemainder = LibBytesUtils.slice(path, offset); - bytes memory keyRemainder = LibBytesUtils.slice(key, currentKeyIndex); - uint256 sharedNibbleLength = _getSharedNibbleLength(pathRemainder, keyRemainder); + bytes memory keyRemainder = + LibBytesUtils.slice(key, currentKeyIndex); + uint256 sharedNibbleLength = + _getSharedNibbleLength(pathRemainder, keyRemainder); if (prefix == PREFIX_LEAF_EVEN || prefix == PREFIX_LEAF_ODD) { if ( @@ -210,14 +241,18 @@ library LibMerkleTrie { && keyRemainder.length == sharedNibbleLength ) { // The key within this leaf matches our key exactly. - // Increment the key index to reflect that we have no remainder. + // Increment the key index to reflect that we have no + // remainder. currentKeyIndex += sharedNibbleLength; } // We've hit a leaf node, so our next node should be NULL. currentNodeID = bytes32(RLP_NULL); break; - } else if (prefix == PREFIX_EXTENSION_EVEN || prefix == PREFIX_EXTENSION_ODD) { + } else if ( + prefix == PREFIX_EXTENSION_EVEN + || prefix == PREFIX_EXTENSION_ODD + ) { if (sharedNibbleLength != pathRemainder.length) { // Our extension node is not identical to the remainder. // We've hit the end of this path @@ -241,7 +276,8 @@ library LibMerkleTrie { // If our node ID is NULL, then we're at a dead end. bool isFinalNode = currentNodeID == bytes32(RLP_NULL); - return (pathLength, LibBytesUtils.slice(key, currentKeyIndex), isFinalNode); + return + (pathLength, LibBytesUtils.slice(key, currentKeyIndex), isFinalNode); } /** @@ -249,13 +285,20 @@ library LibMerkleTrie { * @param _proof RLP-encoded proof to parse. * @return _parsed Proof parsed into easily accessible structs. */ - function _parseProof(bytes memory _proof) private pure returns (TrieNode[] memory _parsed) { + function _parseProof(bytes memory _proof) + private + pure + returns (TrieNode[] memory _parsed) + { LibRLPReader.RLPItem[] memory nodes = LibRLPReader.readList(_proof); TrieNode[] memory proof = new TrieNode[](nodes.length); for (uint256 i; i < nodes.length; ++i) { bytes memory encoded = LibRLPReader.readBytes(nodes[i]); - proof[i] = TrieNode({encoded: encoded, decoded: LibRLPReader.readList(encoded)}); + proof[i] = TrieNode({ + encoded: encoded, + decoded: LibRLPReader.readList(encoded) + }); } return proof; @@ -268,7 +311,11 @@ library LibMerkleTrie { * @param _node Node to pull an ID for. * @return _nodeID ID for the node, depending on the size of its contents. */ - function _getNodeID(LibRLPReader.RLPItem memory _node) private pure returns (bytes32 _nodeID) { + function _getNodeID(LibRLPReader.RLPItem memory _node) + private + pure + returns (bytes32 _nodeID) + { bytes memory nodeID; if (_node.length < 32) { @@ -287,7 +334,11 @@ library LibMerkleTrie { * @param _node Node to get a path for. * @return _path Node path, converted to an array of nibbles. */ - function _getNodePath(TrieNode memory _node) private pure returns (bytes memory _path) { + function _getNodePath(TrieNode memory _node) + private + pure + returns (bytes memory _path) + { return LibBytesUtils.toNibbles(LibRLPReader.readBytes(_node.decoded[0])); } @@ -296,7 +347,11 @@ library LibMerkleTrie { * @param _node Node to get a value for. * @return _value Node value, as hex bytes. */ - function _getNodeValue(TrieNode memory _node) private pure returns (bytes memory _value) { + function _getNodeValue(TrieNode memory _node) + private + pure + returns (bytes memory _value) + { return LibRLPReader.readBytes(_node.decoded[_node.decoded.length - 1]); } @@ -314,7 +369,10 @@ library LibMerkleTrie { * @param _b Second nibble array. * @return _shared Number of shared nibbles. */ - function _getSharedNibbleLength(bytes memory _a, bytes memory _b) + function _getSharedNibbleLength( + bytes memory _a, + bytes memory _b + ) private pure returns (uint256 _shared) diff --git a/packages/protocol/contracts/thirdparty/LibRLPReader.sol b/packages/protocol/contracts/thirdparty/LibRLPReader.sol index 228f214dd58..31a4c9ae888 100644 --- a/packages/protocol/contracts/thirdparty/LibRLPReader.sol +++ b/packages/protocol/contracts/thirdparty/LibRLPReader.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// Taken from https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/rlp/LibRLPReader.sol +// Taken from +// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/rlp/LibRLPReader.sol // (The MIT License) // // Copyright 2020-2021 Optimism @@ -64,13 +65,17 @@ library LibRLPReader { * @param _in Input bytes to convert. * @return Output memory reference. */ - function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) { + function toRLPItem(bytes memory _in) + internal + pure + returns (RLPItem memory) + { uint256 ptr; assembly { ptr := add(_in, 32) } - return RLPItem({length: _in.length, ptr: ptr}); + return RLPItem({ length: _in.length, ptr: ptr }); } /** @@ -78,26 +83,41 @@ library LibRLPReader { * @param _in RLP list value. * @return Decoded RLP list items. */ - function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) { + function readList(RLPItem memory _in) + internal + pure + returns (RLPItem[] memory) + { (uint256 listOffset,, RLPItemType itemType) = _decodeLength(_in); require(itemType == RLPItemType.LIST_ITEM, "Invalid RLP list value."); - // Solidity in-memory arrays can't be increased in size, but *can* be decreased in size by - // writing to the length. Since we can't know the number of RLP items without looping over - // the entire input, we'd have to loop twice to accurately size this array. It's easier to - // simply set a reasonable maximum list length and decrease the size before we finish. + // Solidity in-memory arrays can't be increased in size, but *can* be + // decreased in size by + // writing to the length. Since we can't know the number of RLP items + // without looping over + // the entire input, we'd have to loop twice to accurately size this + // array. It's easier to + // simply set a reasonable maximum list length and decrease the size + // before we finish. RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH); uint256 itemCount; uint256 offset = listOffset; while (offset < _in.length) { - require(itemCount < MAX_LIST_LENGTH, "Provided RLP list exceeds max list length."); + require( + itemCount < MAX_LIST_LENGTH, + "Provided RLP list exceeds max list length." + ); - (uint256 itemOffset, uint256 itemLength,) = - _decodeLength(RLPItem({length: _in.length - offset, ptr: _in.ptr + offset})); + (uint256 itemOffset, uint256 itemLength,) = _decodeLength( + RLPItem({ length: _in.length - offset, ptr: _in.ptr + offset }) + ); - out[itemCount] = RLPItem({length: itemLength + itemOffset, ptr: _in.ptr + offset}); + out[itemCount] = RLPItem({ + length: itemLength + itemOffset, + ptr: _in.ptr + offset + }); itemCount += 1; offset += itemOffset + itemLength; @@ -116,7 +136,11 @@ library LibRLPReader { * @param _in RLP list value. * @return Decoded RLP list items. */ - function readList(bytes memory _in) internal pure returns (RLPItem[] memory) { + function readList(bytes memory _in) + internal + pure + returns (RLPItem[] memory) + { return readList(toRLPItem(_in)); } @@ -125,8 +149,13 @@ library LibRLPReader { * @param _in RLP bytes value. * @return Decoded bytes. */ - function readBytes(RLPItem memory _in) internal pure returns (bytes memory) { - (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in); + function readBytes(RLPItem memory _in) + internal + pure + returns (bytes memory) + { + (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = + _decodeLength(_in); require(itemType == RLPItemType.DATA_ITEM, "Invalid RLP bytes value."); @@ -147,7 +176,11 @@ library LibRLPReader { * @param _in RLP string value. * @return Decoded string. */ - function readString(RLPItem memory _in) internal pure returns (string memory) { + function readString(RLPItem memory _in) + internal + pure + returns (string memory) + { return string(readBytes(_in)); } @@ -156,7 +189,11 @@ library LibRLPReader { * @param _in RLP string value. * @return Decoded string. */ - function readString(bytes memory _in) internal pure returns (string memory) { + function readString(bytes memory _in) + internal + pure + returns (string memory) + { return readString(toRLPItem(_in)); } @@ -168,7 +205,8 @@ library LibRLPReader { function readBytes32(RLPItem memory _in) internal pure returns (bytes32) { require(_in.length <= 33, "Invalid RLP bytes32 value."); - (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in); + (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = + _decodeLength(_in); require(itemType == RLPItemType.DATA_ITEM, "Invalid RLP bytes32 value."); @@ -178,7 +216,9 @@ library LibRLPReader { out := mload(ptr) // Shift the bytes over to match the item size. - if lt(itemLength, 32) { out := div(out, exp(256, sub(32, itemLength))) } + if lt(itemLength, 32) { + out := div(out, exp(256, sub(32, itemLength))) + } } return out; @@ -225,7 +265,10 @@ library LibRLPReader { out := byte(0, mload(ptr)) } - require(out == 0 || out == 1, "LibRLPReader: Invalid RLP boolean value, must be 0 or 1"); + require( + out == 0 || out == 1, + "LibRLPReader: Invalid RLP boolean value, must be 0 or 1" + ); return out != 0; } @@ -268,7 +311,11 @@ library LibRLPReader { * @param _in RLP item to read. * @return Raw RLP bytes. */ - function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) { + function readRawBytes(RLPItem memory _in) + internal + pure + returns (bytes memory) + { return _copy(_in); } @@ -318,10 +365,13 @@ library LibRLPReader { uint256 strLen; assembly { // Pick out the string length. - strLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfStrLen))) + strLen := + div(mload(add(ptr, 1)), exp(256, sub(32, lenOfStrLen))) } - require(_in.length > lenOfStrLen + strLen, "Invalid RLP long string."); + require( + _in.length > lenOfStrLen + strLen, "Invalid RLP long string." + ); return (1 + lenOfStrLen, strLen, RLPItemType.DATA_ITEM); } else if (prefix <= 0xf7) { @@ -341,10 +391,13 @@ library LibRLPReader { uint256 listLen; assembly { // Pick out the list length. - listLen := div(mload(add(ptr, 1)), exp(256, sub(32, lenOfListLen))) + listLen := + div(mload(add(ptr, 1)), exp(256, sub(32, lenOfListLen))) } - require(_in.length > lenOfListLen + listLen, "Invalid RLP long list."); + require( + _in.length > lenOfListLen + listLen, "Invalid RLP long list." + ); return (1 + lenOfListLen, listLen, RLPItemType.LIST_ITEM); } @@ -357,7 +410,11 @@ library LibRLPReader { * @param _length Number of bytes to read. * @return Copied bytes. */ - function _copy(uint256 _src, uint256 _offset, uint256 _length) + function _copy( + uint256 _src, + uint256 _offset, + uint256 _length + ) internal pure returns (bytes memory) diff --git a/packages/protocol/contracts/thirdparty/LibRLPWriter.sol b/packages/protocol/contracts/thirdparty/LibRLPWriter.sol index 69e87de2c7a..3d9bbc00426 100644 --- a/packages/protocol/contracts/thirdparty/LibRLPWriter.sol +++ b/packages/protocol/contracts/thirdparty/LibRLPWriter.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// Taken from https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/rlp/LibRLPWriter.sol +// Taken from +// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/rlp/LibRLPWriter.sol // Modified to support writeBytes32/writeUint64 // (The MIT License) // @@ -41,7 +42,11 @@ library LibRLPWriter { * @param _in The byte string to encode. * @return The RLP encoded string in bytes. */ - function writeBytes(bytes memory _in) internal pure returns (bytes memory) { + function writeBytes(bytes memory _in) + internal + pure + returns (bytes memory) + { bytes memory encoded; if (_in.length == 1 && uint8(_in[0]) < 128) { @@ -58,7 +63,11 @@ library LibRLPWriter { * @param _in The list of RLP encoded byte strings. * @return The RLP encoded list of items in bytes. */ - function writeList(bytes[] memory _in) internal pure returns (bytes memory) { + function writeList(bytes[] memory _in) + internal + pure + returns (bytes memory) + { bytes memory list = _flatten(_in); return abi.encodePacked(_writeLength(list.length, 192), list); } @@ -68,7 +77,11 @@ library LibRLPWriter { * @param _in The string to encode. * @return The RLP encoded string in bytes. */ - function writeString(string memory _in) internal pure returns (bytes memory) { + function writeString(string memory _in) + internal + pure + returns (bytes memory) + { return writeBytes(bytes(_in)); } @@ -125,12 +138,20 @@ library LibRLPWriter { //////////////////////////////////////////////////////////////*/ /** - * Encode the first byte, followed by the `len` in binary form if `length` is more than 55. + * Encode the first byte, followed by the `len` in binary form if `length` + * is more than 55. * @param _len The length of the string or the payload. * @param _offset 128 if item is string, 192 if item is list. * @return RLP encoded bytes. */ - function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) { + function _writeLength( + uint256 _len, + uint256 _offset + ) + private + pure + returns (bytes memory) + { bytes memory encoded; if (_len < 56) { @@ -184,7 +205,11 @@ library LibRLPWriter { * @param _x The integer to encode. * @return RLP encoded bytes. */ - function _toBinaryWithLeadingZeros(uint256 _x) private pure returns (bytes memory) { + function _toBinaryWithLeadingZeros(uint256 _x) + private + pure + returns (bytes memory) + { bytes memory b = abi.encodePacked(_x); uint256 i; @@ -199,7 +224,8 @@ library LibRLPWriter { /** * Copies a piece of memory to another location. - * @notice From: https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol. + * @notice From: + * https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol. * @param _dest Destination location. * @param _src Source location. * @param _len Length of memory to copy. @@ -230,11 +256,16 @@ library LibRLPWriter { /** * Flattens a list of byte strings into one byte string. - * @notice From: https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol. + * @notice From: + * https://github.com/sammayo/solidity-rlp-encoder/blob/master/RLPEncode.sol. * @param _list List of byte strings to flatten. * @return The flattened byte string. */ - function _flatten(bytes[] memory _list) private pure returns (bytes memory) { + function _flatten(bytes[] memory _list) + private + pure + returns (bytes memory) + { if (_list.length == 0) { return new bytes(0); } diff --git a/packages/protocol/contracts/thirdparty/LibSecureMerkleTrie.sol b/packages/protocol/contracts/thirdparty/LibSecureMerkleTrie.sol index 9c7d8779af9..a96dee9f365 100644 --- a/packages/protocol/contracts/thirdparty/LibSecureMerkleTrie.sol +++ b/packages/protocol/contracts/thirdparty/LibSecureMerkleTrie.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// Taken from https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/trie/LibSecureMerkleTrie.sol +// Taken from +// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/libraries/trie/LibSecureMerkleTrie.sol // (The MIT License) // // Copyright 2020-2021 Optimism @@ -27,7 +28,7 @@ pragma solidity ^0.8.18; /* Library Imports */ -import {LibMerkleTrie} from "./LibMerkleTrie.sol"; +import { LibMerkleTrie } from "./LibMerkleTrie.sol"; /** * @title LibSecureMerkleTrie @@ -47,14 +48,19 @@ library LibSecureMerkleTrie { * of a list of RLP-encoded nodes that make a path down to the target node. * @param _root Known root of the Merkle trie. Used to verify that the * included proof is correctly constructed. - * @return _verified `true` if the k/v pair exists in the trie, `false` otherwise. + * @return _verified `true` if the k/v pair exists in the trie, `false` + * otherwise. */ function verifyInclusionProof( bytes memory _key, bytes memory _value, bytes memory _proof, bytes32 _root - ) internal pure returns (bool _verified) { + ) + internal + pure + returns (bool _verified) + { bytes memory key = _getSecureKey(_key); return LibMerkleTrie.verifyInclusionProof(key, _value, _proof, _root); } @@ -67,7 +73,11 @@ library LibSecureMerkleTrie { * @return _exists Whether or not the key exists. * @return _value Value of the key if it exists. */ - function get(bytes memory _key, bytes memory _proof, bytes32 _root) + function get( + bytes memory _key, + bytes memory _proof, + bytes32 _root + ) internal pure returns (bool _exists, bytes memory _value) @@ -85,7 +95,11 @@ library LibSecureMerkleTrie { * @param _key Key to get a secure key from. * @return _secureKey Secure version of the key. */ - function _getSecureKey(bytes memory _key) private pure returns (bytes memory _secureKey) { + function _getSecureKey(bytes memory _key) + private + pure + returns (bytes memory _secureKey) + { return bytes.concat(keccak256(_key)); } } diff --git a/packages/protocol/contracts/thirdparty/TransparentUpgradeableProxy.sol b/packages/protocol/contracts/thirdparty/TransparentUpgradeableProxy.sol index 02668e474e3..f4125692017 100644 --- a/packages/protocol/contracts/thirdparty/TransparentUpgradeableProxy.sol +++ b/packages/protocol/contracts/thirdparty/TransparentUpgradeableProxy.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (proxy/transparent/TransparentUpgradeableProxy.sol) +// OpenZeppelin Contracts (last updated v4.7.0) +// (proxy/transparent/TransparentUpgradeableProxy.sol) pragma solidity ^0.8.0; @@ -8,30 +9,47 @@ import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; /** * @dev This contract implements a proxy that is upgradeable by an admin. * - * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector + * To avoid + * https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy + * selector * clashing], which can potentially be used in an attack, this contract uses the - * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two + * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent + * proxy pattern]. This pattern implies two * things that go hand in hand: * - * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if + * 1. If any account other than the admin calls the proxy, the call will be + * forwarded to the implementation, even if * that call matches one of the admin functions exposed by the proxy itself. - * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the - * implementation. If the admin tries to call a function on the implementation it will fail with an error that says + * 2. If the admin calls the proxy, it can access the admin functions, but its + * calls will never be forwarded to the + * implementation. If the admin tries to call a function on the implementation + * it will fail with an error that says * "admin cannot fallback to proxy target". * - * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing - * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due - * to sudden errors when trying to call a function from the proxy implementation. + * These properties mean that the admin account can only be used for admin + * actions like upgrading the proxy or changing + * the admin, so it's best if it's a dedicated account that is not used for + * anything else. This will avoid headaches due + * to sudden errors when trying to call a function from the proxy + * implementation. * - * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, - * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy. + * Our recommendation is for the dedicated account to be an instance of the + * {ProxyAdmin} contract. If set up this way, + * you should think of the `ProxyAdmin` instance as the real administrative + * interface of your proxy. */ contract TransparentUpgradeableProxy is ERC1967Proxy { /** - * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and - * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}. + * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the + * implementation at `_logic`, and + * optionally initialized with `_data` as explained in + * {ERC1967Proxy-constructor}. */ - constructor(address _logic, address admin_, bytes memory _data) + constructor( + address _logic, + address admin_, + bytes memory _data + ) payable ERC1967Proxy(_logic, _data) { @@ -39,7 +57,8 @@ contract TransparentUpgradeableProxy is ERC1967Proxy { } /** - * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin. + * @dev Modifier used internally that will delegate the call to the + * implementation unless the sender is the admin. */ modifier ifAdmin() { if (msg.sender == _getAdmin()) { @@ -52,10 +71,13 @@ contract TransparentUpgradeableProxy is ERC1967Proxy { /** * @dev Returns the current admin. * - * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. + * NOTE: Only the admin can call this function. See + * {ProxyAdmin-getProxyAdmin}. * - * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the - * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * TIP: To get this value clients can read directly from the storage slot + * shown below (specified by EIP1967) using the + * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC + * call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function admin() external ifAdmin returns (address admin_) { @@ -65,13 +87,20 @@ contract TransparentUpgradeableProxy is ERC1967Proxy { /** * @dev Returns the current implementation. * - * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. + * NOTE: Only the admin can call this function. See + * {ProxyAdmin-getProxyImplementation}. * - * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the - * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. + * TIP: To get this value clients can read directly from the storage slot + * shown below (specified by EIP1967) using the + * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC + * call. * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` */ - function implementation() external ifAdmin returns (address implementation_) { + function implementation() + external + ifAdmin + returns (address implementation_) + { implementation_ = _implementation(); } @@ -80,7 +109,8 @@ contract TransparentUpgradeableProxy is ERC1967Proxy { * * Emits an {AdminChanged} event. * - * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}. + * NOTE: Only the admin can call this function. See + * {ProxyAdmin-changeProxyAdmin}. */ function changeAdmin(address newAdmin) external virtual ifAdmin { _changeAdmin(newAdmin); @@ -96,13 +126,19 @@ contract TransparentUpgradeableProxy is ERC1967Proxy { } /** - * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified - * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the + * @dev Upgrade the implementation of the proxy, and then call a function + * from the new implementation as specified + * by `data`, which should be an encoded function call. This is useful to + * initialize new storage variables in the * proxied contract. * - * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}. + * NOTE: Only the admin can call this function. See + * {ProxyAdmin-upgradeAndCall}. */ - function upgradeToAndCall(address newImplementation, bytes calldata data) + function upgradeToAndCall( + address newImplementation, + bytes calldata data + ) external payable ifAdmin @@ -118,7 +154,8 @@ contract TransparentUpgradeableProxy is ERC1967Proxy { } /** - * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}. + * @dev Makes sure the admin cannot access the fallback function. See + * {Proxy-_beforeFallback}. */ function _beforeFallback() internal virtual override { require( diff --git a/packages/protocol/foundry.toml b/packages/protocol/foundry.toml index 8c1f78f7d4f..4e3f3bfb508 100644 --- a/packages/protocol/foundry.toml +++ b/packages/protocol/foundry.toml @@ -28,4 +28,8 @@ fs_permissions = [ fuzz = { runs = 256 } [fmt] -line_length = 100 +bracket_spacing = true +line_length = 80 +multiline_func_header = 'all' +number_underscore = 'thousands' +wrap_comments = true diff --git a/packages/protocol/package.json b/packages/protocol/package.json index 60f7a61174c..eec3c18ed36 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -6,25 +6,31 @@ "clean": "rm -rf abis cache && pnpm hardhat clean", "compile": "forge build", "compile:hardhat": "pnpm hardhat compile", + "deploy:foundry": "./script/download_solc.sh && ./script/test_deploy_on_l1.sh", + "eslint": "pnpm exec eslint --ignore-path .eslintignore --ext .js,.ts .", + "eslint:fix": "pnpm exec eslint --ignore-path .eslintignore --ext .js,.ts . --fix", "export:abi": "pnpm hardhat clear-abi && pnpm hardhat export-abi", "export:docs": "pnpm hardhat docgen && pnpm prettier --write ../website/pages/docs/reference/contract-documentation/**/*.md", + "fmt:sol": "forge fmt", + "generate:genesis": "ts-node ./utils/generate_genesis/main.ts", "lint:sol": "forge fmt && pnpm solhint 'contracts/**/*.sol' --fix", - "eslint": "pnpm exec eslint --ignore-path .eslintignore --ext .js,.ts .", - "eslint:fix": "pnpm exec eslint --ignore-path .eslintignore --ext .js,.ts . --fix", - "test": "forge test -vvv --gas-report --fuzz-seed $(date +%s) --match-path test/**/*.t.sol", - "snapshot": "forge snapshot --match-path test/**/*.t.sol", - "test:coverage": "forge coverage --report lcov", "sim": "forge test -vvv --gas-report --fuzz-seed $(date +%s) --match-path test/**/*.sim.sol --block-gas-limit 3000000000000000000", "sim:export": "pnpm test:sim > simulation/exports/simulation_data_$(date +%s).txt", - "generate:genesis": "ts-node ./utils/generate_genesis/main.ts", - "test:genesis": "./test/genesis/generate_genesis.test.sh", - "deploy:foundry": "./script/download_solc.sh && ./script/test_deploy_on_l1.sh", - "sizer": "pnpm hardhat size-contracts" + "sizer": "pnpm hardhat size-contracts", + "snapshot": "forge snapshot --match-path test/**/*.t.sol", + "test": "forge test -vvv --gas-report --fuzz-seed $(date +%s) --match-path test/**/*.t.sol", + "test:coverage": "forge coverage --report lcov", + "test:genesis": "./test/genesis/generate_genesis.test.sh" }, "keywords": [ - "Ethereum", "ZKP", + "Zero-Knowledge Proof", + "Decentralized", + "Permissionless", + "Type-1", + "ZK-EVM", "zkRollup", + "Ethereum", "Layer2" ], "author": "Taiko Labs", diff --git a/packages/protocol/script/DeployOnL1.s.sol b/packages/protocol/script/DeployOnL1.s.sol index e3e940b1596..afe41423e31 100644 --- a/packages/protocol/script/DeployOnL1.s.sol +++ b/packages/protocol/script/DeployOnL1.s.sol @@ -8,7 +8,8 @@ pragma solidity ^0.8.18; import "forge-std/Script.sol"; import "forge-std/console2.sol"; -import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; import "../contracts/L1/TaikoToken.sol"; import "../contracts/L1/TaikoL1.sol"; @@ -18,7 +19,6 @@ import "../contracts/signal/SignalService.sol"; import "../contracts/common/AddressManager.sol"; import "../contracts/test/erc20/FreeMintERC20.sol"; import "../contracts/test/erc20/MayFailFreeMintERC20.sol"; -import "../test/LibLn.sol"; contract DeployOnL1 is Script { using SafeCastUpgradeable for uint256; @@ -40,30 +40,26 @@ contract DeployOnL1 is Script { address public treasury = vm.envAddress("TREASURY"); - address public taikoTokenPremintRecipient = vm.envAddress("TAIKO_TOKEN_PREMINT_RECIPIENT"); + address public taikoTokenPremintRecipient = + vm.envAddress("TAIKO_TOKEN_PREMINT_RECIPIENT"); - uint256 public taikoTokenPremintAmount = vm.envUint("TAIKO_TOKEN_PREMINT_AMOUNT"); - - // Change it based on 'consensus' / experience / expected result - // Based in seconds. Please set carefully. - // For testnet it could be somewhere 85-100s - // For mainnet it could be around 1800 s (30mins) - // Can be adjusted later with setters - uint64 public INITIAL_PROOF_TIME_TARGET = uint64(vm.envUint("INITIAL_PROOF_TIME_TARGET")); - uint16 public ADJUSTMENT_QUOTIENT = uint16(vm.envUint("ADJUSTMENT_QUOTIENT")); + uint256 public taikoTokenPremintAmount = + vm.envUint("TAIKO_TOKEN_PREMINT_AMOUNT"); TaikoL1 taikoL1; address public addressManagerProxy; error FAILED_TO_DEPLOY_PLONK_VERIFIER(string contractPath); - error PROOF_TIME_TARGET_NOT_SET(); function run() external { require(owner != address(0), "owner is zero"); require(taikoL2Address != address(0), "taikoL2Address is zero"); require(l2SignalService != address(0), "l2SignalService is zero"); require(treasury != address(0), "treasury is zero"); - require(taikoTokenPremintRecipient != address(0), "taikoTokenPremintRecipient is zero"); + require( + taikoTokenPremintRecipient != address(0), + "taikoTokenPremintRecipient is zero" + ); require(taikoTokenPremintAmount < type(uint64).max, "premint too large"); vm.startBroadcast(deployerPrivateKey); @@ -71,7 +67,9 @@ contract DeployOnL1 is Script { // AddressManager AddressManager addressManager = new ProxiedAddressManager(); addressManagerProxy = deployProxy( - "address_manager", address(addressManager), bytes.concat(addressManager.init.selector) + "address_manager", + address(addressManager), + bytes.concat(addressManager.init.selector) ); // TaikoL1 @@ -99,7 +97,11 @@ contract DeployOnL1 is Script { bytes.concat( taikoToken.init.selector, abi.encode( - addressManagerProxy, "Taiko Token", "TKO", premintRecipients, premintAmounts + addressManagerProxy, + "Taiko Token", + "TKO", + premintRecipients, + premintAmounts ) ) ); @@ -108,35 +110,18 @@ contract DeployOnL1 is Script { address horseToken = address(new FreeMintERC20("Horse Token", "HORSE")); console2.log("HorseToken", horseToken); - address bullToken = address(new MayFailFreeMintERC20("Bull Token", "BLL")); + address bullToken = + address(new MayFailFreeMintERC20("Bull Token", "BLL")); console2.log("BullToken", bullToken); uint64 feeBase = uint64(1) ** taikoToken.decimals(); - // Calculating it for our needs based on testnet/mainnet. We need it in - // order to make the fees on the same level - in ideal circumstences. - // See Brecht's comment https://github.com/taikoxyz/taiko-mono/pull/13564 - if (INITIAL_PROOF_TIME_TARGET == 0) { - revert PROOF_TIME_TARGET_NOT_SET(); - } - - uint64 initProofTimeIssued = LibLn.calcInitProofTimeIssued( - feeBase, uint16(INITIAL_PROOF_TIME_TARGET), uint16(ADJUSTMENT_QUOTIENT) - ); - address taikoL1Proxy = deployProxy( "taiko", address(taikoL1), bytes.concat( taikoL1.init.selector, - abi.encode( - addressManagerProxy, - genesisHash, - feeBase, - INITIAL_PROOF_TIME_TARGET, - initProofTimeIssued, - uint16(ADJUSTMENT_QUOTIENT) - ) + abi.encode(addressManagerProxy, genesisHash, feeBase) ) ); setAddress("taiko", taikoL1Proxy); @@ -155,7 +140,9 @@ contract DeployOnL1 is Script { deployProxy( "token_vault", address(tokenVault), - bytes.concat(tokenVault.init.selector, abi.encode(addressManagerProxy)) + bytes.concat( + tokenVault.init.selector, abi.encode(addressManagerProxy) + ) ); // SignalService @@ -164,10 +151,14 @@ contract DeployOnL1 is Script { deployProxy( "signal_service", address(signalService), - bytes.concat(signalService.init.selector, abi.encode(addressManagerProxy)) + bytes.concat( + signalService.init.selector, abi.encode(addressManagerProxy) + ) ); } else { - console2.log("Warining: using shared signal service: ", sharedSignalService); + console2.log( + "Warining: using shared signal service: ", sharedSignalService + ); setAddress("signal_service", sharedSignalService); } @@ -179,14 +170,18 @@ contract DeployOnL1 is Script { function deployPlonkVerifiers() private { address[] memory plonkVerifiers = new address[](1); - plonkVerifiers[0] = deployYulContract("contracts/libs/yul/PlonkVerifier.yulp"); + plonkVerifiers[0] = + deployYulContract("contracts/libs/yul/PlonkVerifier.yulp"); for (uint16 i = 0; i < plonkVerifiers.length; ++i) { setAddress(taikoL1.getVerifierName(i), plonkVerifiers[i]); } } - function deployYulContract(string memory contractPath) private returns (address) { + function deployYulContract(string memory contractPath) + private + returns (address) + { string[] memory cmds = new string[](3); cmds[0] = "bash"; cmds[1] = "-c"; @@ -213,11 +208,17 @@ contract DeployOnL1 is Script { return deployedAddress; } - function deployProxy(string memory name, address implementation, bytes memory data) + function deployProxy( + string memory name, + address implementation, + bytes memory data + ) private returns (address proxy) { - proxy = address(new TransparentUpgradeableProxy(implementation, owner, data)); + proxy = address( + new TransparentUpgradeableProxy(implementation, owner, data) + ); console2.log(name, "(impl) ->", implementation); console2.log(name, "(proxy) ->", proxy); diff --git a/packages/protocol/script/DetermineNewProofTimeIssued.s.sol b/packages/protocol/script/DetermineNewProofTimeIssued.s.sol deleted file mode 100644 index 2c5f35d17c5..00000000000 --- a/packages/protocol/script/DetermineNewProofTimeIssued.s.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "forge-std/Script.sol"; -import "forge-std/console2.sol"; -import {LibLn} from "../test/LibLn.sol"; - -uint16 constant DESIRED_PROOF_TIME_TARGET = 160; -uint16 constant ADJUSTMENT_QUOTIENT = 32000; - -contract DetermineProofTimeIssued is Script { - function run() public view { - uint16 proofTimeTarget = DESIRED_PROOF_TIME_TARGET; // Approx. value which close to what is in the simulation - uint64 feeBase = 1e8; // 1 TKO - uint64 initProofTimeIssued = - LibLn.calcInitProofTimeIssued(feeBase, proofTimeTarget, ADJUSTMENT_QUOTIENT); - - console2.log("The proof time target is:", proofTimeTarget); - console2.log("The associated proof time issued is:", initProofTimeIssued); - } -} diff --git a/packages/protocol/script/test_deploy_on_l1.sh b/packages/protocol/script/test_deploy_on_l1.sh index 314e2246d5d..dfb8a4fe2ec 100755 --- a/packages/protocol/script/test_deploy_on_l1.sh +++ b/packages/protocol/script/test_deploy_on_l1.sh @@ -14,8 +14,6 @@ TAIKO_TOKEN_PREMINT_RECIPIENT=0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 \ TAIKO_TOKEN_PREMINT_AMOUNT=0xffff \ TREASURY=0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 \ L2_GENESIS_HASH=0xee1950562d42f0da28bd4550d88886bc90894c77c9c9eaefef775d4c8223f259 \ -INITIAL_PROOF_TIME_TARGET=101 \ -ADJUSTMENT_QUOTIENT=32000 \ forge script script/DeployOnL1.s.sol:DeployOnL1 \ --fork-url http://localhost:8545 \ --broadcast \ diff --git a/packages/protocol/test/Bridge.t.sol b/packages/protocol/test/Bridge.t.sol index 139e5115d50..ba3f147560b 100644 --- a/packages/protocol/test/Bridge.t.sol +++ b/packages/protocol/test/Bridge.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {IBridge, Bridge} from "../contracts/bridge/Bridge.sol"; -import {BridgeErrors} from "../contracts/bridge/BridgeErrors.sol"; -import {EtherVault} from "../contracts/bridge/EtherVault.sol"; -import {console2} from "forge-std/console2.sol"; -import {LibBridgeStatus} from "../contracts/bridge/libs/LibBridgeStatus.sol"; -import {SignalService} from "../contracts/signal/SignalService.sol"; -import {Test} from "forge-std/Test.sol"; -import {ICrossChainSync} from "../contracts/common/ICrossChainSync.sol"; +import { AddressManager } from "../contracts/common/AddressManager.sol"; +import { IBridge, Bridge } from "../contracts/bridge/Bridge.sol"; +import { BridgeErrors } from "../contracts/bridge/BridgeErrors.sol"; +import { EtherVault } from "../contracts/bridge/EtherVault.sol"; +import { console2 } from "forge-std/console2.sol"; +import { LibBridgeStatus } from "../contracts/bridge/libs/LibBridgeStatus.sol"; +import { SignalService } from "../contracts/signal/SignalService.sol"; +import { Test } from "forge-std/Test.sol"; +import { ICrossChainSync } from "../contracts/common/ICrossChainSync.sol"; contract BadReceiver { receive() external payable { @@ -54,7 +54,7 @@ contract BridgeTest is Test { EtherVault etherVault; SignalService signalService; PrankCrossChainSync crossChainSync; - uint256 destChainId = 19389; + uint256 destChainId = 19_389; address public constant Alice = 0x10020FCb72e27650651B05eD2CEcA493bC807Ba4; @@ -80,14 +80,20 @@ contract BridgeTest is Test { crossChainSync = new PrankCrossChainSync(); - addressManager.setAddress(block.chainid, "signal_service", address(signalService)); + addressManager.setAddress( + block.chainid, "signal_service", address(signalService) + ); - addressManager.setAddress(destChainId, "bridge", address(destChainBridge)); + addressManager.setAddress( + destChainId, "bridge", address(destChainBridge) + ); vm.stopPrank(); } - function test_send_message_ether_reverts_if_value_doesnt_match_expected() public { + function test_send_message_ether_reverts_if_value_doesnt_match_expected() + public + { uint256 amount = 1 wei; IBridge.Message memory message = newMessage({ owner: Alice, @@ -103,7 +109,9 @@ contract BridgeTest is Test { bridge.sendMessage(message); } - function test_send_message_ether_reverts_when_owner_is_zero_address() public { + function test_send_message_ether_reverts_when_owner_is_zero_address() + public + { uint256 amount = 1 wei; IBridge.Message memory message = newMessage({ owner: address(0), @@ -116,10 +124,12 @@ contract BridgeTest is Test { }); vm.expectRevert(BridgeErrors.B_OWNER_IS_NULL.selector); - bridge.sendMessage{value: amount}(message); + bridge.sendMessage{ value: amount }(message); } - function test_send_message_ether_reverts_when_dest_chain_is_not_enabled() public { + function test_send_message_ether_reverts_when_dest_chain_is_not_enabled() + public + { uint256 amount = 1 wei; IBridge.Message memory message = newMessage({ owner: Alice, @@ -132,10 +142,13 @@ contract BridgeTest is Test { }); vm.expectRevert(BridgeErrors.B_WRONG_CHAIN_ID.selector); - bridge.sendMessage{value: amount}(message); + bridge.sendMessage{ value: amount }(message); } - function test_send_message_ether_reverts_when_dest_chain_same_as_block_chainid() public { + function test_send_message_ether_reverts_when_dest_chain_same_as_block_chainid( + ) + public + { uint256 amount = 1 wei; IBridge.Message memory message = newMessage({ owner: Alice, @@ -148,7 +161,7 @@ contract BridgeTest is Test { }); vm.expectRevert(BridgeErrors.B_WRONG_CHAIN_ID.selector); - bridge.sendMessage{value: amount}(message); + bridge.sendMessage{ value: amount }(message); } function test_send_message_ether_reverts_when_to_is_zero_address() public { @@ -164,7 +177,7 @@ contract BridgeTest is Test { }); vm.expectRevert(BridgeErrors.B_WRONG_TO_ADDRESS.selector); - bridge.sendMessage{value: amount}(message); + bridge.sendMessage{ value: amount }(message); } function test_send_message_ether_with_no_processing_fee() public { @@ -179,7 +192,7 @@ contract BridgeTest is Test { destChain: destChainId }); - bytes32 msgHash = bridge.sendMessage{value: amount}(message); + bytes32 msgHash = bridge.sendMessage{ value: amount }(message); bool isMessageSent = bridge.isMessageSent(msgHash); assertEq(isMessageSent, true); @@ -198,13 +211,16 @@ contract BridgeTest is Test { destChain: destChainId }); - bytes32 msgHash = bridge.sendMessage{value: amount + processingFee}(message); + bytes32 msgHash = + bridge.sendMessage{ value: amount + processingFee }(message); bool isMessageSent = bridge.isMessageSent(msgHash); assertEq(isMessageSent, true); } - function test_send_message_ether_with_processing_fee_invalid_amount() public { + function test_send_message_ether_with_processing_fee_invalid_amount() + public + { uint256 amount = 1 wei; uint256 processingFee = 1 wei; IBridge.Message memory message = newMessage({ @@ -218,10 +234,11 @@ contract BridgeTest is Test { }); vm.expectRevert(BridgeErrors.B_INCORRECT_VALUE.selector); - bridge.sendMessage{value: amount}(message); + bridge.sendMessage{ value: amount }(message); } - // test with a known good merkle proof / message since we cant generate proofs via rpc + // test with a known good merkle proof / message since we cant generate + // proofs via rpc // in foundry function test_process_message() public { vm.startPrank(Alice); @@ -230,18 +247,21 @@ contract BridgeTest is Test { bytes32 msgHash = destChainBridge.hashMessage(message); - bool isMessageReceived = destChainBridge.isMessageReceived(msgHash, 1336, proof); + bool isMessageReceived = + destChainBridge.isMessageReceived(msgHash, 1336, proof); assertEq(isMessageReceived, true); destChainBridge.processMessage(message, proof); - LibBridgeStatus.MessageStatus status = destChainBridge.getMessageStatus(msgHash); + LibBridgeStatus.MessageStatus status = + destChainBridge.getMessageStatus(msgHash); assertEq(status == LibBridgeStatus.MessageStatus.DONE, true); } - // test with a known good merkle proof / message since we cant generate proofs via rpc + // test with a known good merkle proof / message since we cant generate + // proofs via rpc // in foundry function test_retry_message_and_end_up_in_failed_status() public { vm.startPrank(Alice); @@ -253,13 +273,15 @@ contract BridgeTest is Test { bytes32 msgHash = destChainBridge.hashMessage(message); - bool isMessageReceived = destChainBridge.isMessageReceived(msgHash, 1336, proof); + bool isMessageReceived = + destChainBridge.isMessageReceived(msgHash, 1336, proof); assertEq(isMessageReceived, true); destChainBridge.processMessage(message, proof); - LibBridgeStatus.MessageStatus status = destChainBridge.getMessageStatus(msgHash); + LibBridgeStatus.MessageStatus status = + destChainBridge.getMessageStatus(msgHash); assertEq(status == LibBridgeStatus.MessageStatus.RETRIABLE, true); @@ -268,7 +290,8 @@ contract BridgeTest is Test { destChainBridge.retryMessage(message, true); - LibBridgeStatus.MessageStatus postRetryStatus = destChainBridge.getMessageStatus(msgHash); + LibBridgeStatus.MessageStatus postRetryStatus = + destChainBridge.getMessageStatus(msgHash); assertEq(postRetryStatus == LibBridgeStatus.MessageStatus.FAILED, true); } @@ -279,7 +302,7 @@ contract BridgeTest is Test { to: Alice, depositValue: 1, callValue: 0, - gasLimit: 10000, + gasLimit: 10_000, processingFee: 1, destChain: destChainId }); @@ -288,14 +311,16 @@ contract BridgeTest is Test { destChainBridge.retryMessage(message, true); } - function retry_message_reverts_when_last_attempt_and_message_is_not_owner() public { + function retry_message_reverts_when_last_attempt_and_message_is_not_owner() + public + { vm.startPrank(Alice); IBridge.Message memory message = newMessage({ owner: Bob, to: Alice, depositValue: 1, callValue: 0, - gasLimit: 10000, + gasLimit: 10_000, processingFee: 1, destChain: destChainId }); @@ -313,7 +338,9 @@ contract BridgeTest is Test { uint256 dest = 1337; addressManager.setAddress(dest, "taiko", address(crossChainSync)); - addressManager.setAddress(1336, "bridge", 0x564540a26Fb667306b3aBdCB4ead35BEb88698ab); + addressManager.setAddress( + 1336, "bridge", 0x564540a26Fb667306b3aBdCB4ead35BEb88698ab + ); addressManager.setAddress(dest, "bridge", address(destChainBridge)); @@ -323,7 +350,9 @@ contract BridgeTest is Test { vm.deal(address(etherVault), 100 ether); - addressManager.setAddress(dest, "signal_service", address(signalService)); + addressManager.setAddress( + dest, "signal_service", address(signalService) + ); crossChainSync.setCrossChainBlockHeader( 0xd5f5d8ac6bc37139c97389b00e9cf53e89c153ad8a5fc765ffe9f44ea9f3d31e @@ -349,7 +378,7 @@ contract BridgeTest is Test { depositValue: 1000, callValue: 1000, processingFee: 1000, - gasLimit: 1000000, + gasLimit: 1_000_000, data: "", memo: "" }); @@ -368,7 +397,11 @@ contract BridgeTest is Test { uint256 gasLimit, uint256 processingFee, uint256 destChain - ) internal view returns (IBridge.Message memory) { + ) + internal + view + returns (IBridge.Message memory) + { return IBridge.Message({ owner: owner, destChainId: destChain, diff --git a/packages/protocol/test/EtherVault.t.sol b/packages/protocol/test/EtherVault.t.sol index d7fdbea7ddb..89d41cd36a2 100644 --- a/packages/protocol/test/EtherVault.t.sol +++ b/packages/protocol/test/EtherVault.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {EtherVault} from "../contracts/bridge/EtherVault.sol"; -import {BridgeErrors} from "../contracts/bridge/BridgeErrors.sol"; +import { Test } from "forge-std/Test.sol"; +import { AddressManager } from "../contracts/common/AddressManager.sol"; +import { EtherVault } from "../contracts/bridge/EtherVault.sol"; +import { BridgeErrors } from "../contracts/bridge/BridgeErrors.sol"; contract TestEtherVault is Test { AddressManager addressManager; @@ -46,7 +46,10 @@ contract TestEtherVault is Test { etherVault.authorize(address(0), true); } - function test_authorize_reverts_when_authorizing_already_authorized_address() public { + function test_authorize_reverts_when_authorizing_already_authorized_address( + ) + public + { vm.startPrank(Alice); etherVault.authorize(Bob, true); vm.expectRevert(BridgeErrors.B_EV_PARAM.selector); @@ -61,7 +64,7 @@ contract TestEtherVault is Test { assertEq(Alice.balance > 0, true); vm.startPrank(Alice); etherVault.authorize(Alice, true); - (bool aliceSent,) = address(etherVault).call{value: 1}(""); + (bool aliceSent,) = address(etherVault).call{ value: 1 }(""); assertEq(aliceSent, true); assertEq(address(etherVault).balance, 1); @@ -69,7 +72,7 @@ contract TestEtherVault is Test { assertEq(Bob.balance > 0, true); vm.startPrank(Bob); - (bool bobSent,) = address(etherVault).call{value: 1}(""); + (bool bobSent,) = address(etherVault).call{ value: 1 }(""); assertEq(bobSent, false); vm.stopPrank(); } @@ -95,7 +98,9 @@ contract TestEtherVault is Test { vm.stopPrank(); } - function test_release_ether_releases_to_receipient_via_authorized_sender() public { + function test_release_ether_releases_to_receipient_via_authorized_sender() + public + { vm.startPrank(Alice); etherVault.authorize(Alice, true); seedEtherVault(); diff --git a/packages/protocol/test/GasComparison.t.sol b/packages/protocol/test/GasComparison.t.sol index 013826eb782..6bc58da078d 100644 --- a/packages/protocol/test/GasComparison.t.sol +++ b/packages/protocol/test/GasComparison.t.sol @@ -5,11 +5,11 @@ import "forge-std/Test.sol"; import "forge-std/console2.sol"; import "../contracts/L1/TaikoData.sol"; import "../contracts/libs/LibAddress.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; library LibAddress2 { function sendEther(address to, uint256 amount) internal { - (bool success,) = payable(to).call{value: amount}(""); + (bool success,) = payable(to).call{ value: amount }(""); require(success, "ETH transfer failed"); } } @@ -31,9 +31,9 @@ contract FooBar { abi.decode(data, (MyStruct)); } - function loadBlockMetadata_3(MyStruct memory data) public pure {} + function loadBlockMetadata_3(MyStruct memory data) public pure { } - function loadBlockMetadata_4(MyStruct calldata data) public pure {} + function loadBlockMetadata_4(MyStruct calldata data) public pure { } function loadBlockMetadata_5(bytes calldata data) public pure { MyStruct memory meta; @@ -71,7 +71,11 @@ contract FooBar { meta.timestamp = uint64(uint256((a << (128 + 64)) >> (128 + 64))); } - function return_1() public view returns (TaikoData.BlockMetadata memory meta) { + function return_1() + public + view + returns (TaikoData.BlockMetadata memory meta) + { meta = TaikoData.BlockMetadata({ id: 1, l1Height: 1, @@ -106,24 +110,41 @@ contract FooBar { } //------ - function hashString_1(string memory str) public pure returns (bytes32 hash) { + function hashString_1(string memory str) + public + pure + returns (bytes32 hash) + { assembly { hash := keccak256(add(str, 32), mload(str)) } } - function hashString_2(string memory str) public pure returns (bytes32 hash) { + function hashString_2(string memory str) + public + pure + returns (bytes32 hash) + { hash = keccak256(bytes(str)); } //------ - function hashTwo_1(address a, bytes32 b) public pure returns (bytes32 hash) { + function hashTwo_1( + address a, + bytes32 b + ) + public + pure + returns (bytes32 hash) + { assembly { - // Load the free memory pointer and allocate memory for the concatenated arguments + // Load the free memory pointer and allocate memory for the + // concatenated arguments let input := mload(64) - // Store the app address and signal bytes32 value in the allocated memory + // Store the app address and signal bytes32 value in the allocated + // memory mstore(input, a) mstore(add(input, 32), b) @@ -134,7 +155,14 @@ contract FooBar { } } - function hashTwo_2(address a, bytes32 b) public pure returns (bytes32 hash) { + function hashTwo_2( + address a, + bytes32 b + ) + public + pure + returns (bytes32 hash) + { hash = keccak256(bytes.concat(bytes20(uint160(a)), b)); // the following will work too. // hash = keccak256(abi.encodePacked(a, b)); @@ -177,11 +205,25 @@ contract FooBar { } // ------ - function hashKey_1(uint256 chainId, string memory name) public pure returns (bytes32) { + function hashKey_1( + uint256 chainId, + string memory name + ) + public + pure + returns (bytes32) + { return keccak256(bytes(string.concat(Strings.toString(chainId), name))); } - function hashKey_2(uint256 chainId, string memory name) public pure returns (bytes32) { + function hashKey_2( + uint256 chainId, + string memory name + ) + public + pure + returns (bytes32) + { return keccak256(abi.encodePacked(chainId, name)); } diff --git a/packages/protocol/test/Lib1559Math.t.sol b/packages/protocol/test/Lib1559Math.t.sol index 492f4142549..7118f016b6e 100644 --- a/packages/protocol/test/Lib1559Math.t.sol +++ b/packages/protocol/test/Lib1559Math.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {Lib1559Math as T} from "../contracts/libs/Lib1559Math.sol"; -import {SafeCastUpgradeable} from +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { Lib1559Math as T } from "../contracts/libs/Lib1559Math.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; contract TestLib1559Math is Test { @@ -13,10 +13,10 @@ contract TestLib1559Math is Test { function test1559_2X1XRatio(uint16 rand) public { vm.assume(rand != 0); - uint64 xExcessMax = (uint256(15000000) * 256 * rand).toUint64(); - uint64 xTarget = (uint256(6000000) * rand).toUint64(); - uint64 price0 = (uint256(5000000000) * rand).toUint64(); - uint64 ratio2x1x = 11177; + uint64 xExcessMax = (uint256(15_000_000) * 256 * rand).toUint64(); + uint64 xTarget = (uint256(6_000_000) * rand).toUint64(); + uint64 price0 = (uint256(5_000_000_000) * rand).toUint64(); + uint64 ratio2x1x = 11_177; (uint128 xscale, uint128 yscale) = T.calculateScales({ xExcessMax: xExcessMax, price: price0, @@ -36,15 +36,17 @@ contract TestLib1559Math is Test { xExcess <= xExcessMax / 2 + N * xTarget; xExcess += xTarget ) { - uint256 basefee1 = T.calculatePrice(xscale, yscale, xExcess, xTarget); + uint256 basefee1 = + T.calculatePrice(xscale, yscale, xExcess, xTarget); assertLt(basefee1, type(uint64).max); - uint256 basefee2 = T.calculatePrice(xscale, yscale, xExcess, 2 * xTarget); + uint256 basefee2 = + T.calculatePrice(xscale, yscale, xExcess, 2 * xTarget); assertLt(basefee2, type(uint64).max); if (basefee1 != 0) { - assertEq((basefee2 * 10000) / basefee1, ratio2x1x); + assertEq((basefee2 * 10_000) / basefee1, ratio2x1x); } } } @@ -52,10 +54,10 @@ contract TestLib1559Math is Test { function test1559_SpecalCases(uint16 rand) public { vm.assume(rand != 0); - uint64 xExcessMax = (uint256(15000000) * 256 * rand).toUint64(); - uint64 xTarget = (uint256(6000000) * rand).toUint64(); - uint64 price0 = (uint256(5000000000) * rand).toUint64(); - uint64 ratio2x1x = 11177; + uint64 xExcessMax = (uint256(15_000_000) * 256 * rand).toUint64(); + uint64 xTarget = (uint256(6_000_000) * rand).toUint64(); + uint64 price0 = (uint256(5_000_000_000) * rand).toUint64(); + uint64 ratio2x1x = 11_177; (uint128 xscale, uint128 yscale) = T.calculateScales({ xExcessMax: xExcessMax, @@ -67,10 +69,18 @@ contract TestLib1559Math is Test { assertEq(T.calculatePrice(xscale, yscale, 0, 0), 0); assertEq(T.calculatePrice(xscale, yscale, 0, 1), 0); - assertGt(T.calculatePrice(xscale, yscale, xExcessMax - xTarget, xTarget), type(uint64).max); + assertGt( + T.calculatePrice(xscale, yscale, xExcessMax - xTarget, xTarget), + type(uint64).max + ); - assertGt(T.calculatePrice(xscale, yscale, 0, xExcessMax), type(uint64).max); + assertGt( + T.calculatePrice(xscale, yscale, 0, xExcessMax), type(uint64).max + ); - assertGt(T.calculatePrice(xscale, yscale, xExcessMax / 2, xExcessMax / 2), type(uint64).max); + assertGt( + T.calculatePrice(xscale, yscale, xExcessMax / 2, xExcessMax / 2), + type(uint64).max + ); } } diff --git a/packages/protocol/test/LibFixedPointMath.t.sol b/packages/protocol/test/LibFixedPointMath.t.sol index eefb54cc551..58c4617ac39 100644 --- a/packages/protocol/test/LibFixedPointMath.t.sol +++ b/packages/protocol/test/LibFixedPointMath.t.sol @@ -3,24 +3,30 @@ // https://github.com/recmo/experiment-solexp/blob/main/src/test/FixedPointMathLib.t.sol pragma solidity 0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; import "../contracts/thirdparty/LibFixedPointMath.sol"; contract LibFixedPointMathTest is Test { function testExp1() public { - assertEq(LibFixedPointMath.exp(-1e18), 367879441171442321); + assertEq(LibFixedPointMath.exp(-1e18), 367_879_441_171_442_321); } function testExpSmallest() public view { - int256 y = LibFixedPointMath.exp(-42139678854452767550); + int256 y = LibFixedPointMath.exp(-42_139_678_854_452_767_550); - console2.log("LibFixedPointMath.exp(-42139678854452767550)=", uint256(y)); + console2.log( + "LibFixedPointMath.exp(-42139678854452767550)=", uint256(y) + ); } function testExpLargest() public view { - int256 y = LibFixedPointMath.exp(int256(uint256(LibFixedPointMath.MAX_EXP_INPUT))); - console2.log("LibFixedPointMath.exp(135305999368893231588)=", uint256(y)); + int256 y = LibFixedPointMath.exp( + int256(uint256(LibFixedPointMath.MAX_EXP_INPUT)) + ); + console2.log( + "LibFixedPointMath.exp(135305999368893231588)=", uint256(y) + ); } function testExpSome() public view { diff --git a/packages/protocol/test/LibLn.sol b/packages/protocol/test/LibLn.sol deleted file mode 100644 index cc1ad45fdd4..00000000000 --- a/packages/protocol/test/LibLn.sol +++ /dev/null @@ -1,215 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -// Taken from: https://github.com/recmo/experiment-solexp/blob/main/src/FixedPointMathLib.sol -import {LibFixedPointMath} from "../contracts/thirdparty/LibFixedPointMath.sol"; - -library LibLn { - error Overflow(); - error LnNegativeUndefined(); - - // Integer log2 (alternative implementation) - // @returns floor(log2(x)) if x is nonzero, otherwise 0. - // Consumes 317 gas. This could have been an 3 gas EVM opcode though. - function ilog2_alt(uint256 x) internal pure returns (uint256 r) { - unchecked { - // Repeat first zero all the way to the right - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - x |= x >> 32; - x |= x >> 64; - x |= x >> 128; - - // Count 32 bit chunks - r = x & 0x100000001000000010000000100000001000000010000000100000001; - r *= 0x20000000200000002000000020000000200000002000000020; - r >>= 224; - - // Extract highest bit - x ^= x >> 1; - - // Copy to lowest 32 bit chunk - x |= x >> 32; - x |= x >> 64; - x |= x >> 128; - // No need to clear the other chunks - - // Map to 0-31 using the B(2, 5) de Bruijn sequence 0x077CB531. - // See - x = ((x * 0x077CB531) >> 27) & 0x1f; - - // Use a bytes32 32 entry lookup table - assembly { - // Need assembly here because solidity introduces an uncessary bounds - // check. - r := - add(r, byte(x, 0x11c021d0e18031e16140f191104081f1b0d17151310071a0c12060b050a09)) - } - } - } - - // Integer log2 - // @returns floor(log2(x)) if x is nonzero, otherwise 0. This is the same - // as the location of the highest set bit. - // Consumes 232 gas. This could have been an 3 gas EVM opcode though. - function ilog2(uint256 x) internal pure returns (uint256 r) { - assembly { - r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) - r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) - r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) - r := or(r, shl(4, lt(0xffff, shr(r, x)))) - r := or(r, shl(3, lt(0xff, shr(r, x)))) - r := or(r, shl(2, lt(0xf, shr(r, x)))) - r := or(r, shl(1, lt(0x3, shr(r, x)))) - r := or(r, lt(0x1, shr(r, x))) - } - } - - function ln_pub(int256 x) public pure returns (int256 r) { - return ln(x); - } - - // Computes ln(x) in 1e18 fixed point. - // Reverts if x is negative or zero. - // Consumes 670 gas. - function ln(int256 x) internal pure returns (int256 r) { - unchecked { - if (x < 1) { - if (x < 0) revert LnNegativeUndefined(); - revert Overflow(); - } - - // We want to convert x from 10**18 fixed point to 2**96 fixed point. - // We do this by multiplying by 2**96 / 10**18. - // But since ln(x * C) = ln(x) + ln(C), we can simply do nothing here - // and add ln(2**96 / 10**18) at the end. - - // Reduce range of x to (1, 2) * 2**96 - // ln(2^k * x) = k * ln(2) + ln(x) - // Note: inlining ilog2 saves 8 gas. - int256 k = int256(ilog2(uint256(x))) - 96; - x <<= uint256(159 - k); - x = int256(uint256(x) >> 159); - - // Evaluate using a (8, 8)-term rational approximation - // p is made monic, we will multiply by a scale factor later - int256 p = x + 3273285459638523848632254066296; - p = ((p * x) >> 96) + 24828157081833163892658089445524; - p = ((p * x) >> 96) + 43456485725739037958740375743393; - p = ((p * x) >> 96) - 11111509109440967052023855526967; - p = ((p * x) >> 96) - 45023709667254063763336534515857; - p = ((p * x) >> 96) - 14706773417378608786704636184526; - p = p * x - (795164235651350426258249787498 << 96); - //emit log_named_int("p", p); - // We leave p in 2**192 basis so we don't need to scale it back up for the division. - // q is monic by convention - int256 q = x + 5573035233440673466300451813936; - q = ((q * x) >> 96) + 71694874799317883764090561454958; - q = ((q * x) >> 96) + 283447036172924575727196451306956; - q = ((q * x) >> 96) + 401686690394027663651624208769553; - q = ((q * x) >> 96) + 204048457590392012362485061816622; - q = ((q * x) >> 96) + 31853899698501571402653359427138; - q = ((q * x) >> 96) + 909429971244387300277376558375; - assembly { - // Div in assembly because solidity adds a zero check despite the `unchecked`. - // The q polynomial is known not to have zeros in the domain. (All roots are complex) - // No scaling required because p is already 2**96 too large. - r := sdiv(p, q) - } - // r is in the range (0, 0.125) * 2**96 - - // Finalization, we need to - // * multiply by the scale factor s = 5.549… - // * add ln(2**96 / 10**18) - // * add k * ln(2) - // * multiply by 10**18 / 2**96 = 5**18 >> 78 - // mul s * 5e18 * 2**96, base is now 5**18 * 2**192 - r *= 1677202110996718588342820967067443963516166; - // add ln(2) * k * 5e18 * 2**192 - r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k; - // add ln(2**96 / 10**18) * 5e18 * 2**192 - r += 600920179829731861736702779321621459595472258049074101567377883020018308; - // base conversion: mul 2**18 / 2**192 - r >>= 174; - } - } - - // Computes e^x in 1e18 fixed point. - function exp(int256 x) internal pure returns (int256 r) { - unchecked { - // Input x is in fixed point format, with scale factor 1/1e18. - - // When the result is < 0.5 we return zero. This happens when - // x <= floor(log(0.5e18) * 1e18) ~ -42e18 - if (x <= -42139678854452767551) { - return 0; - } - - // When the result is > (2**255 - 1) / 1e18 we can not represent it - // as an int256. This happens when x >= floor(log((2**255 -1) / 1e18) * 1e18) ~ 135. - if (x >= 135305999368893231589) revert Overflow(); - - // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96 - // for more intermediate precision and a binary basis. This base conversion - // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. - x = (x << 78) / 5 ** 18; - - // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers of two - // such that exp(x) = exp(x') * 2**k, where k is an integer. - // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). - int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96; - x = x - k * 54916777467707473351141471128; - // k is in the range [-61, 195]. - - // Evaluate using a (6, 7)-term rational approximation - // p is made monic, we will multiply by a scale factor later - int256 p = x + 2772001395605857295435445496992; - p = ((p * x) >> 96) + 44335888930127919016834873520032; - p = ((p * x) >> 96) + 398888492587501845352592340339721; - p = ((p * x) >> 96) + 1993839819670624470859228494792842; - p = p * x + (4385272521454847904632057985693276 << 96); - // We leave p in 2**192 basis so we don't need to scale it back up for the division. - // Evaluate using using Knuth's scheme from p. 491. - int256 z = x + 750530180792738023273180420736; - z = ((z * x) >> 96) + 32788456221302202726307501949080; - int256 w = x - 2218138959503481824038194425854; - w = ((w * z) >> 96) + 892943633302991980437332862907700; - int256 q = z + w - 78174809823045304726920794422040; - q = ((q * w) >> 96) + 4203224763890128580604056984195872; - assembly { - // Div in assembly because solidity adds a zero check despite the `unchecked`. - // The q polynomial is known not to have zeros in the domain. (All roots are complex) - // No scaling required because p is already 2**96 too large. - r := sdiv(p, q) - } - // r should be in the range (0.09, 0.25) * 2**96. - - // We now need to multiply r by - // * the scale factor s = ~6.031367120..., - // * the 2**k factor from the range reduction, and - // * the 1e18 / 2**96 factor for base converison. - // We do all of this at once, with an intermediate result in 2**213 basis - // so the final right shift is always by a positive amount. - r = int256( - (uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k) - ); - } - } - - function calcInitProofTimeIssued( - uint64 basefee, - uint16 proofTimeTarget, - uint16 adjustmentQuotient - ) public pure returns (uint64 initProofTimeIssued) { - uint256 scale = uint256(proofTimeTarget) * adjustmentQuotient; - // ln_pub() expects 1e18 fixed format - uint256 lnReq = scale * basefee * LibFixedPointMath.SCALING_FACTOR_1E18; - require(lnReq <= uint256(type(int256).max)); - int256 log_result = ln_pub(int256(lnReq)); - initProofTimeIssued = - uint64(((scale * (uint256(log_result))) / (LibFixedPointMath.SCALING_FACTOR_1E18))); - } -} diff --git a/packages/protocol/test/SignalService.t.sol b/packages/protocol/test/SignalService.t.sol index 28703cac0f5..9a009c40842 100644 --- a/packages/protocol/test/SignalService.t.sol +++ b/packages/protocol/test/SignalService.t.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {AddressResolver} from "../contracts/common/AddressResolver.sol"; -import {Bridge} from "../contracts/bridge/Bridge.sol"; -import {BridgedERC20} from "../contracts/bridge/BridgedERC20.sol"; -import {BridgeErrors} from "../contracts/bridge/BridgeErrors.sol"; -import {console2} from "forge-std/console2.sol"; -import {FreeMintERC20} from "../contracts/test/erc20/FreeMintERC20.sol"; -import {SignalService} from "../contracts/signal/SignalService.sol"; -import {Test} from "forge-std/Test.sol"; -import {ICrossChainSync} from "../contracts/common/ICrossChainSync.sol"; +import { AddressManager } from "../contracts/common/AddressManager.sol"; +import { AddressResolver } from "../contracts/common/AddressResolver.sol"; +import { Bridge } from "../contracts/bridge/Bridge.sol"; +import { BridgedERC20 } from "../contracts/bridge/BridgedERC20.sol"; +import { BridgeErrors } from "../contracts/bridge/BridgeErrors.sol"; +import { console2 } from "forge-std/console2.sol"; +import { FreeMintERC20 } from "../contracts/test/erc20/FreeMintERC20.sol"; +import { SignalService } from "../contracts/signal/SignalService.sol"; +import { Test } from "forge-std/Test.sol"; +import { ICrossChainSync } from "../contracts/common/ICrossChainSync.sol"; contract PrankCrossChainSync is ICrossChainSync { bytes32 private _blockHash; @@ -61,11 +61,17 @@ contract TestSignalService is Test { crossChainSync = new PrankCrossChainSync(); - addressManager.setAddress(block.chainid, "signal_service", address(signalService)); + addressManager.setAddress( + block.chainid, "signal_service", address(signalService) + ); - addressManager.setAddress(destChainId, "signal_service", address(destSignalService)); + addressManager.setAddress( + destChainId, "signal_service", address(destSignalService) + ); - addressManager.setAddress(block.chainid, "signal_service", address(signalService)); + addressManager.setAddress( + block.chainid, "signal_service", address(signalService) + ); addressManager.setAddress(destChainId, "taiko", address(crossChainSync)); @@ -98,7 +104,9 @@ contract TestSignalService is Test { assertEq(isSent, true); } - function test_get_signal_slot_returns_expected_slot_for_app_and_signal() public { + function test_get_signal_slot_returns_expected_slot_for_app_and_signal() + public + { vm.startPrank(Alice); for (uint8 i = 1; i < 100; i++) { bytes32 signal = bytes32(block.difficulty + i); @@ -109,13 +117,17 @@ contract TestSignalService is Test { bytes32 slot = signalService.getSignalSlot(Alice, signal); - // confirm our assembly gives same output as expected native solidity hash/packing + // confirm our assembly gives same output as expected native + // solidity hash/packing bytes32 expectedSlot = keccak256(abi.encodePacked(Alice, signal)); assertEq(slot, expectedSlot); } } - function test_is_signal_received_reverts_if_src_chain_id_is_same_as_block_chain_id() public { + function test_is_signal_received_reverts_if_src_chain_id_is_same_as_block_chain_id( + ) + public + { bytes32 signal = bytes32(uint256(1)); bytes memory proof = new bytes(1); vm.expectRevert(SignalService.B_WRONG_CHAIN_ID.selector); @@ -144,9 +156,12 @@ contract TestSignalService is Test { } function test_is_signal_received() public { - // known signal with known proof for known block header/signalRoot from a known chain ID + // known signal with known proof for known block header/signalRoot from + // a known chain ID // of 1336, since we cant generate merkle proofs with foundry. - bytes32 signal = bytes32(0xa99d658793daba4d352c77378e2d0f3b12ff47503518b3ec9ad61bb33ee7031d); + bytes32 signal = bytes32( + 0xa99d658793daba4d352c77378e2d0f3b12ff47503518b3ec9ad61bb33ee7031d + ); bytes memory proof = hex"0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000003e0d5c45a5c0fabac05a887ad983965a225214df2cecd77adc216d3b1172866b1e91dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493470000000000000000000000000000000000000000000000000000000000000000cba38a70215ae3eeba2e97f9b6c3c804541484202953760c1cfe734df6dfce7cf7f7ed1e57a053e1c79765d6b76305193cae04261538400724837787437e621c9e6a8ea258a11278cf2e54d0e4845843837a1da42483ebe1dddf3eed1d33088b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000099c8ac000000000000000000000000000000000000000000000000000000000000ac7500000000000000000000000000000000000000000000000000000000644311c100000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000164c61e700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061d883010a1a846765746888676f312e31382e38856c696e757800000000000000def5020e30ddc20e32151adb608a5d8367d817a707ae8d520c98ac13de04bce35f95ef795a9c4fd13d3e5daf713525521043125bde66aa71eed7ca715f05c720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dbf8d9b8b3f8b18080a04fc5f13ab2f9ba0c2da88b0151ab0e7cf4d85d08cca45ccd923c6ab76323eb28a02b70a98baa2507beffe8c266006cae52064dccf4fd1998af774ab3399029b38380808080a07394a09684ef3b2c87e9e2a753eb4ac78e2047b980e16d2e2133aee78946370d8080a0f4984a11f61a2921456141df88de6e1a710d28681b91af794c5a721e47839cd7a00f6329feca1549bd3bf7ab9a2e474bde37cb4f81366fca1dfdd9257c7305b5b880808080a3e2a037a8317247f2d3e645fa68570a9ae97a73b5568fe0578b90197316c654138997010000000000"; @@ -159,7 +174,8 @@ contract TestSignalService is Test { vm.chainId(destChainId); - bool isReceived = destSignalService.isSignalReceived(1336, Carol, signal, proof); + bool isReceived = + destSignalService.isSignalReceived(1336, Carol, signal, proof); assertEq(isReceived, true); } diff --git a/packages/protocol/test/SignalServiceCalc.t.sol b/packages/protocol/test/SignalServiceCalc.t.sol index dff49be514c..1652f564aeb 100644 --- a/packages/protocol/test/SignalServiceCalc.t.sol +++ b/packages/protocol/test/SignalServiceCalc.t.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {LibRLPWriter} from "../contracts/thirdparty/LibRLPWriter.sol"; +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { LibRLPWriter } from "../contracts/thirdparty/LibRLPWriter.sol"; contract TestSignalServiceCalc is Test { - function setUp() public {} + function setUp() public { } function testLibRLPWriterOne() public { assertEq(LibRLPWriter.writeBytes32(bytes32(uint256(1))), hex"01"); diff --git a/packages/protocol/test/Taiko1559Params.t.sol b/packages/protocol/test/Taiko1559Params.t.sol index 512b0376094..ecafda2a4f9 100644 --- a/packages/protocol/test/Taiko1559Params.t.sol +++ b/packages/protocol/test/Taiko1559Params.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {Lib1559Math as T} from "../contracts/libs/Lib1559Math.sol"; -import {TaikoL2} from "../contracts/L2/TaikoL2.sol"; -import {SafeCastUpgradeable} from +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { Lib1559Math as T } from "../contracts/libs/Lib1559Math.sol"; +import { TaikoL2 } from "../contracts/L2/TaikoL2.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; contract TestTaiko1559Params is Test { @@ -19,13 +19,14 @@ contract TestTaiko1559Params is Test { uint64 costFactor = 25; // Calculate gas space issuance per second - uint64 ethereumBlockGasTarget = 15000000; + uint64 ethereumBlockGasTarget = 15_000_000; uint64 ethereumBlockTime = 12; // https://ultrasound.money/ - uint64 ethereumBasefeeNow = 28000000000; // 28Gwei + uint64 ethereumBasefeeNow = 28_000_000_000; // 28Gwei - uint64 gasIssuedPerSecond = (scaleFactor * ethereumBlockGasTarget) / ethereumBlockTime; + uint64 gasIssuedPerSecond = + (scaleFactor * ethereumBlockGasTarget) / ethereumBlockTime; // Tune this number manually so ratio2x1x is ~112.5%. uint64 maxSeconds = 7272; @@ -39,8 +40,8 @@ contract TestTaiko1559Params is Test { gasIssuedPerSecond: gasIssuedPerSecond, gasExcessMax: gasExcessMax, gasTarget: gasIssuedPerSecond * ethereumBlockTime, - ratio2x1x: 11250 // ~12.5% increase - }); + ratio2x1x: 11_250 // ~12.5% increase + }); console2.log("basefee :", param1559.basefee); console2.log("gasIssuedPerSecond:", param1559.gasIssuedPerSecond); diff --git a/packages/protocol/test/TaikoL1.sim.sol b/packages/protocol/test/TaikoL1.sim.sol index 725f72aa12d..2f55bc38fdd 100644 --- a/packages/protocol/test/TaikoL1.sim.sol +++ b/packages/protocol/test/TaikoL1.sim.sol @@ -1,28 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {TaikoConfig} from "../contracts/L1/TaikoConfig.sol"; -import {TaikoData} from "../contracts/L1/TaikoData.sol"; -import {TaikoL1} from "../contracts/L1/TaikoL1.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {TaikoL1TestBase} from "./TaikoL1TestBase.t.sol"; -import {LibLn} from "./LibLn.sol"; - -/// @dev Tweak this if you iwhs to set - the config and the calculation of the proofTimeIssued -/// @dev also originates from this -uint16 constant INITIAL_PROOF_TIME_TARGET = 160; - -// Need to test (solve) the problem where in the middle of the testnet, the fee is low already - like our internal devnet now - -// but we dont want to lose data with redeploying the contract. Upgrade also does not work because we need to change all -// proof reward / prover fee related variable with one go. -uint16 constant READJUSTED_ADJUSTMENT_QUOTIENT = 32000; +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { TaikoConfig } from "../contracts/L1/TaikoConfig.sol"; +import { TaikoData } from "../contracts/L1/TaikoData.sol"; +import { TaikoL1 } from "../contracts/L1/TaikoL1.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; +import { TaikoL1TestBase } from "./TaikoL1TestBase.t.sol"; /// @dev Warning: this test will take 7-10 minutes and require 1GB memory. /// `pnpm sim` contract TaikoL1_b is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() + public + pure + override + returns (TaikoData.Config memory config) + { config = TaikoConfig.getConfig(); config.txListCacheExpiry = 0; @@ -43,7 +38,7 @@ contract Verifier { contract TaikoL1Simulation is TaikoL1TestBase { // Need to bring variable declaration here - to avoid stack too deep // Initial salt for semi-random generation - uint256 salt = 2195684615435261315311; + uint256 salt = 2_195_684_615_435_261_315_311; // Can play to adjust uint256 blocksToSimulate = 4000; // RandomNumber - pseudo random but fine @@ -52,16 +47,21 @@ contract TaikoL1Simulation is TaikoL1TestBase { ////////////////////////////////////////// // TUNABLE PARAMS // ////////////////////////////////////////// - // This means block proposals will be averaged out (long term if random function is random enough) to 18s - // It is fine it simulates that we do not necessarily put Taiko block at every 12s, but on average around every x1.5 of ETH block - // Meaninig we have less blocks / sec. (We should test what happens if quicker!) + // This means block proposals will be averaged out (long term if random + // function is random enough) to 18s + // It is fine it simulates that we do not necessarily put Taiko block at + // every 12s, but on average around every x1.5 of ETH block + // Meaninig we have less blocks / sec. (We should test what happens if + // quicker!) uint256 nextBlockTime = 8 seconds; uint256 minDiffToBlockPropTime = 8 seconds; - // This means block provings will be averaged out (long term if random function is random enough) to 200s + // This means block provings will be averaged out (long term if random + // function is random enough) to 200s uint256 startBlockProposeTime = 70 seconds; uint256 upperDevToBlockProveTime = 40 seconds; - uint256 secondsToSimulate = blocksToSimulate * 18; //Because of the expected average blocktimestamp - we can tweak it obv. + uint256 secondsToSimulate = blocksToSimulate * 18; //Because of the expected + // average blocktimestamp - we can tweak it obv. ////////////////////////////////////////// // TUNABLE PARAMS END // ////////////////////////////////////////// @@ -70,7 +70,8 @@ contract TaikoL1Simulation is TaikoL1TestBase { uint256 totalDiffsProve = 0; uint256 lastTimestampProp = 0; uint256 lastTimestampProve = 0; - // Need to map a second to a proofTIme, and might be possible that multiple proofs coming in the same block + // Need to map a second to a proofTIme, and might be possible that multiple + // proofs coming in the same block mapping(uint256 proofTimeSecond => uint256[] arrivalIdxOfBlockIds) private _proofTimeToBlockIndexes; // Pre-calculate propose and prove timestamp @@ -90,22 +91,17 @@ contract TaikoL1Simulation is TaikoL1TestBase { } function setUp() public override { - proofTimeTarget = INITIAL_PROOF_TIME_TARGET; // Approx. value which close to what is in the simulation - - initProofTimeIssued = LibLn.calcInitProofTimeIssued(feeBase, proofTimeTarget, 16); // This 16 is a low value (=quick curve)! Will re-adjust at the middle of the simulation, to test update scenario! - TaikoL1TestBase.setUp(); - registerAddress(L1.getVerifierName(100), address(new Verifier())); } // A real world scenario - function xtestGeneratingManyRandomBlocksNonConsecutive() external { + function testGeneratingManyRandomBlocksNonConsecutive() external { uint256 time = block.timestamp; assertEq(time, 1); - depositTaikoToken(Alice, 1e9 * 1e8, 10000 ether); + depositTaikoToken(Alice, 1e9 * 1e8, 10_000 ether); TaikoData.BlockMetadata[] memory metas = new TaikoData.BlockMetadata[]( blocksToSimulate @@ -117,12 +113,21 @@ contract TaikoL1Simulation is TaikoL1TestBase { newRandomWithoutSalt = uint256( keccak256( abi.encodePacked( - block.difficulty, msg.sender, block.timestamp, i, newRandomWithoutSalt, salt + block.difficulty, + msg.sender, + block.timestamp, + i, + newRandomWithoutSalt, + salt ) ) ); blocksProposedTimestamp[i] = uint64( - pickRandomNumber(newRandomWithoutSalt, nextBlockTime, (minDiffToBlockPropTime + 1)) + pickRandomNumber( + newRandomWithoutSalt, + nextBlockTime, + (minDiffToBlockPropTime + 1) + ) ); nextBlockTime = blocksProposedTimestamp[i] + minDiffToBlockPropTime; @@ -134,168 +139,14 @@ contract TaikoL1Simulation is TaikoL1TestBase { lastTimestampProp = blocksProposedTimestamp[i]; // We need this info to extract / export !! //console2.log("Time of PROPOSAL is:", blocksProposedTimestamp[i]); - salt = - uint256(keccak256(abi.encodePacked(nextBlockTime, salt, i, newRandomWithoutSalt))); - - uint64 proofTimePerBlockI = uint64( - pickRandomNumber( - newRandomWithoutSalt, - (nextBlockTime + startBlockProposeTime), - (upperDevToBlockProveTime + 1) - ) - ); - - if (proofTimePerBlockI > maxTime) { - maxTime = proofTimePerBlockI; - } - - if (lastTimestampProve > 0) { - totalDiffsProve += proofTimePerBlockI - lastTimestampProp; - } - lastTimestampProve = proofTimePerBlockI; - // It is possible that proof for block N+1 comes before N, so we need to keep track of that. Because - // the proofs per block is related to propose of that same block (index). - _proofTimeToBlockIndexes[proofTimePerBlockI].push(i); - - // We need this info to extract / export !! - console2.log(i + 1, ";", proofTimePerBlockI - lastTimestampProp); - salt = uint256(keccak256(abi.encodePacked(proofTimePerBlockI, salt))); - } - - uint256 proposedIndex; - - console2.log("Last second:", maxTime); - console2.log("Proof time target:", INITIAL_PROOF_TIME_TARGET); - console2.log("Average proposal time: ", totalDiffsProp / blocksToSimulate); - console2.log("Average proof time: ", totalDiffsProve / blocksToSimulate); - printVariableHeaders(); - //It is a divider / marker for the parser - console2.log("!-----------------------------"); - printVariables(); - // This is a way we can de-couple proposing from proving - for (uint256 secondsElapsed = 0; secondsElapsed <= maxTime; secondsElapsed++) { - newRandomWithoutSalt = uint256( + salt = uint256( keccak256( abi.encodePacked( - newRandomWithoutSalt, - block.difficulty, - secondsElapsed, - msg.sender, - block.timestamp, - salt + nextBlockTime, salt, i, newRandomWithoutSalt ) ) ); - // We are proposing here - if ( - secondsElapsed == blocksProposedTimestamp[proposedIndex] - && proposedIndex < blocksToSimulate - ) { - //console2.log("FOR CYCLE: Time of PROPOSAL is:", blocksProposedTimestamp[proposedIndex]); - uint32 gasLimit = - uint32(pickRandomNumber(newRandomWithoutSalt, 100e3, (3000000 - 100000 + 1))); // 100K to 30M - salt = uint256(keccak256(abi.encodePacked(gasLimit, salt))); - - if (proposedIndex == 0) { - parentGasUsed[proposedIndex] = 0; - parentHashes[proposedIndex] = GENESIS_BLOCK_HASH; - } else { - parentGasUsed[proposedIndex] = gasUsed[proposedIndex - 1]; - parentHashes[proposedIndex] = blockHashes[proposedIndex - 1]; - } - - gasUsed[proposedIndex] = uint32( - pickRandomNumber(newRandomWithoutSalt, (gasLimit / 2), ((gasLimit / 2) + 1)) - ); - salt = uint256(keccak256(abi.encodePacked(gasUsed, salt))); - - uint24 txListSize = uint24( - pickRandomNumber(newRandomWithoutSalt, 1, conf.maxBytesPerTxList) //Actually (conf.maxBytesPerTxList-1)+1 but that's the same - ); - salt = uint256(keccak256(abi.encodePacked(txListSize, salt))); - - blockHashes[proposedIndex] = - bytes32(pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max)); - salt = uint256(keccak256(abi.encodePacked(blockHashes[proposedIndex], salt))); - - signalRoots[proposedIndex] = - bytes32(pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max)); - salt = uint256(keccak256(abi.encodePacked(signalRoots[proposedIndex], salt))); - - metas[proposedIndex] = proposeBlock(Alice, gasLimit, txListSize); - - if (proposedIndex < blocksToSimulate - 1) proposedIndex++; - - printVariables(); - } - - // We are proving here - if (_proofTimeToBlockIndexes[secondsElapsed].length > 0) { - //console2.log("Duplicates check"); - for (uint256 i; i < _proofTimeToBlockIndexes[secondsElapsed].length; i++) { - uint256 blockId = _proofTimeToBlockIndexes[secondsElapsed][i]; - - proveBlock( - Bob, - Bob, - metas[blockId], - parentHashes[blockId], - parentGasUsed[blockId], - gasUsed[blockId], - blockHashes[blockId], - signalRoots[blockId] - ); - } - } - - // Increment time with 1 seconds - vm.warp(block.timestamp + 1); - //Log every 12 sec - if (block.timestamp % 12 == 0) { - printVariables(); - } - } - console2.log("-----------------------------!"); - } - - function test_scenario_where_blockfee_dumped_but_we_reset_parameters() external { - uint256 time = block.timestamp; - - assertEq(time, 1); - - depositTaikoToken(Alice, 1e9 * 1e8, 10000 ether); - - TaikoData.BlockMetadata[] memory metas = new TaikoData.BlockMetadata[]( - blocksToSimulate - ); - - // Determine every timestamp of the block we want to simulate - console2.log("BlockId, ProofTime"); - for (uint256 i = 0; i < blocksToSimulate; i++) { - newRandomWithoutSalt = uint256( - keccak256( - abi.encodePacked( - block.difficulty, msg.sender, block.timestamp, i, newRandomWithoutSalt, salt - ) - ) - ); - blocksProposedTimestamp[i] = uint64( - pickRandomNumber(newRandomWithoutSalt, nextBlockTime, (minDiffToBlockPropTime + 1)) - ); - nextBlockTime = blocksProposedTimestamp[i] + minDiffToBlockPropTime; - - // Avg. calculation - if (lastTimestampProp > 0) { - totalDiffsProp += blocksProposedTimestamp[i] - lastTimestampProp; - } - - lastTimestampProp = blocksProposedTimestamp[i]; - // We need this info to extract / export !! - //console2.log("Time of PROPOSAL is:", blocksProposedTimestamp[i]); - salt = - uint256(keccak256(abi.encodePacked(nextBlockTime, salt, i, newRandomWithoutSalt))); - uint64 proofTimePerBlockI = uint64( pickRandomNumber( newRandomWithoutSalt, @@ -312,38 +163,35 @@ contract TaikoL1Simulation is TaikoL1TestBase { totalDiffsProve += proofTimePerBlockI - lastTimestampProp; } lastTimestampProve = proofTimePerBlockI; - // It is possible that proof for block N+1 comes before N, so we need to keep track of that. Because - // the proofs per block is related to propose of that same block (index). + // It is possible that proof for block N+1 comes before N, so we + // need to keep track of that. Because + // the proofs per block is related to propose of that same block + // (index). _proofTimeToBlockIndexes[proofTimePerBlockI].push(i); // We need this info to extract / export !! console2.log(i + 1, ";", proofTimePerBlockI - lastTimestampProp); - salt = uint256(keccak256(abi.encodePacked(proofTimePerBlockI, salt))); + salt = + uint256(keccak256(abi.encodePacked(proofTimePerBlockI, salt))); } uint256 proposedIndex; console2.log("Last second:", maxTime); - console2.log("Proof time target:", INITIAL_PROOF_TIME_TARGET); - console2.log("Average proposal time: ", totalDiffsProp / blocksToSimulate); + console2.log( + "Average proposal time: ", totalDiffsProp / blocksToSimulate + ); console2.log("Average proof time: ", totalDiffsProve / blocksToSimulate); printVariableHeaders(); //It is a divider / marker for the parser console2.log("!-----------------------------"); printVariables(); // This is a way we can de-couple proposing from proving - for (uint256 secondsElapsed = 0; secondsElapsed <= maxTime; secondsElapsed++) { - if (secondsElapsed == maxTime / 3) { - //console2.log("MIkor jovok be ide?:", i); - //Reset the parameters - initProofTimeIssued = LibLn.calcInitProofTimeIssued( - feeBase, proofTimeTarget, READJUSTED_ADJUSTMENT_QUOTIENT - ); - L1.setProofParams( - proofTimeTarget, initProofTimeIssued, feeBase, READJUSTED_ADJUSTMENT_QUOTIENT - ); - } - + for ( + uint256 secondsElapsed = 0; + secondsElapsed <= maxTime; + secondsElapsed++ + ) { newRandomWithoutSalt = uint256( keccak256( abi.encodePacked( @@ -362,9 +210,13 @@ contract TaikoL1Simulation is TaikoL1TestBase { secondsElapsed == blocksProposedTimestamp[proposedIndex] && proposedIndex < blocksToSimulate ) { - //console2.log("FOR CYCLE: Time of PROPOSAL is:", blocksProposedTimestamp[proposedIndex]); - uint32 gasLimit = - uint32(pickRandomNumber(newRandomWithoutSalt, 100e3, (3000000 - 100000 + 1))); // 100K to 30M + //console2.log("FOR CYCLE: Time of PROPOSAL is:", + // blocksProposedTimestamp[proposedIndex]); + uint32 gasLimit = uint32( + pickRandomNumber( + newRandomWithoutSalt, 100e3, (3_000_000 - 100_000 + 1) + ) + ); // 100K to 30M salt = uint256(keccak256(abi.encodePacked(gasLimit, salt))); if (proposedIndex == 0) { @@ -376,22 +228,39 @@ contract TaikoL1Simulation is TaikoL1TestBase { } gasUsed[proposedIndex] = uint32( - pickRandomNumber(newRandomWithoutSalt, (gasLimit / 2), ((gasLimit / 2) + 1)) + pickRandomNumber( + newRandomWithoutSalt, + (gasLimit / 2), + ((gasLimit / 2) + 1) + ) ); salt = uint256(keccak256(abi.encodePacked(gasUsed, salt))); uint24 txListSize = uint24( - pickRandomNumber(newRandomWithoutSalt, 1, conf.maxBytesPerTxList) //Actually (conf.maxBytesPerTxList-1)+1 but that's the same + pickRandomNumber( + newRandomWithoutSalt, 1, conf.maxBytesPerTxList + ) //Actually (conf.maxBytesPerTxList-1)+1 but that's the + // same ); salt = uint256(keccak256(abi.encodePacked(txListSize, salt))); - blockHashes[proposedIndex] = - bytes32(pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max)); - salt = uint256(keccak256(abi.encodePacked(blockHashes[proposedIndex], salt))); + blockHashes[proposedIndex] = bytes32( + pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max) + ); + salt = uint256( + keccak256( + abi.encodePacked(blockHashes[proposedIndex], salt) + ) + ); - signalRoots[proposedIndex] = - bytes32(pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max)); - salt = uint256(keccak256(abi.encodePacked(signalRoots[proposedIndex], salt))); + signalRoots[proposedIndex] = bytes32( + pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max) + ); + salt = uint256( + keccak256( + abi.encodePacked(signalRoots[proposedIndex], salt) + ) + ); metas[proposedIndex] = proposeBlock(Alice, gasLimit, txListSize); @@ -403,8 +272,13 @@ contract TaikoL1Simulation is TaikoL1TestBase { // We are proving here if (_proofTimeToBlockIndexes[secondsElapsed].length > 0) { //console2.log("Duplicates check"); - for (uint256 i; i < _proofTimeToBlockIndexes[secondsElapsed].length; i++) { - uint256 blockId = _proofTimeToBlockIndexes[secondsElapsed][i]; + for ( + uint256 i; + i < _proofTimeToBlockIndexes[secondsElapsed].length; + i++ + ) { + uint256 blockId = + _proofTimeToBlockIndexes[secondsElapsed][i]; proveBlock( Bob, @@ -430,15 +304,17 @@ contract TaikoL1Simulation is TaikoL1TestBase { } // 90% slow proofs (around 30 mins or so) and 10% (around 1-5 mins ) - function xtest_90percent_slow_10percent_quick() external { + function test_90percent_slow_10percent_quick() external { uint256 time = block.timestamp; - uint256 startBlockProposeTime_quick = 60 seconds; // For the 10% where it is 'quick' - uint256 upperDevToBlockProveTime_quick = 240 seconds; // For the 10% where it is quick + uint256 startBlockProposeTime_quick = 60 seconds; // For the 10% where + // it is 'quick' + uint256 upperDevToBlockProveTime_quick = 240 seconds; // For the 10% + // where it is quick assertEq(time, 1); - depositTaikoToken(Alice, 1e6 * 1e8, 10000 ether); + depositTaikoToken(Alice, 1e6 * 1e8, 10_000 ether); TaikoData.BlockMetadata[] memory metas = new TaikoData.BlockMetadata[]( blocksToSimulate @@ -450,12 +326,21 @@ contract TaikoL1Simulation is TaikoL1TestBase { newRandomWithoutSalt = uint256( keccak256( abi.encodePacked( - block.difficulty, msg.sender, block.timestamp, i, newRandomWithoutSalt, salt + block.difficulty, + msg.sender, + block.timestamp, + i, + newRandomWithoutSalt, + salt ) ) ); blocksProposedTimestamp[i] = uint64( - pickRandomNumber(newRandomWithoutSalt, nextBlockTime, (minDiffToBlockPropTime + 1)) + pickRandomNumber( + newRandomWithoutSalt, + nextBlockTime, + (minDiffToBlockPropTime + 1) + ) ); nextBlockTime = blocksProposedTimestamp[i] + minDiffToBlockPropTime; @@ -467,8 +352,13 @@ contract TaikoL1Simulation is TaikoL1TestBase { lastTimestampProp = blocksProposedTimestamp[i]; // We need this info to extract / export !! //console2.log("Time of PROPOSAL is:", blocksProposedTimestamp[i]); - salt = - uint256(keccak256(abi.encodePacked(nextBlockTime, salt, i, newRandomWithoutSalt))); + salt = uint256( + keccak256( + abi.encodePacked( + nextBlockTime, salt, i, newRandomWithoutSalt + ) + ) + ); uint64 proofTimePerBlockI; if (i % 10 == 0) { // A very quick proof this case @@ -501,27 +391,35 @@ contract TaikoL1Simulation is TaikoL1TestBase { totalDiffsProve += proofTimePerBlockI - lastTimestampProp; } lastTimestampProve = proofTimePerBlockI; - // It is possible that proof for block N+1 comes before N, so we need to keep track of that. Because - // the proofs per block is related to propose of that same block (index). + // It is possible that proof for block N+1 comes before N, so we + // need to keep track of that. Because + // the proofs per block is related to propose of that same block + // (index). _proofTimeToBlockIndexes[proofTimePerBlockI].push(i); // We need this info to extract / export !! console2.log(i + 1, ";", proofTimePerBlockI - lastTimestampProp); - salt = uint256(keccak256(abi.encodePacked(proofTimePerBlockI, salt))); + salt = + uint256(keccak256(abi.encodePacked(proofTimePerBlockI, salt))); } uint256 proposedIndex; console2.log("Last second:", maxTime); - console2.log("Proof time target:", INITIAL_PROOF_TIME_TARGET); - console2.log("Average proposal time: ", totalDiffsProp / blocksToSimulate); + console2.log( + "Average proposal time: ", totalDiffsProp / blocksToSimulate + ); console2.log("Average proof time: ", totalDiffsProve / blocksToSimulate); printVariableHeaders(); //It is a divider / marker for the parser console2.log("!-----------------------------"); printVariables(); // This is a way we can de-couple proposing from proving - for (uint256 secondsElapsed = 0; secondsElapsed <= maxTime; secondsElapsed++) { + for ( + uint256 secondsElapsed = 0; + secondsElapsed <= maxTime; + secondsElapsed++ + ) { newRandomWithoutSalt = uint256( keccak256( abi.encodePacked( @@ -540,9 +438,13 @@ contract TaikoL1Simulation is TaikoL1TestBase { secondsElapsed == blocksProposedTimestamp[proposedIndex] && proposedIndex < blocksToSimulate ) { - //console2.log("FOR CYCLE: Time of PROPOSAL is:", blocksProposedTimestamp[proposedIndex]); - uint32 gasLimit = - uint32(pickRandomNumber(newRandomWithoutSalt, 100e3, (3000000 - 100000 + 1))); // 100K to 30M + //console2.log("FOR CYCLE: Time of PROPOSAL is:", + // blocksProposedTimestamp[proposedIndex]); + uint32 gasLimit = uint32( + pickRandomNumber( + newRandomWithoutSalt, 100e3, (3_000_000 - 100_000 + 1) + ) + ); // 100K to 30M salt = uint256(keccak256(abi.encodePacked(gasLimit, salt))); if (proposedIndex == 0) { @@ -554,22 +456,39 @@ contract TaikoL1Simulation is TaikoL1TestBase { } gasUsed[proposedIndex] = uint32( - pickRandomNumber(newRandomWithoutSalt, (gasLimit / 2), ((gasLimit / 2) + 1)) + pickRandomNumber( + newRandomWithoutSalt, + (gasLimit / 2), + ((gasLimit / 2) + 1) + ) ); salt = uint256(keccak256(abi.encodePacked(gasUsed, salt))); uint24 txListSize = uint24( - pickRandomNumber(newRandomWithoutSalt, 1, conf.maxBytesPerTxList) //Actually (conf.maxBytesPerTxList-1)+1 but that's the same + pickRandomNumber( + newRandomWithoutSalt, 1, conf.maxBytesPerTxList + ) //Actually (conf.maxBytesPerTxList-1)+1 but that's the + // same ); salt = uint256(keccak256(abi.encodePacked(txListSize, salt))); - blockHashes[proposedIndex] = - bytes32(pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max)); - salt = uint256(keccak256(abi.encodePacked(blockHashes[proposedIndex], salt))); + blockHashes[proposedIndex] = bytes32( + pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max) + ); + salt = uint256( + keccak256( + abi.encodePacked(blockHashes[proposedIndex], salt) + ) + ); - signalRoots[proposedIndex] = - bytes32(pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max)); - salt = uint256(keccak256(abi.encodePacked(signalRoots[proposedIndex], salt))); + signalRoots[proposedIndex] = bytes32( + pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max) + ); + salt = uint256( + keccak256( + abi.encodePacked(signalRoots[proposedIndex], salt) + ) + ); metas[proposedIndex] = proposeBlock(Alice, gasLimit, txListSize); @@ -581,8 +500,13 @@ contract TaikoL1Simulation is TaikoL1TestBase { // We are proving here if (_proofTimeToBlockIndexes[secondsElapsed].length > 0) { //console2.log("Duplicates check"); - for (uint256 i; i < _proofTimeToBlockIndexes[secondsElapsed].length; i++) { - uint256 blockId = _proofTimeToBlockIndexes[secondsElapsed][i]; + for ( + uint256 i; + i < _proofTimeToBlockIndexes[secondsElapsed].length; + i++ + ) { + uint256 blockId = + _proofTimeToBlockIndexes[secondsElapsed][i]; proveBlock( Bob, @@ -608,14 +532,16 @@ contract TaikoL1Simulation is TaikoL1TestBase { } // 90% slow proofs (around 30 mins or so) and 10% (around 1-5 mins ) - function xtest_90percent_quick_10percent_slow() external { + function test_90percent_quick_10percent_slow() external { uint256 time = block.timestamp; - uint256 startBlockProposeTime_quick = 60 seconds; // For the 10% where it is 'quick' - uint256 upperDevToBlockProveTime_quick = 240 seconds; // For the 10% where it is quick + uint256 startBlockProposeTime_quick = 60 seconds; // For the 10% where + // it is 'quick' + uint256 upperDevToBlockProveTime_quick = 240 seconds; // For the 10% + // where it is quick assertEq(time, 1); - depositTaikoToken(Alice, 1e6 * 1e8, 10000 ether); + depositTaikoToken(Alice, 1e6 * 1e8, 10_000 ether); TaikoData.BlockMetadata[] memory metas = new TaikoData.BlockMetadata[]( blocksToSimulate @@ -627,12 +553,21 @@ contract TaikoL1Simulation is TaikoL1TestBase { newRandomWithoutSalt = uint256( keccak256( abi.encodePacked( - block.difficulty, msg.sender, block.timestamp, i, newRandomWithoutSalt, salt + block.difficulty, + msg.sender, + block.timestamp, + i, + newRandomWithoutSalt, + salt ) ) ); blocksProposedTimestamp[i] = uint64( - pickRandomNumber(newRandomWithoutSalt, nextBlockTime, (minDiffToBlockPropTime + 1)) + pickRandomNumber( + newRandomWithoutSalt, + nextBlockTime, + (minDiffToBlockPropTime + 1) + ) ); nextBlockTime = blocksProposedTimestamp[i] + minDiffToBlockPropTime; @@ -644,8 +579,13 @@ contract TaikoL1Simulation is TaikoL1TestBase { lastTimestampProp = blocksProposedTimestamp[i]; // We need this info to extract / export !! //console2.log("Time of PROPOSAL is:", blocksProposedTimestamp[i]); - salt = - uint256(keccak256(abi.encodePacked(nextBlockTime, salt, i, newRandomWithoutSalt))); + salt = uint256( + keccak256( + abi.encodePacked( + nextBlockTime, salt, i, newRandomWithoutSalt + ) + ) + ); uint64 proofTimePerBlockI; if (i % 10 == 0) { @@ -684,27 +624,35 @@ contract TaikoL1Simulation is TaikoL1TestBase { totalDiffsProve += proofTimePerBlockI - lastTimestampProp; } lastTimestampProve = proofTimePerBlockI; - // It is possible that proof for block N+1 comes before N, so we need to keep track of that. Because - // the proofs per block is related to propose of that same block (index). + // It is possible that proof for block N+1 comes before N, so we + // need to keep track of that. Because + // the proofs per block is related to propose of that same block + // (index). _proofTimeToBlockIndexes[proofTimePerBlockI].push(i); // We need this info to extract / export !! console2.log(i + 1, ";", proofTimePerBlockI - lastTimestampProp); - salt = uint256(keccak256(abi.encodePacked(proofTimePerBlockI, salt))); + salt = + uint256(keccak256(abi.encodePacked(proofTimePerBlockI, salt))); } uint256 proposedIndex; console2.log("Last second:", maxTime); - console2.log("Proof time target:", INITIAL_PROOF_TIME_TARGET); - console2.log("Average proposal time: ", totalDiffsProp / blocksToSimulate); + console2.log( + "Average proposal time: ", totalDiffsProp / blocksToSimulate + ); console2.log("Average proof time: ", totalDiffsProve / blocksToSimulate); printVariableHeaders(); //It is a divider / marker for the parser console2.log("!-----------------------------"); printVariables(); // This is a way we can de-couple proposing from proving - for (uint256 secondsElapsed = 0; secondsElapsed <= maxTime; secondsElapsed++) { + for ( + uint256 secondsElapsed = 0; + secondsElapsed <= maxTime; + secondsElapsed++ + ) { newRandomWithoutSalt = uint256( keccak256( abi.encodePacked( @@ -723,9 +671,13 @@ contract TaikoL1Simulation is TaikoL1TestBase { secondsElapsed == blocksProposedTimestamp[proposedIndex] && proposedIndex < blocksToSimulate ) { - //console2.log("FOR CYCLE: Time of PROPOSAL is:", blocksProposedTimestamp[proposedIndex]); - uint32 gasLimit = - uint32(pickRandomNumber(newRandomWithoutSalt, 100e3, (3000000 - 100000 + 1))); // 100K to 30M + //console2.log("FOR CYCLE: Time of PROPOSAL is:", + // blocksProposedTimestamp[proposedIndex]); + uint32 gasLimit = uint32( + pickRandomNumber( + newRandomWithoutSalt, 100e3, (3_000_000 - 100_000 + 1) + ) + ); // 100K to 30M salt = uint256(keccak256(abi.encodePacked(gasLimit, salt))); if (proposedIndex == 0) { @@ -737,22 +689,39 @@ contract TaikoL1Simulation is TaikoL1TestBase { } gasUsed[proposedIndex] = uint32( - pickRandomNumber(newRandomWithoutSalt, (gasLimit / 2), ((gasLimit / 2) + 1)) + pickRandomNumber( + newRandomWithoutSalt, + (gasLimit / 2), + ((gasLimit / 2) + 1) + ) ); salt = uint256(keccak256(abi.encodePacked(gasUsed, salt))); uint24 txListSize = uint24( - pickRandomNumber(newRandomWithoutSalt, 1, conf.maxBytesPerTxList) //Actually (conf.maxBytesPerTxList-1)+1 but that's the same + pickRandomNumber( + newRandomWithoutSalt, 1, conf.maxBytesPerTxList + ) //Actually (conf.maxBytesPerTxList-1)+1 but that's the + // same ); salt = uint256(keccak256(abi.encodePacked(txListSize, salt))); - blockHashes[proposedIndex] = - bytes32(pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max)); - salt = uint256(keccak256(abi.encodePacked(blockHashes[proposedIndex], salt))); + blockHashes[proposedIndex] = bytes32( + pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max) + ); + salt = uint256( + keccak256( + abi.encodePacked(blockHashes[proposedIndex], salt) + ) + ); - signalRoots[proposedIndex] = - bytes32(pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max)); - salt = uint256(keccak256(abi.encodePacked(signalRoots[proposedIndex], salt))); + signalRoots[proposedIndex] = bytes32( + pickRandomNumber(newRandomWithoutSalt, 0, type(uint256).max) + ); + salt = uint256( + keccak256( + abi.encodePacked(signalRoots[proposedIndex], salt) + ) + ); metas[proposedIndex] = proposeBlock(Alice, gasLimit, txListSize); @@ -764,8 +733,13 @@ contract TaikoL1Simulation is TaikoL1TestBase { // We are proving here if (_proofTimeToBlockIndexes[secondsElapsed].length > 0) { //console2.log("Duplicates check"); - for (uint256 i; i < _proofTimeToBlockIndexes[secondsElapsed].length; i++) { - uint256 blockId = _proofTimeToBlockIndexes[secondsElapsed][i]; + for ( + uint256 i; + i < _proofTimeToBlockIndexes[secondsElapsed].length; + i++ + ) { + uint256 blockId = + _proofTimeToBlockIndexes[secondsElapsed][i]; proveBlock( Bob, @@ -797,8 +771,7 @@ contract TaikoL1Simulation is TaikoL1TestBase { "time,", "lastVerifiedBlockId,", "numBlocks,", - "blockFee,", - "accProposedAt" + "blockFee," ); console2.log(str); } @@ -815,9 +788,7 @@ contract TaikoL1Simulation is TaikoL1TestBase { ";", Strings.toString(vars.numBlocks), ";", - Strings.toString(vars.blockFee), - ";", - Strings.toString(vars.accProposedAt) + Strings.toString(vars.blockFee) ); console2.log(str); } @@ -827,7 +798,11 @@ contract TaikoL1Simulation is TaikoL1TestBase { uint256 randomNum, uint256 lowerLimit, uint256 diffBtwLowerAndUpperLimit - ) internal view returns (uint256) { + ) + internal + view + returns (uint256) + { randomNum = uint256(keccak256(abi.encodePacked(randomNum, salt))); return (lowerLimit + (randomNum % diffBtwLowerAndUpperLimit)); } diff --git a/packages/protocol/test/TaikoL1.t.sol b/packages/protocol/test/TaikoL1.t.sol index 64206e90df4..bbe93892944 100644 --- a/packages/protocol/test/TaikoL1.t.sol +++ b/packages/protocol/test/TaikoL1.t.sol @@ -1,20 +1,25 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {LibEthDepositing} from "../contracts/L1/libs/LibEthDepositing.sol"; -import {TaikoConfig} from "../contracts/L1/TaikoConfig.sol"; -import {TaikoData} from "../contracts/L1/TaikoData.sol"; -import {TaikoL1} from "../contracts/L1/TaikoL1.sol"; -import {TaikoToken} from "../contracts/L1/TaikoToken.sol"; -import {SignalService} from "../contracts/signal/SignalService.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {TaikoL1TestBase} from "./TaikoL1TestBase.t.sol"; +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { AddressManager } from "../contracts/common/AddressManager.sol"; +import { LibEthDepositing } from "../contracts/L1/libs/LibEthDepositing.sol"; +import { TaikoConfig } from "../contracts/L1/TaikoConfig.sol"; +import { TaikoData } from "../contracts/L1/TaikoData.sol"; +import { TaikoL1 } from "../contracts/L1/TaikoL1.sol"; +import { TaikoToken } from "../contracts/L1/TaikoToken.sol"; +import { SignalService } from "../contracts/signal/SignalService.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; +import { TaikoL1TestBase } from "./TaikoL1TestBase.t.sol"; contract TaikoL1_NoCooldown is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() + public + pure + override + returns (TaikoData.Config memory config) + { config = TaikoConfig.getConfig(); config.txListCacheExpiry = 5 minutes; @@ -42,7 +47,8 @@ contract TaikoL1Test is TaikoL1TestBase { registerAddress(L1.getVerifierName(100), address(new Verifier())); } - /// @dev Test we can propose, prove, then verify more blocks than 'maxNumProposedBlocks' + /// @dev Test we can propose, prove, then verify more blocks than + /// 'maxNumProposedBlocks' function test_more_blocks_than_ring_buffer_size() external { depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); @@ -50,17 +56,31 @@ contract TaikoL1Test is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; + uint32 gasUsed = 1_000_000; - for (uint256 blockId = 1; blockId < conf.maxNumProposedBlocks * 10; blockId++) { + for ( + uint256 blockId = 1; + blockId < conf.maxNumProposedBlocks * 10; + blockId++ + ) { printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); printVariables("after propose"); mine(1); bytes32 blockHash = bytes32(1e10 + blockId); bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock(Bob, Bob, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot); + proveBlock( + Bob, + Bob, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot + ); verifyBlock(Carol, 1); parentHash = blockHash; @@ -76,17 +96,25 @@ contract TaikoL1Test is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; + uint32 gasUsed = 1_000_000; for (uint256 blockId = 1; blockId <= 2; blockId++) { printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); printVariables("after propose"); bytes32 blockHash = bytes32(1e10 + blockId); bytes32 signalRoot = bytes32(1e9 + blockId); proveBlock( - Alice, Alice, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot + Alice, + Alice, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot ); verifyBlock(Alice, 2); parentHash = blockHash; @@ -101,17 +129,27 @@ contract TaikoL1Test is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; + uint32 gasUsed = 1_000_000; - for (uint256 blockId = 1; blockId <= conf.maxNumProposedBlocks; blockId++) { + for ( + uint256 blockId = 1; blockId <= conf.maxNumProposedBlocks; blockId++ + ) { printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); printVariables("after propose"); bytes32 blockHash = bytes32(1e10 + blockId); bytes32 signalRoot = bytes32(1e9 + blockId); proveBlock( - Alice, Alice, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot + Alice, + Alice, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot ); parentHash = blockHash; parentGasUsed = gasUsed; @@ -131,11 +169,11 @@ contract TaikoL1Test is TaikoL1TestBase { vm.prank(Alice, Alice); vm.expectRevert(); - L1.depositEtherToL2{value: minAmount - 1}(); + L1.depositEtherToL2{ value: minAmount - 1 }(); vm.prank(Alice, Alice); vm.expectRevert(); - L1.depositEtherToL2{value: maxAmount + 1}(); + L1.depositEtherToL2{ value: maxAmount + 1 }(); assertEq(L1.getStateVariables().nextEthDepositToProcess, 0); assertEq(L1.getStateVariables().numEthDeposits, 0); @@ -146,10 +184,11 @@ contract TaikoL1Test is TaikoL1TestBase { bytes32 emptyDepositsRoot = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; - depositTaikoToken(Alice, 1e6 * 1e8, 100000 ether); + depositTaikoToken(Alice, 1e6 * 1e8, 100_000 ether); - proposeBlock(Alice, 1000000, 1024); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + proposeBlock(Alice, 1_000_000, 1024); + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); assertEq(meta.depositsProcessed.length, 0); uint256 count = conf.maxEthDepositsPerBlock; @@ -157,26 +196,30 @@ contract TaikoL1Test is TaikoL1TestBase { printVariables("before sending ethers"); for (uint256 i; i < count; ++i) { vm.prank(Alice, Alice); - L1.depositEtherToL2{value: (i + 1) * 1 ether}(); + L1.depositEtherToL2{ value: (i + 1) * 1 ether }(); } printVariables("after sending ethers"); uint256 gas = gasleft(); - meta = proposeBlock(Alice, 1000000, 1024); + meta = proposeBlock(Alice, 1_000_000, 1024); uint256 gasUsedWithDeposits = gas - gasleft(); console2.log("gas used with eth deposits:", gasUsedWithDeposits); printVariables("after processing send-ethers"); - assertTrue(LibEthDepositing.hashEthDeposits(meta.depositsProcessed) != emptyDepositsRoot); + assertTrue( + LibEthDepositing.hashEthDeposits(meta.depositsProcessed) + != emptyDepositsRoot + ); assertEq(meta.depositsProcessed.length, count + 1); gas = gasleft(); - meta = proposeBlock(Alice, 1000000, 1024); + meta = proposeBlock(Alice, 1_000_000, 1024); uint256 gasUsedWithoutDeposits = gas - gasleft(); console2.log("gas used without eth deposits:", gasUsedWithoutDeposits); - uint256 gasPerEthDeposit = (gasUsedWithDeposits - gasUsedWithoutDeposits) / count; + uint256 gasPerEthDeposit = + (gasUsedWithDeposits - gasUsedWithoutDeposits) / count; console2.log("gas per eth deposit:", gasPerEthDeposit); console2.log("maxEthDepositsPerBlock:", count); @@ -202,12 +245,12 @@ contract TaikoL1Test is TaikoL1TestBase { bytes32[] memory parentHashes = new bytes32[](iterationCnt); parentHashes[0] = GENESIS_BLOCK_HASH; - depositTaikoToken(Alice, 1e6 * 1e8, 100000 ether); + depositTaikoToken(Alice, 1e6 * 1e8, 100_000 ether); // Propose blocks for (uint256 blockId = 1; blockId < iterationCnt; blockId++) { //printVariables("before propose"); - meta = proposeBlock(Alice, 1000000, 1024); + meta = proposeBlock(Alice, 1_000_000, 1024); mine(5); blockHash = bytes32(1e10 + blockId); @@ -218,8 +261,8 @@ contract TaikoL1Test is TaikoL1TestBase { Bob, meta, parentHashes[blockId - 1], - blockId == 1 ? 0 : 1000000, - 1000000, + blockId == 1 ? 0 : 1_000_000, + 1_000_000, blockHash, signalRoot ); @@ -264,29 +307,35 @@ contract TaikoL1Test is TaikoL1TestBase { // So after this point we have 8 deposits vm.prank(Alice, Alice); - L1.depositEtherToL2{value: 1 ether}(); + L1.depositEtherToL2{ value: 1 ether }(); vm.prank(Bob, Bob); - L1.depositEtherToL2{value: 2 ether}(); + L1.depositEtherToL2{ value: 2 ether }(); vm.prank(Carol, Carol); - L1.depositEtherToL2{value: 3 ether}(); + L1.depositEtherToL2{ value: 3 ether }(); vm.prank(Dave, Dave); - L1.depositEtherToL2{value: 4 ether}(); + L1.depositEtherToL2{ value: 4 ether }(); vm.prank(Eve, Eve); - L1.depositEtherToL2{value: 5 ether}(); + L1.depositEtherToL2{ value: 5 ether }(); vm.prank(Frank, Frank); - L1.depositEtherToL2{value: 6 ether}(); + L1.depositEtherToL2{ value: 6 ether }(); vm.prank(George, George); - L1.depositEtherToL2{value: 7 ether}(); + L1.depositEtherToL2{ value: 7 ether }(); vm.prank(Hilbert, Hilbert); - L1.depositEtherToL2{value: 8 ether}(); + L1.depositEtherToL2{ value: 8 ether }(); - assertEq(L1.getStateVariables().numEthDeposits, 8); // The number of deposits - assertEq(L1.getStateVariables().nextEthDepositToProcess, 0); // The index / cursos of the next deposit + assertEq(L1.getStateVariables().numEthDeposits, 8); // The number of + // deposits + assertEq(L1.getStateVariables().nextEthDepositToProcess, 0); // The + // index / cursos of the next deposit - // We shall invoke proposeBlock() because this is what will call the processDeposits() - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + // We shall invoke proposeBlock() because this is what will call the + // processDeposits() + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); - // Expected: 0x8117066d69ff650d78f0d7383a10cc802c2b8c0eedd932d70994252e2438c636 (pre calculated with these values) + // Expected: + // 0x8117066d69ff650d78f0d7383a10cc802c2b8c0eedd932d70994252e2438c636 (pre + // calculated with these values) //console2.logBytes32(meta.depositsRoot); assertEq( LibEthDepositing.hashEthDeposits(meta.depositsProcessed), diff --git a/packages/protocol/test/TaikoL1LibTokenomicsMainnet.t.sol b/packages/protocol/test/TaikoL1LibTokenomicsMainnet.t.sol deleted file mode 100644 index ebfa41e53f5..00000000000 --- a/packages/protocol/test/TaikoL1LibTokenomicsMainnet.t.sol +++ /dev/null @@ -1,285 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.18; - -// Uncomment if you want to compare fee/vs reward -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {TaikoConfig} from "../contracts/L1/TaikoConfig.sol"; -import {TaikoData} from "../contracts/L1/TaikoData.sol"; -import {TaikoL1} from "../contracts/L1/TaikoL1.sol"; -import {TaikoToken} from "../contracts/L1/TaikoToken.sol"; -import {SignalService} from "../contracts/signal/SignalService.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {TaikoL1TestBase} from "./TaikoL1TestBase.t.sol"; -import {LibLn} from "./LibLn.sol"; - -/// @dev Tweak this if you iwhs to set - the config and the calculation of the proofTimeIssued -/// @dev also originates from this -uint16 constant INITIAL_PROOF_TIME_TARGET = 2160; //sec. Approx mainnet scenario - -contract TaikoL1MainnetMockConfig is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { - config = TaikoConfig.getConfig(); - - config.txListCacheExpiry = 5 minutes; - config.maxVerificationsPerTx = 1; - config.maxNumProposedBlocks = 200; - config.ringBufferSize = 240; - config.proofCooldownPeriod = 0; - } -} - -contract TaikoL1LibTokenomicsMainnet is TaikoL1TestBase { - // To avoid stack too deep error - // Can play to adjust - uint32 iterationCnt = 5000; - uint8 proofTime = 180; // When proofs are coming, 180 means 180 sec - // Check balances - uint256 Alice_start_balance; - uint256 Bob_start_balance; - - function deployTaikoL1() internal override returns (TaikoL1 taikoL1) { - taikoL1 = new TaikoL1MainnetMockConfig(); - } - - function setUp() public override { - proofTimeTarget = INITIAL_PROOF_TIME_TARGET; // Approx. mainnet value - // Calculating it for our needs based on testnet/mainnet proof vars. - // See Brecht's comment https://github.com/taikoxyz/taiko-mono/pull/13564 - initProofTimeIssued = - LibLn.calcInitProofTimeIssued(feeBase, proofTimeTarget, ADJUSTMENT_QUOTIENT); - - TaikoL1TestBase.setUp(); - - depositTaikoToken(Alice, 1e8 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e8 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e8 * 1e8, 100 ether); - - Alice_start_balance = L1.getTaikoTokenBalance(Alice); - Bob_start_balance = L1.getTaikoTokenBalance(Bob); - } - - /// @dev A possible (close to) mainnet scenarios is the following: - //// - Blocks ever 10 seconds proposed - //// - Proofs coming shifted slightly below 30 min / proposed block afterwards - //// Expected result: Withdrawals and deposits are in balance but keep shrinking since quicker proofTime - function xtest_possible_mainnet_scenario_proof_time_below_target() external { - vm.pauseGasMetering(); - mine(1); - - depositTaikoToken(Alice, 1e8 * 1e8, 1000 ether); - depositTaikoToken(Bob, 1e8 * 1e8, 1000 ether); - depositTaikoToken(Carol, 1e8 * 1e8, 1000 ether); - - // Check balances - Alice_start_balance = L1.getTaikoTokenBalance(Alice); - Bob_start_balance = L1.getTaikoTokenBalance(Bob); - - // Can play to adjust - proofTime = 179; // When proofs are coming, 179 means 1790 sec - - TaikoData.BlockMetadata[] memory meta = new TaikoData.BlockMetadata[]( - iterationCnt - ); - uint64[] memory proposedAt = new uint64[](iterationCnt); - bytes32[] memory parentHashes = new bytes32[](iterationCnt); - bytes32[] memory blockHashes = new bytes32[](iterationCnt); - bytes32[] memory signalRoots = new bytes32[](iterationCnt); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - console2.logBytes32(parentHash); - - // Run another session with huge times - for (uint256 blockId = 1; blockId < iterationCnt; blockId++) { - meta[blockId] = proposeBlock(Alice, 1000000, 1024); - proposedAt[blockId] = (uint64(block.timestamp)); - printVariables("after propose"); - blockHashes[blockId] = bytes32(1e10 + blockId); - signalRoots[blockId] = bytes32(1e9 + blockId); - - if (blockId > proofTime) { - //Start proving with an offset - proveBlock( - Bob, - Bob, - meta[blockId - proofTime], - parentHashes[blockId - proofTime], - (blockId - proofTime == 1) ? 0 : 1000000, // Genesis block has 0 gas used - 1000000, - blockHashes[blockId - proofTime], - signalRoots[blockId - proofTime] - ); - - uint64 provenAt = uint64(block.timestamp); - console2.log( - "Proof reward is:", - L1.getProofReward(provenAt - proposedAt[blockId - proofTime]) - ); - verifyBlock(Carol, 1); - } - - mine_every_12_sec(); - - parentHashes[blockId] = parentHash; - parentHash = blockHashes[blockId]; - } - - //Check end balances - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - //Check end balances - deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - // Assert their balance changed relatively the same way - // 1e18 == within 100 % delta -> 1e17 10%, let's see if this is within that range - assertApproxEqRel(deposits, withdrawals, 1e17); - } - - /// @dev A possible (close to) mainnet scenarios is the following: - //// - Blocks ever 10 seconds proposed - //// - Proofs coming shifted slightly below 30 min / proposed block afterwards - //// Expected result: Withdrawals and deposits are in balance but keep shrinking since quicker proofTime - function xtest_possible_mainnet_scenario_proof_time_at_target() external { - vm.pauseGasMetering(); - mine(1); - - TaikoData.BlockMetadata[] memory meta = new TaikoData.BlockMetadata[]( - iterationCnt - ); - uint64[] memory proposedAt = new uint64[](iterationCnt); - bytes32[] memory parentHashes = new bytes32[](iterationCnt); - bytes32[] memory blockHashes = new bytes32[](iterationCnt); - bytes32[] memory signalRoots = new bytes32[](iterationCnt); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Run another session with huge times - for (uint256 blockId = 1; blockId < iterationCnt; blockId++) { - { - meta[blockId] = proposeBlock(Alice, 100000, 10); - proposedAt[blockId] = (uint64(block.timestamp)); - printVariables("after propose"); - blockHashes[blockId] = bytes32(1e10 + blockId); //blockHash; - signalRoots[blockId] = bytes32(1e9 + blockId); //signalRoot; - - if (blockId > proofTime) { - //Start proving with an offset - proveBlock( - Bob, - Bob, - meta[blockId - proofTime], - parentHashes[blockId - proofTime], - (blockId - proofTime == 1) ? 0 : 1000000, - 1000000, - blockHashes[blockId - proofTime], - signalRoots[blockId - proofTime] - ); - - uint64 provenAt = uint64(block.timestamp); - console2.log( - "Proof reward is:", - L1.getProofReward(provenAt - proposedAt[blockId - proofTime]) - ); - } - - mine_every_12_sec(); - - parentHashes[blockId] = parentHash; - parentHash = blockHashes[blockId]; - } - } - //Check end balances - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - //Check end balances - deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - // Assert their balance changed relatively the same way - // 1e18 == within 100 % delta -> 1e17 10%, let's see if this is within that range - assertApproxEqRel(deposits, withdrawals, 1e17); - } - - /// @dev A possible (close to) mainnet scenarios is the following: - //// - Blocks ever 10 seconds proposed - //// - Proofs coming shifted slightly above 30 min / proposed block afterwards - //// Expected result: Withdrawals and deposits are in balance but fees keep growing bc of above target - function xtest_possible_mainnet_scenario_proof_time_above_target() external { - vm.pauseGasMetering(); - mine(1); - - proofTime = 181; // When proofs are coming, 181 means 1810 sec - - TaikoData.BlockMetadata[] memory meta = new TaikoData.BlockMetadata[]( - iterationCnt - ); - uint64[] memory proposedAt = new uint64[](iterationCnt); - bytes32[] memory parentHashes = new bytes32[](iterationCnt); - bytes32[] memory blockHashes = new bytes32[](iterationCnt); - bytes32[] memory signalRoots = new bytes32[](iterationCnt); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - for (uint256 blockId = 1; blockId < iterationCnt; blockId++) { - meta[blockId] = proposeBlock(Alice, 1000000, 1024); - proposedAt[blockId] = (uint64(block.timestamp)); - printVariables("after propose"); - blockHashes[blockId] = bytes32(1e10 + blockId); - signalRoots[blockId] = bytes32(1e9 + blockId); - - if (blockId > proofTime) { - //Start proving with an offset - proveBlock( - Bob, - Bob, - meta[blockId - proofTime], - parentHashes[blockId - proofTime], - (blockId - proofTime == 1) ? 0 : 1000000, - 1000000, - blockHashes[blockId - proofTime], - signalRoots[blockId - proofTime] - ); - - uint64 provenAt = uint64(block.timestamp); - console2.log( - "Proof reward is:", - L1.getProofReward(provenAt - proposedAt[blockId - proofTime]) - ); - verifyBlock(Carol, 1); - } - - mine_every_12_sec(); - - parentHashes[blockId] = parentHash; - parentHash = blockHashes[blockId]; - } - - //Check end balances - //Check end balances - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - //Check end balances - deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - // Assert their balance changed relatively the same way - // 1e18 == within 100 % delta -> 1e17 10%, let's see if this is within that range - assertApproxEqRel(deposits, withdrawals, 1e17); - } - - function mine_every_12_sec() internal { - vm.warp(block.timestamp + 12); - vm.roll(block.number + 1); - } -} diff --git a/packages/protocol/test/TaikoL1LibTokenomicsTestnet.t.sol b/packages/protocol/test/TaikoL1LibTokenomicsTestnet.t.sol deleted file mode 100644 index 7a137bf58d6..00000000000 --- a/packages/protocol/test/TaikoL1LibTokenomicsTestnet.t.sol +++ /dev/null @@ -1,919 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -// Uncomment if you want to compare fee/vs reward -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {TaikoConfig} from "../contracts/L1/TaikoConfig.sol"; -import {TaikoData} from "../contracts/L1/TaikoData.sol"; -import {TaikoL1} from "../contracts/L1/TaikoL1.sol"; -import {TaikoToken} from "../contracts/L1/TaikoToken.sol"; -import {SignalService} from "../contracts/signal/SignalService.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {TaikoL1TestBase} from "./TaikoL1TestBase.t.sol"; -import {LibLn} from "./LibLn.sol"; - -uint16 constant INITIAL_PROOF_TIME_TARGET = 120; //sec. Approx testnet scenario - -contract TaikoL1WithTestnetConfig is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { - config = TaikoConfig.getConfig(); - - config.txListCacheExpiry = 5 minutes; - config.maxVerificationsPerTx = 0; - config.proofCooldownPeriod = 0; - config.maxNumProposedBlocks = 40; - config.ringBufferSize = 48; - } -} - -// Testing the base "math" and directions if all is good -contract TaikoL1LibTokenomicsTestnet is TaikoL1TestBase { - function deployTaikoL1() internal override returns (TaikoL1 taikoL1) { - taikoL1 = new TaikoL1WithTestnetConfig(); - } - - function setUp() public override { - proofTimeTarget = INITIAL_PROOF_TIME_TARGET; // Approx. testnet value - // Calculating it for our needs based on testnet/mainnet proof vars. - // See Brecht's comment https://github.com/taikoxyz/taiko-mono/pull/13564 - initProofTimeIssued = - LibLn.calcInitProofTimeIssued(feeBase, proofTimeTarget, ADJUSTMENT_QUOTIENT); - - TaikoL1TestBase.setUp(); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - } - - /// @dev Test what happens when proof time increases - function test_balanced_state_reward_and_fee_if_proof_time_increases_slowly_then_drastically() - external - { - mine(1); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - for (uint256 blockId = 1; blockId < 10; blockId++) { - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - uint64 proposedAt = uint64(block.timestamp); - mine(blockId); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock( - Bob, - Bob, - meta, - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - - verifyBlock(Carol, 1); - // This is where new fee evaluated - printVariables("after verify"); - - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - - assertEq(deposits, withdrawals); - - // Run another session with huge times - for (uint256 blockId = 1; blockId < 10; blockId++) { - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - uint64 proposedAt = uint64(block.timestamp); - mine_huge(); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - - proveBlock(Bob, Bob, meta, parentHash, 1000000, 1000000, blockHash, signalRoot); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - verifyBlock(Carol, 1); - // This is where new fee evaluated - printVariables("after verify"); - - parentHash = blockHash; - } - - //Check end balances - deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - assertEq(deposits, withdrawals); - } - - /// @dev Test what happens when proof time hectic couple of proposes, without prove, then some proofs - function test_balanced_state_reward_and_fee_if_proof_time_hectic() external { - mine(1); - //Needs lot of token here - because there is lots of time elapsed between 2 'propose' blocks, which will raise the fee - depositTaikoToken(Alice, 1e8 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e8 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e8 * 1e8, 100 ether); - - TaikoData.BlockMetadata[] memory metas = new TaikoData.BlockMetadata[]( - 20 - ); - uint64[] memory proposedAtArr = new uint64[](20); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - // Propose blocks - but dont go above a certain iterationi count because the drastically increasing - // proof time will be an issue - for (uint256 blockId = 1; blockId < 10; blockId++) { - //printVariables("before propose"); - metas[blockId] = proposeBlock(Alice, 1000000, 1024); - proposedAtArr[blockId] = (uint64(block.timestamp)); - printVariables("after propose"); - mine(blockId); - } - - // Wait random X - mine(6); - // Prove and verify - for (uint256 blockId = 1; blockId < 10; blockId++) { - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock( - Bob, - Bob, - metas[blockId], - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAtArr[blockId])); - - verifyBlock(Carol, 1); - - printVariables("after verify"); - mine(blockId); - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - // Run another iteration - for (uint256 blockId = 1; blockId < 10; blockId++) { - printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - uint64 proposedAt = uint64(block.timestamp); - printVariables("after propose"); - mine_proofTime(); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock(Bob, Bob, meta, parentHash, 1000000, 1000000, blockHash, signalRoot); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - verifyBlock(Carol, 1); - - parentHash = blockHash; - } - - //Check end balances - - deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - assertEq(deposits, withdrawals); - } - - /// @dev Test and see what happens when proof time is stable below the target and proving consecutive - function test_balanced_state_reward_and_fee_if_proof_time_stable_below_target_prooving_consecutive( - ) external { - mine(1); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - //parentHash = prove_with_increasing_time(parentHash, 10); - for (uint256 blockId = 1; blockId < 10; blockId++) { - printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - uint64 proposedAt = uint64(block.timestamp); - printVariables("after propose"); - mine(2); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock( - Bob, - Bob, - meta, - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - - verifyBlock(Carol, 1); - - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - - assertEq(deposits, withdrawals); - } - - /// @dev Test and see what happens when proof time is stable below the target and proving non consecutive - function test_balanced_state_reward_and_fee_if_proof_time_stable_below_target_proving_non_consecutive( - ) external { - mine(1); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - TaikoData.BlockMetadata[] memory meta = new TaikoData.BlockMetadata[]( - 30 - ); - uint64[] memory proposedAt = new uint64[](30); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - // Propose blocks - for (uint256 blockId = 1; blockId < 30; blockId++) { - //printVariables("before propose"); - meta[blockId] = proposeBlock(Alice, 1000000, 1024); - proposedAt[blockId] = (uint64(block.timestamp)); - printVariables("after propose"); - mine(blockId); - } - - // Wait random X - mine(6); - //Prove and verify - for (uint256 blockId = 1; blockId < 30; blockId++) { - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - - proveBlock( - Bob, - Bob, - meta[blockId], - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt[blockId])); - - verifyBlock(Carol, 1); - - mine(3); - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - - assertEq(deposits, withdrawals); - } - - /// @dev Test what happens when proof time decreases - function test_balanced_state_reward_and_fee_if_proof_time_decreases() external { - mine(1); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - TaikoData.BlockMetadata[] memory meta = new TaikoData.BlockMetadata[]( - 20 - ); - uint64[] memory proposedAt = new uint64[](20); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - // Propose blocks - for (uint256 blockId = 1; blockId < 20; blockId++) { - //printVariables("before propose"); - meta[blockId] = proposeBlock(Alice, 1000000, 1024); - proposedAt[blockId] = (uint64(block.timestamp)); - printVariables("after propose"); - mine(blockId); - } - - // Wait random X - mine(6); - // Prove and verify - for (uint256 blockId = 1; blockId < 20; blockId++) { - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock( - Bob, - Bob, - meta[blockId], - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt[blockId])); - - verifyBlock(Carol, 1); - mine(21 - blockId); - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - // console2.log("Deposits:", deposits); - // console2.log("withdrawals:", withdrawals); - assertEq(deposits, withdrawals); - } - - /// @dev Test and see what happens when proof time is stable above the target and proving consecutive - function test_balanced_state_reward_and_fee_if_proof_time_stable_above_target_prooving_consecutive( - ) external { - mine(1); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - //parentHash = prove_with_increasing_time(parentHash, 10); - for (uint256 blockId = 1; blockId < 10; blockId++) { - printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - uint64 proposedAt = uint64(block.timestamp); - printVariables("after propose"); - mine(5); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock( - Bob, - Bob, - meta, - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - - verifyBlock(Carol, 1); - - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - - assertEq(deposits, withdrawals); - } - - /// @dev Test and see what happens when proof time is stable above the target and proving non consecutive - function test_balanced_state_reward_and_fee_if_proof_time_stable_above_target_proving_non_consecutive( - ) external { - mine(1); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - TaikoData.BlockMetadata[] memory meta = new TaikoData.BlockMetadata[]( - 30 - ); - uint64[] memory proposedAt = new uint64[](30); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - // Propose blocks - for (uint256 blockId = 1; blockId < 30; blockId++) { - //printVariables("before propose"); - meta[blockId] = proposeBlock(Alice, 1000000, 1024); - proposedAt[blockId] = (uint64(block.timestamp)); - printVariables("after propose"); - mine(blockId); - } - - // Wait random X - mine(6); - // Prove and verify - for (uint256 blockId = 1; blockId < 30; blockId++) { - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - - proveBlock( - Bob, - Bob, - meta[blockId], - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt[blockId])); - - verifyBlock(Carol, 1); - mine(5); - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - - assertEq(deposits, withdrawals); - } - - /// @dev Test what happens when proof time decreases - function test_balanced_state_reward_and_fee_if_proof_time_decreasses_then_stabilizes_consecutive( - ) external { - mine(1); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - //parentHash = prove_with_increasing_time(parentHash, 10); - for (uint256 blockId = 1; blockId < 10; blockId++) { - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - printVariables("after propose"); - uint64 proposedAt = uint64(block.timestamp); - mine(11 - blockId); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock( - Bob, - Bob, - meta, - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - - verifyBlock(Carol, 1); - - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - - assertEq(deposits, withdrawals); - - // Run another session with huge times - for (uint256 blockId = 1; blockId < 10; blockId++) { - printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - uint64 proposedAt = uint64(block.timestamp); - printVariables("after propose"); - mine_proofTime(); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock(Bob, Bob, meta, parentHash, 1000000, 1000000, blockHash, signalRoot); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - verifyBlock(Carol, 1); - - parentHash = blockHash; - } - - //Check end balances - deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - assertEq(deposits, withdrawals); - } - - /// @dev Test what happens when proof time decreases - function test_balanced_state_reward_and_fee_if_proof_time_decreases_then_stabilizes_non_consecutive( - ) external { - mine(1); - // Requires a bit more tokens - depositTaikoToken(Alice, 1e8 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e8 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e8 * 1e8, 100 ether); - - TaikoData.BlockMetadata[] memory metaArr = new TaikoData.BlockMetadata[](20); - uint64[] memory proposedAtArr = new uint64[](20); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - // Propose blocks - for (uint256 blockId = 1; blockId < 10; blockId++) { - //printVariables("before propose"); - metaArr[blockId] = proposeBlock(Alice, 1000000, 1024); - proposedAtArr[blockId] = (uint64(block.timestamp)); - printVariables("after propose"); - mine(blockId); - } - - // Wait random X - mine(6); - // Prove and verify - for (uint256 blockId = 1; blockId < 10; blockId++) { - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock( - Bob, - Bob, - metaArr[blockId], - parentHash, - (blockId == 1 ? 0 : 1000000), - 1000000, - blockHash, - signalRoot - ); - - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAtArr[blockId])); - - verifyBlock(Carol, 1); - mine(21 - blockId); - parentHash = blockHash; - } - - //Check end balances - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - - assertEq(deposits, withdrawals); - - // Run another session with huge times - for (uint256 blockId = 1; blockId < 10; blockId++) { - printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - uint64 proposedAt = uint64(block.timestamp); - printVariables("after propose"); - mine_proofTime(); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock(Bob, Bob, meta, parentHash, 1000000, 1000000, blockHash, signalRoot); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - verifyBlock(Carol, 1); - - parentHash = blockHash; - } - - //Check end balances - deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - // console2.log("Deposits:", deposits); - // console2.log("withdrawals:", withdrawals); - assertEq(deposits, withdrawals); - } - - /// @dev Test and see what happens when proof time is stable at the target and proving consecutive - function test_balanced_state_reward_and_fee_if_proof_time_stable_consecutive() external { - mine(1); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - //parentHash = prove_with_increasing_time(parentHash, 10); - for (uint256 blockId = 1; blockId < 10; blockId++) { - printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - uint64 proposedAt = uint64(block.timestamp); - printVariables("after propose"); - mine_proofTime(); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock( - Bob, - Bob, - meta, - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - - verifyBlock(Carol, 1); - - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - - assertEq(deposits, withdrawals); - } - - /// @dev Test a scenario which very close to a testnet behaviour - function test_balanced_state_reward_and_fee_if_proof_time_stable_non_consecutive() external { - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - - // Need constants here and in loop counter to avoid stack too deep error - TaikoData.BlockMetadata[] memory meta = new TaikoData.BlockMetadata[]( - 200 - ); - uint64[] memory proposedAt = new uint64[](200); - bytes32[] memory parentHashes = new bytes32[](200); - bytes32[] memory blockHashes = new bytes32[](200); - bytes32[] memory signalRoots = new bytes32[](200); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - uint8 proofTime = 10; - console2.logBytes32(parentHash); - - // Run another session with huge times - for (uint256 blockId = 1; blockId < 150; blockId++) { - { - meta[blockId] = proposeBlock(Alice, 1000000, 1024); - proposedAt[blockId] = (uint64(block.timestamp)); - printVariables("after propose"); - - blockHashes[blockId] = bytes32(1e10 + blockId); //blockHash; - signalRoots[blockId] = bytes32(1e9 + blockId); //signalRoot; - - if (blockId > proofTime) { - //Start proving with an offset - proveBlock( - Bob, - Bob, - meta[blockId - proofTime], - parentHashes[blockId - proofTime], - (blockId - proofTime == 1) ? 0 : 1000000, - 1000000, - blockHashes[blockId - proofTime], - signalRoots[blockId - proofTime] - ); - - uint64 provenAt = uint64(block.timestamp); - console2.log( - "Proof reward is:", - L1.getProofReward(provenAt - proposedAt[blockId - proofTime]) - ); - } - - mine_every_12_sec(); - - parentHashes[blockId] = parentHash; - parentHash = blockHashes[blockId]; - verifyBlock(Carol, 1); - } - } - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - //Check end balances - deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - // Assert their balance changed relatively the same way - // 1e18 == within 100 % delta -> 1e17 10%, let's see if this is within that range - assertApproxEqRel(deposits, withdrawals, 1e17); - } - - /// @dev Test if testing proof time params works (changes) as expected - function test_changing_proof_time_parameters() external { - mine(1); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - - // Check balances - uint256 Alice_start_balance = L1.getTaikoTokenBalance(Alice); - uint256 Bob_start_balance = L1.getTaikoTokenBalance(Bob); - console2.log("Alice balance:", Alice_start_balance); - console2.log("Bob balance:", Bob_start_balance); - - //parentHash = prove_with_increasing_time(parentHash, 10); - for (uint256 blockId = 1; blockId < 20; blockId++) { - // See if proof reward decreases faster than usual - if (blockId == 8) { - // 500 sec has the proofTimeIssued of 219263 (Calculated with 'forge script script/DetermineNewProofTimeIssued.s.sol') - L1.setProofParams(500, 219263, feeBase, ADJUSTMENT_QUOTIENT); - } - - // See if proof reward increases now - if (blockId == 15) { - // 10 sec has the proofTimeIssued of 3759 (Calculated with 'forge script script/DetermineNewProofTimeIssued.s.sol') - L1.setProofParams(10, 3759, feeBase, ADJUSTMENT_QUOTIENT); - } - - printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - uint64 proposedAt = uint64(block.timestamp); - printVariables("after propose"); - mine(5); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock( - Bob, - Bob, - meta, - parentHash, - blockId == 1 ? 0 : 1000000, - 1000000, - blockHash, - signalRoot - ); - uint64 provenAt = uint64(block.timestamp); - console2.log("Proof reward is:", L1.getProofReward(provenAt - proposedAt)); - - verifyBlock(Carol, 1); - - parentHash = blockHash; - } - - //Check end balances - - uint256 deposits = Alice_start_balance - L1.getTaikoTokenBalance(Alice); - uint256 withdrawals = L1.getTaikoTokenBalance(Bob) - Bob_start_balance; - - console2.log("Deposits:", deposits); - console2.log("withdrawals:", withdrawals); - - assertEq(deposits, withdrawals); - } - - function mine_huge() internal { - vm.warp(block.timestamp + 1200); - vm.roll(block.number + 300); - } - - function mine_every_12_sec() internal { - vm.warp(block.timestamp + 12); - vm.roll(block.number + 1); - } - - function mine_proofTime() internal { - vm.warp(block.timestamp + 120); - vm.roll(block.number + 5); - } -} diff --git a/packages/protocol/test/TaikoL1Oracle.t.sol b/packages/protocol/test/TaikoL1Oracle.t.sol index fbb5281bc63..93a8bde2df1 100644 --- a/packages/protocol/test/TaikoL1Oracle.t.sol +++ b/packages/protocol/test/TaikoL1Oracle.t.sol @@ -1,21 +1,26 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {LibUtils} from "../contracts/L1/libs/LibUtils.sol"; -import {TaikoConfig} from "../contracts/L1/TaikoConfig.sol"; -import {TaikoData} from "../contracts/L1/TaikoData.sol"; -import {TaikoErrors} from "../contracts/L1/TaikoErrors.sol"; -import {TaikoL1} from "../contracts/L1/TaikoL1.sol"; -import {TaikoToken} from "../contracts/L1/TaikoToken.sol"; -import {SignalService} from "../contracts/signal/SignalService.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {TaikoL1TestBase} from "./TaikoL1TestBase.t.sol"; +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { AddressManager } from "../contracts/common/AddressManager.sol"; +import { LibUtils } from "../contracts/L1/libs/LibUtils.sol"; +import { TaikoConfig } from "../contracts/L1/TaikoConfig.sol"; +import { TaikoData } from "../contracts/L1/TaikoData.sol"; +import { TaikoErrors } from "../contracts/L1/TaikoErrors.sol"; +import { TaikoL1 } from "../contracts/L1/TaikoL1.sol"; +import { TaikoToken } from "../contracts/L1/TaikoToken.sol"; +import { SignalService } from "../contracts/signal/SignalService.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; +import { TaikoL1TestBase } from "./TaikoL1TestBase.t.sol"; contract TaikoL1Oracle is TaikoL1 { - function getConfig() public pure override returns (TaikoData.Config memory config) { + function getConfig() + public + pure + override + returns (TaikoData.Config memory config) + { config = TaikoConfig.getConfig(); config.txListCacheExpiry = 5 minutes; @@ -49,14 +54,14 @@ contract TaikoL1OracleTest is TaikoL1TestBase { depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - TaikoData.BlockMetadata memory meta = proposeBlock(Bob, 1000000, 1024); + TaikoData.BlockMetadata memory meta = proposeBlock(Bob, 1_000_000, 1024); proveBlock( Bob, Bob, meta, GENESIS_BLOCK_HASH, - 10000, - 10001, + 10_000, + 10_001, bytes32(uint256(0x11)), bytes32(uint256(0x12)) ); @@ -67,25 +72,27 @@ contract TaikoL1OracleTest is TaikoL1TestBase { signalRoot: bytes32(uint256(0x12)), graffiti: 0x0, prover: address(0), - parentGasUsed: 10000, - gasUsed: 40000, + parentGasUsed: 10_000, + gasUsed: 40_000, verifierId: 0, proof: new bytes(0) }); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(AlicePK, keccak256(abi.encode(evidence))); + (uint8 v, bytes32 r, bytes32 s) = + vm.sign(AlicePK, keccak256(abi.encode(evidence))); evidence.verifierId = v; evidence.proof = bytes.concat(r, s); vm.prank(Carol, Carol); L1.proveBlock(meta.id, abi.encode(evidence)); - TaikoData.ForkChoice memory fc = L1.getForkChoice(1, GENESIS_BLOCK_HASH, 10000); + TaikoData.ForkChoice memory fc = + L1.getForkChoice(1, GENESIS_BLOCK_HASH, 10_000); assertEq(fc.blockHash, bytes32(uint256(0x11))); assertEq(fc.signalRoot, bytes32(uint256(0x12))); assertEq(fc.provenAt, block.timestamp); assertEq(fc.prover, address(0)); - assertEq(fc.gasUsed, 40000); + assertEq(fc.gasUsed, 40_000); } function testOracleProverCanAlwaysOverwriteIfNotSameProof() external { @@ -99,10 +106,11 @@ contract TaikoL1OracleTest is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint256 blockId = 1; - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); for (uint256 i = 0; i < 5; ++i) { - uint32 parentGasUsed = uint32(10000 + i); + uint32 parentGasUsed = uint32(10_000 + i); // Bob proves the block proveBlock( @@ -111,14 +119,15 @@ contract TaikoL1OracleTest is TaikoL1TestBase { meta, parentHash, parentGasUsed, - 10001, + 10_001, bytes32(uint256(0x11)), bytes32(uint256(0x12)) ); uint256 provenAt = block.timestamp; - TaikoData.ForkChoice memory fc = L1.getForkChoice(blockId, parentHash, parentGasUsed); + TaikoData.ForkChoice memory fc = + L1.getForkChoice(blockId, parentHash, parentGasUsed); if (i == 0) { assertFalse(fc.key == 0); @@ -129,7 +138,7 @@ contract TaikoL1OracleTest is TaikoL1TestBase { assertEq(fc.signalRoot, bytes32(uint256(0x12))); assertEq(fc.provenAt, provenAt); assertEq(fc.prover, Bob); - assertEq(fc.gasUsed, 10001); + assertEq(fc.gasUsed, 10_001); // Carol - who is oracle prover - can overwrite with same proof vm.warp(block.timestamp + 10 seconds); @@ -139,7 +148,7 @@ contract TaikoL1OracleTest is TaikoL1TestBase { meta, parentHash, parentGasUsed, - 10002, + 10_002, bytes32(uint256(0x11)), bytes32(uint256(0x12)) ); @@ -157,7 +166,7 @@ contract TaikoL1OracleTest is TaikoL1TestBase { assertEq(fc.signalRoot, bytes32(uint256(0x12))); assertEq(fc.provenAt, provenAt); assertEq(fc.prover, address(0)); - assertEq(fc.gasUsed, 10002); + assertEq(fc.gasUsed, 10_002); } } @@ -168,10 +177,11 @@ contract TaikoL1OracleTest is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint256 blockId = 1; - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); for (uint256 i = 0; i < 5; ++i) { - uint32 parentGasUsed = uint32(10000 + i); + uint32 parentGasUsed = uint32(10_000 + i); // Bob proves the block proveBlock( @@ -180,14 +190,15 @@ contract TaikoL1OracleTest is TaikoL1TestBase { meta, parentHash, parentGasUsed, - 10001, + 10_001, bytes32(uint256(0x11)), bytes32(uint256(0x12)) ); uint256 provenAt = block.timestamp; - TaikoData.ForkChoice memory fc = L1.getForkChoice(blockId, parentHash, parentGasUsed); + TaikoData.ForkChoice memory fc = + L1.getForkChoice(blockId, parentHash, parentGasUsed); if (i == 0) { assertFalse(fc.key == 0); @@ -198,7 +209,7 @@ contract TaikoL1OracleTest is TaikoL1TestBase { assertEq(fc.signalRoot, bytes32(uint256(0x12))); assertEq(fc.provenAt, provenAt); assertEq(fc.prover, Bob); - assertEq(fc.gasUsed, 10001); + assertEq(fc.gasUsed, 10_001); // Carol cannot prove the fork choice again vm.warp(block.timestamp + 10 seconds); @@ -209,7 +220,7 @@ contract TaikoL1OracleTest is TaikoL1TestBase { meta, parentHash, parentGasUsed, - 10002, + 10_002, bytes32(uint256(0x21)), bytes32(uint256(0x22)) ); @@ -224,7 +235,7 @@ contract TaikoL1OracleTest is TaikoL1TestBase { meta, parentHash, parentGasUsed, - 10001, + 10_001, bytes32(uint256(0x11)), bytes32(uint256(0x12)) ); @@ -242,54 +253,22 @@ contract TaikoL1OracleTest is TaikoL1TestBase { assertEq(fc.signalRoot, bytes32(uint256(0x12))); assertEq(fc.provenAt, provenAt); assertEq(fc.prover, Bob); - assertEq(fc.gasUsed, 10001); + assertEq(fc.gasUsed, 10_001); vm.warp(block.timestamp + 10 seconds); } } - /// @dev Test we can propose, prove, then verify more blocks than 'maxNumProposedBlocks' - function test_cooldown_more_blocks_than_ring_buffer_size() external { - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; - - for (uint256 blockId = 1; blockId < conf.maxNumProposedBlocks * 10; blockId++) { - printVariables("before propose"); - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - printVariables("after propose"); - mine(1); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock(Bob, Bob, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot); - - uint256 lastVerifiedBlockId = L1.getStateVariables().lastVerifiedBlockId; - - vm.warp(block.timestamp + 4 minutes + 59 seconds); - verifyBlock(Carol, 1); - - assertEq(lastVerifiedBlockId, L1.getStateVariables().lastVerifiedBlockId); - - vm.warp(block.timestamp + 1 seconds); - verifyBlock(Carol, 1); - assertFalse(lastVerifiedBlockId == L1.getStateVariables().lastVerifiedBlockId); - - parentHash = blockHash; - parentGasUsed = gasUsed; - } - printVariables(""); - } - - /// @dev So in case we have regular proving mechanism we shall check if still a cooldown happens + /// @dev So in case we have regular proving mechanism we shall check if + /// still a cooldown happens /// @dev when proving a block (in a normal way). - /// @notice In case both oracle_prover and system_prover is disbaled, there is no reason why + /// @notice In case both oracle_prover and system_prover is disbaled, there + /// is no reason why /// @notice cooldowns be above 0 min tho (!). - function test_if_oracle_is_disabled_cooldown_is_still_as_proofCooldownPeriod() external { + function test_if_oracle_is_disabled_cooldown_is_still_as_proofCooldownPeriod( + ) + external + { registerAddress("oracle_prover", address(0)); registerAddress("system_prover", address(0)); @@ -299,25 +278,42 @@ contract TaikoL1OracleTest is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; - - for (uint256 blockId = 1; blockId < conf.maxNumProposedBlocks * 10; blockId++) { - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + uint32 gasUsed = 1_000_000; + + for ( + uint256 blockId = 1; + blockId < conf.maxNumProposedBlocks * 10; + blockId++ + ) { + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); printVariables("after propose"); mine(1); bytes32 blockHash = bytes32(1e10 + blockId); bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock(Bob, Bob, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot); + proveBlock( + Bob, + Bob, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot + ); - uint256 lastVerifiedBlockId = L1.getStateVariables().lastVerifiedBlockId; + uint256 lastVerifiedBlockId = + L1.getStateVariables().lastVerifiedBlockId; vm.warp(block.timestamp + 1 seconds); verifyBlock(Carol, 1); - // Check if shortly after proving (+verify) the last verify is not the same anymore + // Check if shortly after proving (+verify) the last verify is not + // the same anymore // no need to have a cooldown period - uint256 lastVerifiedBlockIdNow = L1.getStateVariables().lastVerifiedBlockId; + uint256 lastVerifiedBlockIdNow = + L1.getStateVariables().lastVerifiedBlockId; assertEq(lastVerifiedBlockIdNow, lastVerifiedBlockId); @@ -335,7 +331,8 @@ contract TaikoL1OracleTest is TaikoL1TestBase { } /// @dev Test if oracle prover is the only prover it cannot be verified - function test_that_simple_oracle_prover_cannot_be_verified_only_if_normal_proof_comes_in() + function test_that_simple_oracle_prover_cannot_be_verified_only_if_normal_proof_comes_in( + ) external { // Bob is an oracle prover now @@ -348,32 +345,54 @@ contract TaikoL1OracleTest is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; - - for (uint256 blockId = 1; blockId < conf.maxNumProposedBlocks * 10; blockId++) { - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + uint32 gasUsed = 1_000_000; + + for ( + uint256 blockId = 1; + blockId < conf.maxNumProposedBlocks * 10; + blockId++ + ) { + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); printVariables("after propose"); mine(1); bytes32 blockHash = bytes32(1e10 + blockId); bytes32 signalRoot = bytes32(1e9 + blockId); proveBlock( - Bob, address(0), meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot + Bob, + address(0), + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot ); - uint256 lastVerifiedBlockId = L1.getStateVariables().lastVerifiedBlockId; + uint256 lastVerifiedBlockId = + L1.getStateVariables().lastVerifiedBlockId; vm.warp(block.timestamp + 1 seconds); verifyBlock(Carol, 1); - // Check if shortly after proving (+verify) the last verify is the same (bc it is an oracle proof) - uint256 lastVerifiedBlockIdNow = L1.getStateVariables().lastVerifiedBlockId; + // Check if shortly after proving (+verify) the last verify is the + // same (bc it is an oracle proof) + uint256 lastVerifiedBlockIdNow = + L1.getStateVariables().lastVerifiedBlockId; // Cannot be verified assertEq(lastVerifiedBlockIdNow, lastVerifiedBlockId); proveBlock( - Carol, Carol, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot + Carol, + Carol, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot ); vm.warp(block.timestamp + 1 seconds); @@ -391,73 +410,10 @@ contract TaikoL1OracleTest is TaikoL1TestBase { printVariables(""); } - /// @dev Test if system prover is the prover, cooldown is systemProofCooldownPeriod - function test_if_prover_is_system_prover_cooldown_is_systemProofCooldownPeriod() external { - registerAddress("system_prover", Bob); - - depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); - depositTaikoToken(Bob, 1e6 * 1e8, 100 ether); - depositTaikoToken(Carol, 1e6 * 1e8, 100 ether); - - bytes32 parentHash = GENESIS_BLOCK_HASH; - uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; - - for (uint256 blockId = 1; blockId < conf.maxNumProposedBlocks * 10; blockId++) { - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); - printVariables("after propose"); - mine(1); - - bytes32 blockHash = bytes32(1e10 + blockId); - bytes32 signalRoot = bytes32(1e9 + blockId); - - uint256 realproof = blockId % conf.realProofSkipSize; - - if (realproof == 0) { - proveBlock( - Carol, Carol, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot - ); - } else { - proveBlock( - Bob, address(1), meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot - ); - } - - uint256 lastVerifiedBlockId = L1.getStateVariables().lastVerifiedBlockId; - - vm.warp(block.timestamp + 1 seconds); - verifyBlock(Carol, 1); - - // Check if shortly after proving (+verify) the last verify is not the same anymore - // no need to have a cooldown period - uint256 lastVerifiedBlockIdNow = L1.getStateVariables().lastVerifiedBlockId; - - // It would be true anyways, but better to separate things. - // If not real proof is necessary, also the proofCooldownPeriod needs to be elapsed to be true. - // So separating the check. - /// @notice: In case both system and oracle are disabled, we should set the cooldown time to 0 mins. - if (realproof != 0) { - assertEq(lastVerifiedBlockIdNow, lastVerifiedBlockId); - } - - vm.warp( - block.timestamp + L1.getStateVariables().proofTimeTarget - + conf.systemProofCooldownPeriod - ); - verifyBlock(Carol, 1); - - lastVerifiedBlockIdNow = L1.getStateVariables().lastVerifiedBlockId; - - assertFalse(lastVerifiedBlockIdNow == lastVerifiedBlockId); - - parentHash = blockHash; - parentGasUsed = gasUsed; - } - printVariables(""); - } - /// @dev Test if system proofs can be verified - function test_if_system_proofs_can_be_verified_without_regular_proofs() external { + function test_if_system_proofs_can_be_verified_without_regular_proofs() + external + { registerAddress("system_prover", Bob); depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); @@ -466,26 +422,43 @@ contract TaikoL1OracleTest is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; - - for (uint256 blockId = 1; blockId < conf.maxNumProposedBlocks * 10; blockId++) { - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + uint32 gasUsed = 1_000_000; + + for ( + uint256 blockId = 1; + blockId < conf.maxNumProposedBlocks * 10; + blockId++ + ) { + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); printVariables("after propose"); mine(1); bytes32 blockHash = bytes32(1e10 + blockId); bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock(Bob, Bob, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot); + proveBlock( + Bob, + Bob, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot + ); - uint256 lastVerifiedBlockId = L1.getStateVariables().lastVerifiedBlockId; + uint256 lastVerifiedBlockId = + L1.getStateVariables().lastVerifiedBlockId; // Need to wait config.systemProofCooldownPeriod vm.warp(block.timestamp + conf.systemProofCooldownPeriod); verifyBlock(Carol, 1); - // Check if shortly after proving (+verify) the last verify is not the same anymore + // Check if shortly after proving (+verify) the last verify is not + // the same anymore // no need to have a cooldown period - uint256 lastVerifiedBlockIdNow = L1.getStateVariables().lastVerifiedBlockId; + uint256 lastVerifiedBlockIdNow = + L1.getStateVariables().lastVerifiedBlockId; assertFalse(lastVerifiedBlockIdNow == lastVerifiedBlockId); @@ -496,7 +469,9 @@ contract TaikoL1OracleTest is TaikoL1TestBase { } /// @dev Test if system prover cannot be overwritten - function test_if_systemProver_can_prove_but_regular_provers_can_overwrite() external { + function test_if_systemProver_can_prove_but_regular_provers_can_overwrite() + external + { registerAddress("system_prover", Bob); depositTaikoToken(Alice, 1e6 * 1e8, 100 ether); @@ -505,10 +480,15 @@ contract TaikoL1OracleTest is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; - - for (uint256 blockId = 1; blockId < conf.maxNumProposedBlocks * 10; blockId++) { - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + uint32 gasUsed = 1_000_000; + + for ( + uint256 blockId = 1; + blockId < conf.maxNumProposedBlocks * 10; + blockId++ + ) { + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); printVariables("after propose"); mine(1); @@ -519,35 +499,60 @@ contract TaikoL1OracleTest is TaikoL1TestBase { if (realProof == 0) { proveBlock( - Carol, Carol, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot + Carol, + Carol, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot ); } else { proveBlock( - Bob, address(1), meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot + Bob, + address(1), + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot ); } - uint256 lastVerifiedBlockId = L1.getStateVariables().lastVerifiedBlockId; + uint256 lastVerifiedBlockId = + L1.getStateVariables().lastVerifiedBlockId; // Carol could overwrite it if (realProof != 0) { proveBlock( - Carol, Carol, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot + Carol, + Carol, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot ); } vm.warp(block.timestamp + 1 seconds); vm.warp(block.timestamp + 5 minutes); - TaikoData.ForkChoice memory fc = L1.getForkChoice(blockId, parentHash, parentGasUsed); + TaikoData.ForkChoice memory fc = + L1.getForkChoice(blockId, parentHash, parentGasUsed); if (realProof != 0) assertEq(fc.prover, Carol); verifyBlock(Carol, 1); - // Check if shortly after proving (+verify) the last verify is not the same anymore + // Check if shortly after proving (+verify) the last verify is not + // the same anymore // no need to have a cooldown period - uint256 lastVerifiedBlockIdNow = L1.getStateVariables().lastVerifiedBlockId; + uint256 lastVerifiedBlockIdNow = + L1.getStateVariables().lastVerifiedBlockId; assertFalse(lastVerifiedBlockIdNow == lastVerifiedBlockId); @@ -568,33 +573,59 @@ contract TaikoL1OracleTest is TaikoL1TestBase { bytes32 parentHash = GENESIS_BLOCK_HASH; uint32 parentGasUsed = 0; - uint32 gasUsed = 1000000; - - for (uint256 blockId = 1; blockId < conf.maxNumProposedBlocks * 10; blockId++) { - TaikoData.BlockMetadata memory meta = proposeBlock(Alice, 1000000, 1024); + uint32 gasUsed = 1_000_000; + + for ( + uint256 blockId = 1; + blockId < conf.maxNumProposedBlocks * 10; + blockId++ + ) { + TaikoData.BlockMetadata memory meta = + proposeBlock(Alice, 1_000_000, 1024); printVariables("after propose"); mine(1); bytes32 blockHash = bytes32(1e10 + blockId); bytes32 signalRoot = bytes32(1e9 + blockId); - proveBlock(Bob, Bob, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot); + proveBlock( + Bob, + Bob, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot + ); - uint256 lastVerifiedBlockId = L1.getStateVariables().lastVerifiedBlockId; + uint256 lastVerifiedBlockId = + L1.getStateVariables().lastVerifiedBlockId; // Carol could not overwrite it vm.expectRevert(TaikoErrors.L1_ALREADY_PROVEN.selector); proveBlock( - Carol, Carol, meta, parentHash, parentGasUsed, gasUsed, blockHash, signalRoot + Carol, + Carol, + meta, + parentHash, + parentGasUsed, + gasUsed, + blockHash, + signalRoot ); - /// @notice: Based on the current codebase we still need to wait even if the system and oracle proofs are disbaled, which - /// @notice: in such case best to set 0 mins (cause noone could overwrite a valid fk). + /// @notice: Based on the current codebase we still need to wait + /// even if the system and oracle proofs are disbaled, which + /// @notice: in such case best to set 0 mins (cause noone could + /// overwrite a valid fk). vm.warp(block.timestamp + conf.proofCooldownPeriod); verifyBlock(Carol, 1); - // Check if shortly after proving (+verify) the last verify is not the same anymore + // Check if shortly after proving (+verify) the last verify is not + // the same anymore // no need to have a cooldown period - uint256 lastVerifiedBlockIdNow = L1.getStateVariables().lastVerifiedBlockId; + uint256 lastVerifiedBlockIdNow = + L1.getStateVariables().lastVerifiedBlockId; assertFalse(lastVerifiedBlockIdNow == lastVerifiedBlockId); diff --git a/packages/protocol/test/TaikoL1TestBase.t.sol b/packages/protocol/test/TaikoL1TestBase.t.sol index fb38a0bff37..ba856ff8937 100644 --- a/packages/protocol/test/TaikoL1TestBase.t.sol +++ b/packages/protocol/test/TaikoL1TestBase.t.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {LibUtils} from "../contracts/L1/libs/LibUtils.sol"; -import {TaikoConfig} from "../contracts/L1/TaikoConfig.sol"; -import {TaikoData} from "../contracts/L1/TaikoData.sol"; -import {TaikoL1} from "../contracts/L1/TaikoL1.sol"; -import {TaikoToken} from "../contracts/L1/TaikoToken.sol"; -import {SignalService} from "../contracts/signal/SignalService.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { AddressManager } from "../contracts/common/AddressManager.sol"; +import { LibUtils } from "../contracts/L1/libs/LibUtils.sol"; +import { TaikoConfig } from "../contracts/L1/TaikoConfig.sol"; +import { TaikoData } from "../contracts/L1/TaikoData.sol"; +import { TaikoL1 } from "../contracts/L1/TaikoL1.sol"; +import { TaikoToken } from "../contracts/L1/TaikoToken.sol"; +import { SignalService } from "../contracts/signal/SignalService.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; contract Verifier { fallback(bytes calldata) external returns (bytes memory) { @@ -30,10 +30,12 @@ abstract contract TaikoL1TestBase is Test { uint64 feeBase = 1e8; // 1 TKO uint64 l2GasExcess = 1e18; - address public constant L2Treasury = 0x859d74b52762d9ed07D1b2B8d7F93d26B1EA78Bb; + address public constant L2Treasury = + 0x859d74b52762d9ed07D1b2B8d7F93d26B1EA78Bb; address public constant L2SS = 0xa008AE5Ba00656a3Cc384de589579e3E52aC030C; address public constant TaikoL2 = 0x0082D90249342980d011C58105a03b35cCb4A315; - address public constant L1EthVault = 0xDAFEA492D9c6733ae3d56b7Ed1ADB60692c98Bc5; + address public constant L1EthVault = + 0xDAFEA492D9c6733ae3d56b7Ed1ADB60692c98Bc5; address public constant Alice = 0xa9bcF99f5eb19277f48b71F9b14f5960AEA58a89; uint256 public constant AlicePK = @@ -47,13 +49,6 @@ abstract contract TaikoL1TestBase is Test { address public constant George = 0x520147C0eB43d8D71b2b03037bB7b31f8F78EF5f; address public constant Hilbert = 0x61081B12838240B1Ba02b3177153BcA678a86078; - // Calculation shall be done in derived contracts - based on testnet or mainnet expected proof time - uint64 public initProofTimeIssued; - uint16 proofTimeTarget; - // As we know this is value which will make the curve 'quick' this is fine for testing and - // will readjust during simulation to test devnet, where we need to reset everything blockfee calculation related. - uint16 public constant ADJUSTMENT_QUOTIENT = 16; - function deployTaikoL1() internal virtual returns (TaikoL1 taikoL1); function setUp() public virtual { @@ -79,33 +74,28 @@ abstract contract TaikoL1TestBase is Test { registerAddress("taiko_token", address(tko)); address[] memory premintRecipients; uint256[] memory premintAmounts; - tko.init(address(addressManager), "TaikoToken", "TKO", premintRecipients, premintAmounts); + tko.init( + address(addressManager), + "TaikoToken", + "TKO", + premintRecipients, + premintAmounts + ); // Set protocol broker registerAddress("proto_broker", address(this)); tko.mint(address(this), 1e9 * 1e8); registerAddress("proto_broker", address(L1)); - // Lastly, init L1 - if (proofTimeTarget == 0 || initProofTimeIssued == 0) { - // This just means, these tests are not focusing on the tokenomics, which is fine! - // So here, with 500second proof time the initial proof time issued value shall be that below. - // Calculated with 'forge script script/DetermineNewProofTimeIssued.s.sol' - proofTimeTarget = 500; - initProofTimeIssued = 219263; - } - L1.init( - address(addressManager), - GENESIS_BLOCK_HASH, - feeBase, - proofTimeTarget, - initProofTimeIssued, - ADJUSTMENT_QUOTIENT - ); + L1.init(address(addressManager), GENESIS_BLOCK_HASH, feeBase); printVariables("init "); } - function proposeBlock(address proposer, uint32 gasLimit, uint24 txListSize) + function proposeBlock( + address proposer, + uint32 gasLimit, + uint24 txListSize + ) internal returns (TaikoData.BlockMetadata memory meta) { @@ -151,7 +141,9 @@ abstract contract TaikoL1TestBase is Test { uint32 gasUsed, bytes32 blockHash, bytes32 signalRoot - ) internal { + ) + internal + { TaikoData.BlockEvidence memory evidence = TaikoData.BlockEvidence({ metaHash: LibUtils.hashMetadata(meta), parentHash: parentHash, @@ -184,11 +176,17 @@ abstract contract TaikoL1TestBase is Test { console2.log(conf.chainId, uint256(nameHash), unicode"→", addr); } - function depositTaikoToken(address who, uint256 amountTko, uint256 amountEth) internal { + function depositTaikoToken( + address who, + uint256 amountTko, + uint256 amountEth + ) + internal + { vm.deal(who, amountEth); tko.transfer(who, amountTko); - vm.prank(who, who); - L1.depositTaikoToken(amountTko); + // vm.prank(who, who); + // L1.depositTaikoToken(amountTko); } function printVariables(string memory comment) internal { diff --git a/packages/protocol/test/TaikoL2.t.sol b/packages/protocol/test/TaikoL2.t.sol index cec675a5e57..b890e6c95dc 100644 --- a/packages/protocol/test/TaikoL2.t.sol +++ b/packages/protocol/test/TaikoL2.t.sol @@ -1,18 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {LibL2Consts} from "../contracts/L2/LibL2Consts.sol"; -import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; -import {TaikoL2} from "../contracts/L2/TaikoL2.sol"; -import {SafeCastUpgradeable} from +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { LibL2Consts } from "../contracts/L2/LibL2Consts.sol"; +import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; +import { TaikoL2 } from "../contracts/L2/TaikoL2.sol"; +import { SafeCastUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol"; contract TestTaikoL2 is Test { using SafeCastUpgradeable for uint256; - uint64 public constant BLOCK_GAS_LIMIT = 30000000; // same as `block_gas_limit` in foundry.toml + uint64 public constant BLOCK_GAS_LIMIT = 30_000_000; // same as + // `block_gas_limit` in foundry.toml TaikoL2 public L2; uint256 private logIndex; @@ -22,10 +23,10 @@ contract TestTaikoL2 is Test { uint16 rand = 2; TaikoL2.EIP1559Params memory param1559 = TaikoL2.EIP1559Params({ basefee: (uint256(BLOCK_GAS_LIMIT * 10) * rand).toUint64(), - gasIssuedPerSecond: 1000000, - gasExcessMax: (uint256(15000000) * 256 * rand).toUint64(), - gasTarget: (uint256(6000000) * rand).toUint64(), - ratio2x1x: 11177 + gasIssuedPerSecond: 1_000_000, + gasExcessMax: (uint256(15_000_000) * 256 * rand).toUint64(), + gasTarget: (uint256(6_000_000) * rand).toUint64(), + ratio2x1x: 11_177 }); L2 = new TaikoL2(); @@ -133,25 +134,38 @@ contract TestTaikoL2 is Test { function testGetBasefee() external { uint32 timeSinceParent = uint32(block.timestamp - L2.parentTimestamp()); - assertEq(_getBasefeeAndPrint(timeSinceParent, 0, 0), 317609019); - assertEq(_getBasefeeAndPrint(timeSinceParent, 1, 0), 317609019); - assertEq(_getBasefeeAndPrint(timeSinceParent, 1000000, 0), 320423332); - assertEq(_getBasefeeAndPrint(timeSinceParent, 5000000, 0), 332018053); - assertEq(_getBasefeeAndPrint(timeSinceParent, 10000000, 0), 347305199); + assertEq(_getBasefeeAndPrint(timeSinceParent, 0, 0), 317_609_019); + assertEq(_getBasefeeAndPrint(timeSinceParent, 1, 0), 317_609_019); + assertEq( + _getBasefeeAndPrint(timeSinceParent, 1_000_000, 0), 320_423_332 + ); + assertEq( + _getBasefeeAndPrint(timeSinceParent, 5_000_000, 0), 332_018_053 + ); + assertEq( + _getBasefeeAndPrint(timeSinceParent, 10_000_000, 0), 347_305_199 + ); timeSinceParent = uint32(100 + block.timestamp - L2.parentTimestamp()); - assertEq(_getBasefeeAndPrint(timeSinceParent, 0, 0), 54544902); - assertEq(_getBasefeeAndPrint(timeSinceParent, 1, 0), 54544902); - assertEq(_getBasefeeAndPrint(timeSinceParent, 1000000, 0), 55028221); - assertEq(_getBasefeeAndPrint(timeSinceParent, 5000000, 0), 57019452); - assertEq(_getBasefeeAndPrint(timeSinceParent, 10000000, 0), 59644805); + assertEq(_getBasefeeAndPrint(timeSinceParent, 0, 0), 54_544_902); + assertEq(_getBasefeeAndPrint(timeSinceParent, 1, 0), 54_544_902); + assertEq(_getBasefeeAndPrint(timeSinceParent, 1_000_000, 0), 55_028_221); + assertEq(_getBasefeeAndPrint(timeSinceParent, 5_000_000, 0), 57_019_452); + assertEq( + _getBasefeeAndPrint(timeSinceParent, 10_000_000, 0), 59_644_805 + ); } - function _getBasefeeAndPrint(uint32 timeSinceParent, uint64 gasLimit, uint64 parentGasUsed) + function _getBasefeeAndPrint( + uint32 timeSinceParent, + uint64 gasLimit, + uint64 parentGasUsed + ) private returns (uint256 _basefee) { - uint256 gasIssued = L2.getEIP1559Config().gasIssuedPerSecond * timeSinceParent; + uint256 gasIssued = + L2.getEIP1559Config().gasIssuedPerSecond * timeSinceParent; string memory _msg = string.concat( "#", Strings.toString(logIndex++), @@ -180,7 +194,10 @@ contract TestTaikoL2 is Test { console2.log(_msg); } - function _getBasefeeAndPrint(uint32 timeSinceNow, uint64 gasLimit) + function _getBasefeeAndPrint( + uint32 timeSinceNow, + uint64 gasLimit + ) private returns (uint256 _basefee) { @@ -192,6 +209,11 @@ contract TestTaikoL2 is Test { } function _anchor(uint64 parentGasLimit) private { - L2.anchor(keccak256("a"), keccak256("b"), 12345, parentGasLimit + ANCHOR_GAS_COST); + L2.anchor( + keccak256("a"), + keccak256("b"), + 12_345, + parentGasLimit + ANCHOR_GAS_COST + ); } } diff --git a/packages/protocol/test/TaikoToken.t.sol b/packages/protocol/test/TaikoToken.t.sol index 89612e00c85..20018099217 100644 --- a/packages/protocol/test/TaikoToken.t.sol +++ b/packages/protocol/test/TaikoToken.t.sol @@ -1,14 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {AddressResolver} from "../contracts/common/AddressResolver.sol"; -import {TaikoErrors} from "../contracts/L1/TaikoErrors.sol"; -import {TaikoToken} from "../contracts/L1/TaikoToken.sol"; +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { AddressManager } from "../contracts/common/AddressManager.sol"; +import { AddressResolver } from "../contracts/common/AddressResolver.sol"; +import { TaikoErrors } from "../contracts/L1/TaikoErrors.sol"; +import { TaikoToken } from "../contracts/L1/TaikoToken.sol"; -import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; +import + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract TaikoTokenTest is Test { AddressManager public addressManager; @@ -18,10 +19,14 @@ contract TaikoTokenTest is Test { bytes32 public constant GENESIS_BLOCK_HASH = keccak256("GENESIS_BLOCK_HASH"); - address public constant tokenAdmin = 0x200C9b60e19634E12FC6D68B7FeA7Bfb26c2e418; - address public constant protoBroker = 0x300C9b60E19634e12FC6D68B7FEa7bFB26c2E419; - address public constant TeamWallet = 0x300C9b60E19634e12FC6D68B7FEa7bFB26c2E419; - address public constant DaoTreasury = 0x400147C0Eb43D8D71b2B03037bB7B31f8f78EF5F; + address public constant tokenAdmin = + 0x200C9b60e19634E12FC6D68B7FeA7Bfb26c2e418; + address public constant protoBroker = + 0x300C9b60E19634e12FC6D68B7FEa7bFB26c2E419; + address public constant TeamWallet = + 0x300C9b60E19634e12FC6D68B7FEa7bFB26c2E419; + address public constant DaoTreasury = + 0x400147C0Eb43D8D71b2B03037bB7B31f8f78EF5F; address public constant Eve = 0x50081b12838240B1bA02b3177153Bca678a86078; address public constant Dave = 0x50081b12838240B1ba02b3177153bCA678a86079; @@ -45,7 +50,11 @@ contract TaikoTokenTest is Test { bytes.concat( tko.init.selector, abi.encode( - address(addressManager), "Taiko Token", "TKO", premintRecipients, premintAmounts + address(addressManager), + "Taiko Token", + "TKO", + premintRecipients, + premintAmounts ) ) ); @@ -263,7 +272,10 @@ contract TaikoTokenTest is Test { addressManager.setAddress(block.chainid, nameHash, addr); } - function deployViaProxy(address implementation, bytes memory data) + function deployViaProxy( + address implementation, + bytes memory data + ) internal returns (TransparentUpgradeableProxy proxy) { diff --git a/packages/protocol/test/TokenVault.t.sol b/packages/protocol/test/TokenVault.t.sol index 4cac2694926..2873805f161 100644 --- a/packages/protocol/test/TokenVault.t.sol +++ b/packages/protocol/test/TokenVault.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import {AddressManager} from "../contracts/common/AddressManager.sol"; -import {AddressResolver} from "../contracts/common/AddressResolver.sol"; -import {Bridge} from "../contracts/bridge/Bridge.sol"; -import {BridgedERC20} from "../contracts/bridge/BridgedERC20.sol"; -import {BridgeErrors} from "../contracts/bridge/BridgeErrors.sol"; -import {FreeMintERC20} from "../contracts/test/erc20/FreeMintERC20.sol"; -import {SignalService} from "../contracts/signal/SignalService.sol"; -import {Test} from "forge-std/Test.sol"; -import {TokenVault} from "../contracts/bridge/TokenVault.sol"; +import { AddressManager } from "../contracts/common/AddressManager.sol"; +import { AddressResolver } from "../contracts/common/AddressResolver.sol"; +import { Bridge } from "../contracts/bridge/Bridge.sol"; +import { BridgedERC20 } from "../contracts/bridge/BridgedERC20.sol"; +import { BridgeErrors } from "../contracts/bridge/BridgeErrors.sol"; +import { FreeMintERC20 } from "../contracts/test/erc20/FreeMintERC20.sol"; +import { SignalService } from "../contracts/signal/SignalService.sol"; +import { Test } from "forge-std/Test.sol"; +import { TokenVault } from "../contracts/bridge/TokenVault.sol"; // PrankDestBridge lets us simulate a transaction to the TokenVault // from a named Bridge, without having to test/run through the real Bridge code, @@ -44,7 +44,9 @@ contract PrankDestBridge { bytes32 msgHash, address srcChainTokenVault, uint256 srcChainId - ) public { + ) + public + { ctx.sender = srcChainTokenVault; ctx.msgHash = msgHash; ctx.srcChainId = srcChainId; @@ -96,13 +98,21 @@ contract TestTokenVault is Test { addressManager.setAddress(block.chainid, "bridge", address(bridge)); - addressManager.setAddress(block.chainid, "signal_service", address(signalService)); + addressManager.setAddress( + block.chainid, "signal_service", address(signalService) + ); - addressManager.setAddress(block.chainid, "token_vault", address(tokenVault)); + addressManager.setAddress( + block.chainid, "token_vault", address(tokenVault) + ); - addressManager.setAddress(destChainId, "token_vault", address(destChainIdTokenVault)); + addressManager.setAddress( + destChainId, "token_vault", address(destChainIdTokenVault) + ); - addressManager.setAddress(destChainId, "bridge", address(destChainIdBridge)); + addressManager.setAddress( + destChainId, "bridge", address(destChainIdBridge) + ); vm.stopPrank(); } @@ -111,7 +121,9 @@ contract TestTokenVault is Test { vm.startPrank(Alice); vm.expectRevert("ERC20: insufficient allowance"); - tokenVault.sendERC20(destChainId, Bob, address(erc20), 1 wei, 1000000, 1, Bob, ""); + tokenVault.sendERC20( + destChainId, Bob, address(erc20), 1 wei, 1_000_000, 1, Bob, "" + ); } function test_send_erc20_no_processing_fee() public { @@ -123,7 +135,9 @@ contract TestTokenVault is Test { uint256 aliceBalanceBefore = erc20.balanceOf(Alice); uint256 tokenVaultBalanceBefore = erc20.balanceOf(address(tokenVault)); - tokenVault.sendERC20(destChainId, Bob, address(erc20), amount, 1000000, 0, Bob, ""); + tokenVault.sendERC20( + destChainId, Bob, address(erc20), amount, 1_000_000, 0, Bob, "" + ); uint256 aliceBalanceAfter = erc20.balanceOf(Alice); uint256 tokenVaultBalanceAfter = erc20.balanceOf(address(tokenVault)); @@ -132,14 +146,25 @@ contract TestTokenVault is Test { assertEq(tokenVaultBalanceAfter - tokenVaultBalanceBefore, amount); } - function test_send_erc20_processing_fee_reverts_if_msg_value_too_low() public { + function test_send_erc20_processing_fee_reverts_if_msg_value_too_low() + public + { vm.startPrank(Alice); uint256 amount = 2 wei; erc20.approve(address(tokenVault), amount); vm.expectRevert(); - tokenVault.sendERC20(destChainId, Bob, address(erc20), amount, 1000000, amount - 1, Bob, ""); + tokenVault.sendERC20( + destChainId, + Bob, + address(erc20), + amount, + 1_000_000, + amount - 1, + Bob, + "" + ); } function test_send_erc20_processing_fee() public { @@ -151,8 +176,15 @@ contract TestTokenVault is Test { uint256 aliceBalanceBefore = erc20.balanceOf(Alice); uint256 tokenVaultBalanceBefore = erc20.balanceOf(address(tokenVault)); - tokenVault.sendERC20{value: amount}( - destChainId, Bob, address(erc20), amount, 1000000, amount - 1, Bob, "" + tokenVault.sendERC20{ value: amount }( + destChainId, + Bob, + address(erc20), + amount, + 1_000_000, + amount - 1, + Bob, + "" ); uint256 aliceBalanceAfter = erc20.balanceOf(Alice); @@ -168,7 +200,9 @@ contract TestTokenVault is Test { uint256 amount = 0; vm.expectRevert(TokenVault.TOKENVAULT_INVALID_AMOUNT.selector); - tokenVault.sendERC20(destChainId, Bob, address(erc20), amount, 1000000, 0, Bob, ""); + tokenVault.sendERC20( + destChainId, Bob, address(erc20), amount, 1_000_000, 0, Bob, "" + ); } function test_send_erc20_reverts_invalid_token_address() public { @@ -177,7 +211,9 @@ contract TestTokenVault is Test { uint256 amount = 1; vm.expectRevert(TokenVault.TOKENVAULT_INVALID_TOKEN.selector); - tokenVault.sendERC20(destChainId, Bob, address(0), amount, 1000000, 0, Bob, ""); + tokenVault.sendERC20( + destChainId, Bob, address(0), amount, 1_000_000, 0, Bob, "" + ); } function test_send_erc20_reverts_invalid_to() public { @@ -186,10 +222,22 @@ contract TestTokenVault is Test { uint256 amount = 1; vm.expectRevert(TokenVault.TOKENVAULT_INVALID_TO.selector); - tokenVault.sendERC20(destChainId, address(0), address(erc20), amount, 1000000, 0, Bob, ""); + tokenVault.sendERC20( + destChainId, + address(0), + address(erc20), + amount, + 1_000_000, + 0, + Bob, + "" + ); } - function test_receive_erc20_canonical_to_dest_chain_transfers_from_canonical_token() public { + function test_receive_erc20_canonical_to_dest_chain_transfers_from_canonical_token( + ) + public + { vm.startPrank(Alice); uint256 srcChainId = block.chainid; @@ -220,7 +268,8 @@ contract TestTokenVault is Test { assertEq(toBalanceAfter - toBalanceBefore, amount); } - function test_receive_erc20_non_canonical_to_dest_chain_deploys_new_bridged_token_and_mints() + function test_receive_erc20_non_canonical_to_dest_chain_deploys_new_bridged_token_and_mints( + ) public { vm.startPrank(Alice); diff --git a/packages/protocol/test/genesis/GenerateGenesis.g.sol b/packages/protocol/test/genesis/GenerateGenesis.g.sol index cc49c957b67..00dfc582419 100644 --- a/packages/protocol/test/genesis/GenerateGenesis.g.sol +++ b/packages/protocol/test/genesis/GenerateGenesis.g.sol @@ -5,31 +5,34 @@ import "forge-std/StdJson.sol"; import "../../contracts/bridge/BridgeErrors.sol"; import "../../contracts/bridge/IBridge.sol"; import "../../contracts/common/AddressResolver.sol"; -import {Test} from "forge-std/Test.sol"; -import {console2} from "forge-std/console2.sol"; -import {TaikoL2} from "../../contracts/L2/TaikoL2.sol"; -import {AddressManager} from "../../contracts/common/AddressManager.sol"; -import {Bridge} from "../../contracts/bridge/Bridge.sol"; -import {TokenVault} from "../../contracts/bridge/TokenVault.sol"; -import {EtherVault} from "../../contracts/bridge/EtherVault.sol"; -import {SignalService} from "../../contracts/signal/SignalService.sol"; -import {LibBridgeStatus} from "../../contracts/bridge/libs/LibBridgeStatus.sol"; -import {LibL2Consts} from "../../contracts/L2/LibL2Consts.sol"; -import {RegularERC20} from "../../contracts/test/erc20/RegularERC20.sol"; -import {TransparentUpgradeableProxy} from +import { Test } from "forge-std/Test.sol"; +import { console2 } from "forge-std/console2.sol"; +import { TaikoL2 } from "../../contracts/L2/TaikoL2.sol"; +import { AddressManager } from "../../contracts/common/AddressManager.sol"; +import { Bridge } from "../../contracts/bridge/Bridge.sol"; +import { TokenVault } from "../../contracts/bridge/TokenVault.sol"; +import { EtherVault } from "../../contracts/bridge/EtherVault.sol"; +import { SignalService } from "../../contracts/signal/SignalService.sol"; +import { LibBridgeStatus } from + "../../contracts/bridge/libs/LibBridgeStatus.sol"; +import { LibL2Consts } from "../../contracts/L2/LibL2Consts.sol"; +import { RegularERC20 } from "../../contracts/test/erc20/RegularERC20.sol"; +import { TransparentUpgradeableProxy } from "../../contracts/thirdparty/TransparentUpgradeableProxy.sol"; contract TestGenerateGenesis is Test, AddressResolver { using stdJson for string; - string private configJSON = - vm.readFile(string.concat(vm.projectRoot(), "/test/genesis/test_config.json")); - string private genesisAllocJSON = - vm.readFile(string.concat(vm.projectRoot(), "/deployments/genesis_alloc.json")); + string private configJSON = vm.readFile( + string.concat(vm.projectRoot(), "/test/genesis/test_config.json") + ); + string private genesisAllocJSON = vm.readFile( + string.concat(vm.projectRoot(), "/deployments/genesis_alloc.json") + ); address private owner = configJSON.readAddress(".contractOwner"); address private admin = configJSON.readAddress(".contractAdmin"); - uint64 public constant BLOCK_GAS_LIMIT = 30000000; + uint64 public constant BLOCK_GAS_LIMIT = 30_000_000; function testContractDeployment() public { assertEq(block.chainid, 167); @@ -69,7 +72,9 @@ contract TestGenerateGenesis is Test, AddressResolver { checkSavedAddress(addressManager, "TokenVaultProxy", "token_vault"); checkSavedAddress(addressManager, "EtherVaultProxy", "ether_vault"); checkSavedAddress(addressManager, "TaikoL2Proxy", "taiko"); - checkSavedAddress(addressManager, "SignalServiceProxy", "signal_service"); + checkSavedAddress( + addressManager, "SignalServiceProxy", "signal_service" + ); TransparentUpgradeableProxy proxy = TransparentUpgradeableProxy( payable(getPredeployedContractAddress("AddressManagerProxy")) @@ -92,7 +97,11 @@ contract TestGenerateGenesis is Test, AddressResolver { for (uint64 i = 0; i < 300; i++) { vm.roll(block.number + 1); vm.warp(taikoL2.parentTimestamp() + 12); - vm.fee(taikoL2.getBasefee(12, BLOCK_GAS_LIMIT, i + LibL2Consts.ANCHOR_GAS_COST)); + vm.fee( + taikoL2.getBasefee( + 12, BLOCK_GAS_LIMIT, i + LibL2Consts.ANCHOR_GAS_COST + ) + ); uint256 gasLeftBefore = gasleft(); @@ -105,7 +114,8 @@ contract TestGenerateGenesis is Test, AddressResolver { if (i == 299) { console2.log( - "TaikoL2.anchor gas cost after 256 L2 blocks:", gasLeftBefore - gasleft() + "TaikoL2.anchor gas cost after 256 L2 blocks:", + gasLeftBefore - gasleft() ); } } @@ -113,8 +123,9 @@ contract TestGenerateGenesis is Test, AddressResolver { vm.startPrank(admin); - TransparentUpgradeableProxy proxy = - TransparentUpgradeableProxy(payable(getPredeployedContractAddress("TaikoL2Proxy"))); + TransparentUpgradeableProxy proxy = TransparentUpgradeableProxy( + payable(getPredeployedContractAddress("TaikoL2Proxy")) + ); TaikoL2 newTaikoL2 = new TaikoL2(); @@ -125,7 +136,8 @@ contract TestGenerateGenesis is Test, AddressResolver { } function testBridge() public { - address payable bridgeAddress = payable(getPredeployedContractAddress("BridgeProxy")); + address payable bridgeAddress = + payable(getPredeployedContractAddress("BridgeProxy")); Bridge bridge = Bridge(bridgeAddress); assertEq(owner, bridge.owner()); @@ -152,8 +164,9 @@ contract TestGenerateGenesis is Test, AddressResolver { vm.startPrank(admin); - TransparentUpgradeableProxy proxy = - TransparentUpgradeableProxy(payable(getPredeployedContractAddress("BridgeProxy"))); + TransparentUpgradeableProxy proxy = TransparentUpgradeableProxy( + payable(getPredeployedContractAddress("BridgeProxy")) + ); Bridge newBridge = new Bridge(); @@ -170,13 +183,19 @@ contract TestGenerateGenesis is Test, AddressResolver { assertEq(owner, etherVault.owner()); - assertEq(etherVault.isAuthorized(getPredeployedContractAddress("BridgeProxy")), true); + assertEq( + etherVault.isAuthorized( + getPredeployedContractAddress("BridgeProxy") + ), + true + ); assertEq(etherVault.isAuthorized(etherVault.owner()), false); vm.startPrank(admin); - TransparentUpgradeableProxy proxy = - TransparentUpgradeableProxy(payable(getPredeployedContractAddress("EtherVaultProxy"))); + TransparentUpgradeableProxy proxy = TransparentUpgradeableProxy( + payable(getPredeployedContractAddress("EtherVaultProxy")) + ); EtherVault newEtherVault = new EtherVault(); @@ -187,7 +206,8 @@ contract TestGenerateGenesis is Test, AddressResolver { } function testTokenVault() public { - address tokenVaultAddress = getPredeployedContractAddress("TokenVaultProxy"); + address tokenVaultAddress = + getPredeployedContractAddress("TokenVaultProxy"); address bridgeAddress = getPredeployedContractAddress("BridgeProxy"); TokenVault tokenVault = TokenVault(tokenVaultAddress); @@ -203,8 +223,9 @@ contract TestGenerateGenesis is Test, AddressResolver { vm.startPrank(admin); - TransparentUpgradeableProxy proxy = - TransparentUpgradeableProxy(payable(getPredeployedContractAddress("TokenVaultProxy"))); + TransparentUpgradeableProxy proxy = TransparentUpgradeableProxy( + payable(getPredeployedContractAddress("TokenVaultProxy")) + ); TokenVault newTokenVault = new TokenVault(); @@ -237,32 +258,43 @@ contract TestGenerateGenesis is Test, AddressResolver { } function testERC20() public { - RegularERC20 regularERC20 = RegularERC20(getPredeployedContractAddress("RegularERC20")); + RegularERC20 regularERC20 = + RegularERC20(getPredeployedContractAddress("RegularERC20")); assertEq(regularERC20.name(), "RegularERC20"); assertEq(regularERC20.symbol(), "RGL"); } - function getPredeployedContractAddress(string memory contractName) private returns (address) { - return configJSON.readAddress(string.concat(".contractAddresses.", contractName)); + function getPredeployedContractAddress(string memory contractName) + private + returns (address) + { + return configJSON.readAddress( + string.concat(".contractAddresses.", contractName) + ); } function checkDeployedCode(string memory contractName) private { address contractAddress = getPredeployedContractAddress(contractName); - string memory deployedCode = - genesisAllocJSON.readString(string.concat(".", vm.toString(contractAddress), ".code")); + string memory deployedCode = genesisAllocJSON.readString( + string.concat(".", vm.toString(contractAddress), ".code") + ); assertEq(address(contractAddress).code, vm.parseBytes(deployedCode)); } - function checkProxyImplementation(string memory proxyName, string memory contractName) + function checkProxyImplementation( + string memory proxyName, + string memory contractName + ) private { vm.startPrank(admin); address contractAddress = getPredeployedContractAddress(contractName); address proxyAddress = getPredeployedContractAddress(proxyName); - TransparentUpgradeableProxy proxy = TransparentUpgradeableProxy(payable(proxyAddress)); + TransparentUpgradeableProxy proxy = + TransparentUpgradeableProxy(payable(proxyAddress)); assertEq(proxy.implementation(), address(contractAddress)); @@ -275,7 +307,9 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManager, string memory contractName, bytes32 name - ) private { + ) + private + { assertEq( getPredeployedContractAddress(contractName), addressManager.getAddress(block.chainid, name) diff --git a/packages/website/pages/docs/reference/contract-documentation/L1/TaikoData.md b/packages/website/pages/docs/reference/contract-documentation/L1/TaikoData.md index 37abc79bd72..16bb9c07c22 100644 --- a/packages/website/pages/docs/reference/contract-documentation/L1/TaikoData.md +++ b/packages/website/pages/docs/reference/contract-documentation/L1/TaikoData.md @@ -34,14 +34,10 @@ struct Config { ```solidity struct StateVariables { uint64 blockFee; - uint64 accBlockFees; uint64 genesisHeight; uint64 genesisTimestamp; uint64 numBlocks; - uint64 proofTimeIssued; - uint64 proofTimeTarget; uint64 lastVerifiedBlockId; - uint64 accProposedAt; uint64 nextEthDepositToProcess; uint64 numEthDeposits; } @@ -152,17 +148,17 @@ struct State { struct TaikoData.EthDeposit[] ethDeposits; uint64 genesisHeight; uint64 genesisTimestamp; - uint16 adjustmentQuotient; + uint16 __reserved70; uint48 __reserved71; uint64 __reserved72; - uint64 accProposedAt; - uint64 accBlockFees; + uint64 __reserved80; + uint64 __reserved81; uint64 numBlocks; uint64 nextEthDepositToProcess; uint64 blockFee; - uint64 proofTimeIssued; + uint64 __reserved90; uint64 lastVerifiedBlockId; - uint64 proofTimeTarget; + uint64 __reserved91; uint256[42] __gap; } ``` diff --git a/packages/website/pages/docs/reference/contract-documentation/L1/TaikoErrors.md b/packages/website/pages/docs/reference/contract-documentation/L1/TaikoErrors.md index 85b66c7b9c7..d03d35973ed 100644 --- a/packages/website/pages/docs/reference/contract-documentation/L1/TaikoErrors.md +++ b/packages/website/pages/docs/reference/contract-documentation/L1/TaikoErrors.md @@ -28,12 +28,6 @@ error L1_EVIDENCE_MISMATCH(bytes32 expected, bytes32 actual) error L1_FORK_CHOICE_NOT_FOUND() ``` -### L1_INSUFFICIENT_TOKEN - -```solidity -error L1_INSUFFICIENT_TOKEN() -``` - ### L1_INVALID_CONFIG ```solidity diff --git a/packages/website/pages/docs/reference/contract-documentation/L1/TaikoL1.md b/packages/website/pages/docs/reference/contract-documentation/L1/TaikoL1.md index bf6d15f3928..970a4190151 100644 --- a/packages/website/pages/docs/reference/contract-documentation/L1/TaikoL1.md +++ b/packages/website/pages/docs/reference/contract-documentation/L1/TaikoL1.md @@ -19,21 +19,18 @@ receive() external payable ### init ```solidity -function init(address _addressManager, bytes32 _genesisBlockHash, uint64 _initBlockFee, uint64 _initProofTimeTarget, uint64 _initProofTimeIssued, uint16 _adjustmentQuotient) external +function init(address _addressManager, bytes32 _genesisBlockHash, uint64 _initBlockFee) external ``` Initialize the rollup. #### Parameters -| Name | Type | Description | -| --------------------- | ------- | ------------------------------------------------------------------- | -| \_addressManager | address | The AddressManager address. | -| \_genesisBlockHash | bytes32 | The block hash of the genesis block. | -| \_initBlockFee | uint64 | Initial (reasonable) block fee value. | -| \_initProofTimeTarget | uint64 | Initial (reasonable) proof submission time target. | -| \_initProofTimeIssued | uint64 | Initial proof time issued corresponding with the initial block fee. | -| \_adjustmentQuotient | uint16 | Block fee calculation adjustment quotient. | +| Name | Type | Description | +| ------------------ | ------- | ------------------------------------- | +| \_addressManager | address | The AddressManager address. | +| \_genesisBlockHash | bytes32 | The block hash of the genesis block. | +| \_initBlockFee | uint64 | Initial (reasonable) block fee value. | ### proposeBlock @@ -79,35 +76,6 @@ Verify up to N blocks. | --------- | ------- | ------------------------------- | | maxBlocks | uint256 | Max number of blocks to verify. | -### setProofParams - -```solidity -function setProofParams(uint64 newProofTimeTarget, uint64 newProofTimeIssued, uint64 newBlockFee, uint16 newAdjustmentQuotient) external -``` - -Change proof parameters (time target and time issued) - to avoid complex/risky upgrades in case need to change relatively frequently. - -#### Parameters - -| Name | Type | Description | -| --------------------- | ------ | ------------------------------------------------------------------------- | -| newProofTimeTarget | uint64 | New proof time target. | -| newProofTimeIssued | uint64 | New proof time issued. If set to type(uint64).max, let it be unchanged. | -| newBlockFee | uint64 | New blockfee. If set to type(uint64).max, let it be unchanged. | -| newAdjustmentQuotient | uint16 | New adjustment quotient. If set to type(uint16).max, let it be unchanged. | - -### depositTaikoToken - -```solidity -function depositTaikoToken(uint256 amount) external -``` - -### withdrawTaikoToken - -```solidity -function withdrawTaikoToken(uint256 amount) external -``` - ### depositEtherToL2 ```solidity @@ -126,12 +94,6 @@ function getTaikoTokenBalance(address addr) public view returns (uint256) function getBlockFee() public view returns (uint64) ``` -### getProofReward - -```solidity -function getProofReward(uint64 proofTime) public view returns (uint64) -``` - ### getBlock ```solidity diff --git a/packages/website/pages/docs/reference/contract-documentation/common/AddressResolver.md b/packages/website/pages/docs/reference/contract-documentation/common/AddressResolver.md index 448cb93a26f..169e6f93ab9 100644 --- a/packages/website/pages/docs/reference/contract-documentation/common/AddressResolver.md +++ b/packages/website/pages/docs/reference/contract-documentation/common/AddressResolver.md @@ -13,6 +13,12 @@ it uses an AddressManager to manage the name-to-address mapping. contract IAddressManager _addressManager ``` +### AddressManagerChanged + +```solidity +event AddressManagerChanged(address addressManager) +``` + ### RESOLVER_DENIED ```solidity @@ -37,12 +43,6 @@ error RESOLVER_ZERO_ADDR(uint256 chainId, bytes32 name) modifier onlyFromNamed(bytes32 name) ``` -### AddressManagerChanged - -```solidity -event AddressManagerChanged(address addressManager) -``` - ### resolve ```solidity