diff --git a/packages/protocol/contracts/L2/TaikoL2.sol b/packages/protocol/contracts/L2/TaikoL2.sol index a3c76fef681..3c5b89163e2 100644 --- a/packages/protocol/contracts/L2/TaikoL2.sol +++ b/packages/protocol/contracts/L2/TaikoL2.sol @@ -28,7 +28,7 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { struct EIP1559Params { uint64 basefee; - uint64 gasIssuedPerSecond; + uint32 gasIssuedPerSecond; uint64 gasExcessMax; uint64 gasTarget; uint64 ratio2x1x; @@ -37,7 +37,7 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { struct EIP1559Config { uint128 yscale; uint64 xscale; - uint64 gasIssuedPerSecond; + uint32 gasIssuedPerSecond; } /*////////////////////////////////////////////////////////////// @@ -71,7 +71,7 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { event Anchored( uint64 number, uint64 basefee, - uint64 gaslimit, + uint32 gaslimit, uint64 timestamp, bytes32 parentHash, uint256 prevrandao, @@ -89,9 +89,8 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { error L2_INVALID_SENDER(); error L2_PUBLIC_INPUT_HASH_MISMATCH(bytes32 expected, bytes32 actual); error L2_TOO_LATE(); - - error M1559_UNEXPECTED_CHANGE(uint64 expected, uint64 actual); - error M1559_OUT_OF_STOCK(); + error L2_1559_UNEXPECTED_CHANGE(uint64 expected, uint64 actual); + error L2_1559_OUT_OF_STOCK(); /*////////////////////////////////////////////////////////////// USER-FACING FUNCTIONS @@ -172,7 +171,7 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { bytes32 l1Hash, bytes32 l1SignalRoot, uint64 l1Height, - uint64 parentGasUsed + uint32 parentGasUsed ) external { @@ -203,7 +202,7 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { (basefee, gasExcess) = _calcBasefee( config, block.timestamp - parentTimestamp, - uint64(block.gaslimit), + uint32(block.gaslimit), parentGasUsed ); } @@ -224,7 +223,7 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { emit Anchored({ number: uint64(block.number), basefee: uint64(basefee), - gaslimit: uint64(block.gaslimit), + gaslimit: uint32(block.gaslimit), timestamp: uint64(block.timestamp), parentHash: parentHash, prevrandao: block.prevrandao, @@ -235,8 +234,8 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { function getBasefee( uint32 timeSinceParent, - uint64 gasLimit, - uint64 parentGasUsed + uint32 gasLimit, + uint32 parentGasUsed ) public view @@ -322,8 +321,8 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { function _calcBasefee( EIP1559Config memory config, uint256 timeSinceParent, - uint64 gasLimit, - uint64 parentGasUsed + uint32 gasLimit, + uint32 parentGasUsed ) private view @@ -331,7 +330,7 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync { { // Very important to cap _gasExcess uint64 unchecked { - uint64 parentGasUsedNet = parentGasUsed + uint32 parentGasUsedNet = parentGasUsed > LibL2Consts.ANCHOR_GAS_COST ? parentGasUsed - LibL2Consts.ANCHOR_GAS_COST : 0; diff --git a/packages/protocol/contracts/libs/Lib1559Math.sol b/packages/protocol/contracts/libs/Lib1559Math.sol index d3147dbd092..450618c9890 100644 --- a/packages/protocol/contracts/libs/Lib1559Math.sol +++ b/packages/protocol/contracts/libs/Lib1559Math.sol @@ -13,8 +13,8 @@ import { SafeCastUpgradeable } from library Lib1559Math { using SafeCastUpgradeable for uint256; - error M1559_UNEXPECTED_CHANGE(uint64 expected, uint64 actual); - error M1559_OUT_OF_STOCK(); + error L2_1559_UNEXPECTED_CHANGE(uint64 expected, uint64 actual); + error L2_1559_OUT_OF_STOCK(); function calculateScales( uint64 xExcessMax, @@ -42,7 +42,7 @@ library Lib1559Math { uint64 ratio = uint64((price2x * 10_000) / price1x); if (ratio2x1x != ratio) { - revert M1559_UNEXPECTED_CHANGE(ratio2x1x, ratio); + revert L2_1559_UNEXPECTED_CHANGE(ratio2x1x, ratio); } } @@ -66,7 +66,7 @@ library Lib1559Math { function _calcY(uint256 x, uint128 xscale) private pure returns (uint256) { uint256 _x = x * xscale; if (_x >= LibFixedPointMath.MAX_EXP_INPUT) { - revert M1559_OUT_OF_STOCK(); + revert L2_1559_OUT_OF_STOCK(); } return uint256(LibFixedPointMath.exp(int256(_x))); } diff --git a/packages/protocol/docs/tokenomics_objective_metrics.md b/packages/protocol/docs/tokenomics_objective_metrics.md index b81ffdeff41..202bf7d2e02 100644 --- a/packages/protocol/docs/tokenomics_objective_metrics.md +++ b/packages/protocol/docs/tokenomics_objective_metrics.md @@ -1,9 +1,8 @@ - # Objective and Metrics in Tokenomics Design ## Objective -The current tokenomics structure rewards the fastest prover, inadvertently promoting speed over cost-effectiveness. This contradicts Taiko's goal of delivering cost-efficient proofs. By shifting the incentives towards cost-effective proofs, we can dramatically decrease Taiko's overall Layer 2 (L2) expenses, thereby augmenting our competitive standing in the market. +Taiko's goal is to promote cost-efficient proofs, which dramatically decreases Taiko's overall Layer 2 (L2) expenses, thereby augmenting our competitive standing in the market. ## Key Metrics @@ -19,10 +18,10 @@ Based on the provided insights and inputs from Brecht and Hugo (zkpool), the fol 1. **No Built-In PoS Reward**: To prevent being classified as a security, our tokenomics design should not offer tokens to stakers as rewards. A prover may establish a staking-based reward system allowing token holders to delegate their power, but this should not be considered as part of our tokenomics. -1. **Immediate Proof Submission**: Provers should not be required to withhold their proofs and wait offline for the optimal submission moment. Introducing such a system would entail the development of additional infrastructure to store proofs and make strategic decisions regarding submission timings. This increased complexity compared to our competitors could discourage potential provers from participating. Therefore, our tokenomics should incentivize immediate proof submissions as soon as they are ready. This approach enables the system to accurately capture the actual time taken by each proof, facilitating automatic adjustment of relevant parameters. - 1. **Simplicity in Design**: Ensuring simplicity in the design of our tokenomics is of paramount importance. It is imperative for decision-makers and engineers within prover companies to easily comprehend the system. The design should encapsulate core concepts concisely and coherently, allowing for rapid understanding of the fundamental principles. This clarity facilitates efficient formulation of strategies and algorithms by provers, enhancing their system participation. 1. **Minimal L1 Cost**: The complexity of the required code in the smart contracts/node is also an important factor to consider. Our tokenomics should strive to minimize the average additional cost per block on its base layer. Provers will likely impose higher fees on L2 to offset this cost, potentially leaving out transactions with lower fees. +1. **Immediate Proof Submission**: Provers should not be required to withhold their proofs and wait offline for the optimal submission moment. Introducing such a system would entail the development of additional infrastructure to store proofs and make strategic decisions regarding submission timings. This increased complexity compared to our competitors could discourage potential provers from participating. Therefore, our tokenomics should incentivize immediate proof submissions as soon as they are ready. This approach enables the system to accurately capture the actual time taken by each proof, facilitating automatic adjustment of relevant parameters. + The above comparison metrics should guide our discussions and prevent an overemphasis on subjective opinions. diff --git a/packages/protocol/test/Taiko1559Params.t.sol b/packages/protocol/test/Taiko1559Params.t.sol index 4719a4bf9a0..cacd8e42244 100644 --- a/packages/protocol/test/Taiko1559Params.t.sol +++ b/packages/protocol/test/Taiko1559Params.t.sol @@ -25,8 +25,8 @@ contract TestTaiko1559Params is Test { // https://ultrasound.money/ uint64 ethereumBasefeeNow = 28_000_000_000; // 28Gwei - uint64 gasIssuedPerSecond = - (scaleFactor * ethereumBlockGasTarget) / ethereumBlockTime; + uint32 gasIssuedPerSecond = + uint32(scaleFactor * ethereumBlockGasTarget / ethereumBlockTime); // Tune this number manually so ratio2x1x is ~112.5%. uint64 maxSeconds = 7272; diff --git a/packages/protocol/test/TaikoL2.t.sol b/packages/protocol/test/TaikoL2.t.sol index df14e09ce37..2a98cc260ce 100644 --- a/packages/protocol/test/TaikoL2.t.sol +++ b/packages/protocol/test/TaikoL2.t.sol @@ -12,12 +12,12 @@ import { SafeCastUpgradeable } from contract TestTaikoL2 is Test { using SafeCastUpgradeable for uint256; - uint64 public constant BLOCK_GAS_LIMIT = 30_000_000; // same as + uint32 public constant BLOCK_GAS_LIMIT = 30_000_000; // same as // `block_gas_limit` in foundry.toml TaikoL2 public L2; uint256 private logIndex; - uint64 private ANCHOR_GAS_COST = LibL2Consts.ANCHOR_GAS_COST; + uint32 private ANCHOR_GAS_COST = LibL2Consts.ANCHOR_GAS_COST; function setUp() public { uint16 rand = 2; @@ -158,8 +158,8 @@ contract TestTaikoL2 is Test { function _getBasefeeAndPrint( uint32 timeSinceParent, - uint64 gasLimit, - uint64 parentGasUsed + uint32 gasLimit, + uint32 parentGasUsed ) private returns (uint256 _basefee) @@ -196,7 +196,7 @@ contract TestTaikoL2 is Test { function _getBasefeeAndPrint( uint32 timeSinceNow, - uint64 gasLimit + uint32 gasLimit ) private returns (uint256 _basefee) @@ -208,7 +208,7 @@ contract TestTaikoL2 is Test { ); } - function _anchor(uint64 parentGasLimit) private { + function _anchor(uint32 parentGasLimit) private { L2.anchor( keccak256("a"), keccak256("b"), diff --git a/packages/protocol/test/genesis/GenerateGenesis.g.sol b/packages/protocol/test/genesis/GenerateGenesis.g.sol index adbc3e832ec..0074a8dcb3f 100644 --- a/packages/protocol/test/genesis/GenerateGenesis.g.sol +++ b/packages/protocol/test/genesis/GenerateGenesis.g.sol @@ -32,7 +32,7 @@ contract TestGenerateGenesis is Test, AddressResolver { address private owner = configJSON.readAddress(".contractOwner"); address private admin = configJSON.readAddress(".contractAdmin"); - uint64 public constant BLOCK_GAS_LIMIT = 30_000_000; + uint32 public constant BLOCK_GAS_LIMIT = 30_000_000; function testContractDeployment() public { assertEq(block.chainid, 167); @@ -94,7 +94,7 @@ contract TestGenerateGenesis is Test, AddressResolver { TaikoL2 taikoL2 = TaikoL2(getPredeployedContractAddress("TaikoL2Proxy")); vm.startPrank(taikoL2.GOLDEN_TOUCH_ADDRESS()); - for (uint64 i = 0; i < 300; i++) { + for (uint32 i = 0; i < 300; i++) { vm.roll(block.number + 1); vm.warp(taikoL2.parentTimestamp() + 12); vm.fee( diff --git a/packages/website/pages/docs/reference/contract-documentation/L2/TaikoL2.md b/packages/website/pages/docs/reference/contract-documentation/L2/TaikoL2.md index 533e2c0650c..00e5d9011c7 100644 --- a/packages/website/pages/docs/reference/contract-documentation/L2/TaikoL2.md +++ b/packages/website/pages/docs/reference/contract-documentation/L2/TaikoL2.md @@ -18,7 +18,7 @@ struct VerifiedBlock { ```solidity struct EIP1559Params { uint64 basefee; - uint64 gasIssuedPerSecond; + uint32 gasIssuedPerSecond; uint64 gasExcessMax; uint64 gasTarget; uint64 ratio2x1x; @@ -31,7 +31,7 @@ struct EIP1559Params { struct EIP1559Config { uint128 yscale; uint64 xscale; - uint64 gasIssuedPerSecond; + uint32 gasIssuedPerSecond; } ``` @@ -62,7 +62,7 @@ uint64 gasExcess ### Anchored ```solidity -event Anchored(uint64 number, uint64 basefee, uint64 gaslimit, uint64 timestamp, bytes32 parentHash, uint256 prevrandao, address coinbase, uint32 chainid) +event Anchored(uint64 number, uint64 basefee, uint32 gaslimit, uint64 timestamp, bytes32 parentHash, uint256 prevrandao, address coinbase, uint32 chainid) ``` ### L2_BASEFEE_MISMATCH @@ -101,16 +101,16 @@ error L2_PUBLIC_INPUT_HASH_MISMATCH(bytes32 expected, bytes32 actual) error L2_TOO_LATE() ``` -### M1559_UNEXPECTED_CHANGE +### L2_1559_UNEXPECTED_CHANGE ```solidity -error M1559_UNEXPECTED_CHANGE(uint64 expected, uint64 actual) +error L2_1559_UNEXPECTED_CHANGE(uint64 expected, uint64 actual) ``` -### M1559_OUT_OF_STOCK +### L2_1559_OUT_OF_STOCK ```solidity -error M1559_OUT_OF_STOCK() +error L2_1559_OUT_OF_STOCK() ``` ### init @@ -122,7 +122,7 @@ function init(address _addressManager, struct TaikoL2.EIP1559Params _param1559) ### anchor ```solidity -function anchor(bytes32 l1Hash, bytes32 l1SignalRoot, uint64 l1Height, uint64 parentGasUsed) external +function anchor(bytes32 l1Hash, bytes32 l1SignalRoot, uint64 l1Height, uint32 parentGasUsed) external ``` Persist the latest L1 block height and hash to L2 for cross-layer @@ -145,12 +145,12 @@ This transaction shall be the first transaction in every L2 block. | l1Hash | bytes32 | The latest L1 block hash when this block was proposed. | | l1SignalRoot | bytes32 | The latest value of the L1 "signal service storage root". | | l1Height | uint64 | The latest L1 block height when this block was proposed. | -| parentGasUsed | uint64 | the gas used in the parent block. | +| parentGasUsed | uint32 | the gas used in the parent block. | ### getBasefee ```solidity -function getBasefee(uint32 timeSinceParent, uint64 gasLimit, uint64 parentGasUsed) public view returns (uint256 _basefee) +function getBasefee(uint32 timeSinceParent, uint32 gasLimit, uint32 parentGasUsed) public view returns (uint256 _basefee) ``` ### getCrossChainBlockHash