diff --git a/packages/protocol/contract_layout.md b/packages/protocol/contract_layout.md index 26860eabd3..bec4136538 100644 --- a/packages/protocol/contract_layout.md +++ b/packages/protocol/contract_layout.md @@ -35,10 +35,10 @@ | __gap | uint256[49] | 202 | 0 | 1568 | contracts/L2/TaikoL2.sol:TaikoL2 | | l2Hashes | mapping(uint256 => bytes32) | 251 | 0 | 32 | contracts/L2/TaikoL2.sol:TaikoL2 | | publicInputHash | bytes32 | 252 | 0 | 32 | contracts/L2/TaikoL2.sol:TaikoL2 | -| gasExcess | uint64 | 253 | 0 | 8 | contracts/L2/TaikoL2.sol:TaikoL2 | +| parentGasExcess | uint64 | 253 | 0 | 8 | contracts/L2/TaikoL2.sol:TaikoL2 | | lastSyncedBlock | uint64 | 253 | 8 | 8 | contracts/L2/TaikoL2.sol:TaikoL2 | | parentTimestamp | uint64 | 253 | 16 | 8 | contracts/L2/TaikoL2.sol:TaikoL2 | -| __deprecated2 | uint64 | 253 | 24 | 8 | contracts/L2/TaikoL2.sol:TaikoL2 | +| parentGasTarget | uint64 | 253 | 24 | 8 | contracts/L2/TaikoL2.sol:TaikoL2 | | l1ChainId | uint64 | 254 | 0 | 8 | contracts/L2/TaikoL2.sol:TaikoL2 | | __gap | uint256[46] | 255 | 0 | 1472 | contracts/L2/TaikoL2.sol:TaikoL2 | diff --git a/packages/protocol/contracts/L1/TaikoData.sol b/packages/protocol/contracts/L1/TaikoData.sol index e2cae944c1..8b08b699a1 100644 --- a/packages/protocol/contracts/L1/TaikoData.sol +++ b/packages/protocol/contracts/L1/TaikoData.sol @@ -41,7 +41,7 @@ library TaikoData { // --------------------------------------------------------------------- uint8 basefeeAdjustmentQuotient; uint8 basefeeSharingPctg; - uint32 gasTargetPerL1Block; + uint32 gasIssuancePerSecond; // --------------------------------------------------------------------- // Group 6: Others // --------------------------------------------------------------------- @@ -126,7 +126,7 @@ library TaikoData { uint8 blobIndex; uint8 basefeeAdjustmentQuotient; uint8 basefeeSharingPctg; - uint32 gasTargetPerL1Block; + uint32 gasIssuancePerSecond; } /// @dev Struct representing transition to be proven. diff --git a/packages/protocol/contracts/L1/TaikoL1.sol b/packages/protocol/contracts/L1/TaikoL1.sol index e4d70136e6..96a5651edd 100644 --- a/packages/protocol/contracts/L1/TaikoL1.sol +++ b/packages/protocol/contracts/L1/TaikoL1.sol @@ -287,7 +287,7 @@ contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents { maxAnchorHeightOffset: 64, basefeeAdjustmentQuotient: 8, basefeeSharingPctg: 75, - gasTargetPerL1Block: 60_000_000, + gasIssuancePerSecond: 5_000_000, ontakeForkHeight: 374_400 // = 7200 * 52 }); } diff --git a/packages/protocol/contracts/L1/libs/LibData.sol b/packages/protocol/contracts/L1/libs/LibData.sol index d8ea53b743..f497b7fa0a 100644 --- a/packages/protocol/contracts/L1/libs/LibData.sol +++ b/packages/protocol/contracts/L1/libs/LibData.sol @@ -78,7 +78,7 @@ library LibData { blobIndex: 0, basefeeAdjustmentQuotient: 0, basefeeSharingPctg: 0, - gasTargetPerL1Block: 0 + gasIssuancePerSecond: 0 }); } } diff --git a/packages/protocol/contracts/L1/libs/LibProposing.sol b/packages/protocol/contracts/L1/libs/LibProposing.sol index 0e8b2c893c..14afcf4f5c 100644 --- a/packages/protocol/contracts/L1/libs/LibProposing.sol +++ b/packages/protocol/contracts/L1/libs/LibProposing.sol @@ -176,7 +176,7 @@ library LibProposing { blobIndex: local.params.blobIndex, basefeeAdjustmentQuotient: _config.basefeeAdjustmentQuotient, basefeeSharingPctg: _config.basefeeSharingPctg, - gasTargetPerL1Block: _config.gasTargetPerL1Block + gasIssuancePerSecond: _config.gasIssuancePerSecond }); } diff --git a/packages/protocol/contracts/L2/Lib1559Math.sol b/packages/protocol/contracts/L2/Lib1559Math.sol index 1ee53ef118..aac64054f2 100644 --- a/packages/protocol/contracts/L2/Lib1559Math.sol +++ b/packages/protocol/contracts/L2/Lib1559Math.sol @@ -15,8 +15,7 @@ library Lib1559Math { error EIP1559_INVALID_PARAMS(); function calc1559BaseFee( - uint32 _gasTarget, - uint8 _adjustmentQuotient, + uint256 _gasTarget, uint64 _gasExcess, uint64 _gasIssuance, uint32 _parentGasUsed @@ -35,42 +34,50 @@ library Lib1559Math { // bonding curve, regardless the actual amount of gas used by this // block, however, this block's gas used will affect the next // block's base fee. - basefee_ = basefee(gasExcess_, uint256(_adjustmentQuotient) * _gasTarget); - - // Always make sure basefee is nonzero, this is required by the node. - if (basefee_ == 0) basefee_ = 1; + basefee_ = basefee(gasExcess_, _gasTarget); } - /// @dev eth_qty(excess_gas_issued) / (TARGET * ADJUSTMENT_QUOTIENT) - /// @param _gasExcess The gas excess value - /// @param _adjustmentFactor The product of gasTarget and adjustmentQuotient - function basefee( - uint256 _gasExcess, - uint256 _adjustmentFactor + /// @dev Returns the new gas excess that will keep the basefee the same. + /// `_newGasTarget * ln(_newGasTarget / _target) + _gasExcess * _newGasTarget / _target` + function adjustExcess( + uint64 _gasExcess, + uint64 _gasTarget, + uint64 _newGasTarget ) internal pure - returns (uint256) + returns (uint64) { - if (_adjustmentFactor == 0) { - revert EIP1559_INVALID_PARAMS(); + if (_gasTarget == 0) revert EIP1559_INVALID_PARAMS(); + + uint256 f = LibFixedPointMath.SCALING_FACTOR; + uint256 ratio = f * _newGasTarget / _gasTarget; + if (ratio > uint256(type(int256).max)) revert EIP1559_INVALID_PARAMS(); + + int256 lnRatio = LibFixedPointMath.ln(int256(ratio)); // may be negative + + uint256 newGasExcess; + assembly { + newGasExcess := sdiv(add(mul(lnRatio, _newGasTarget), mul(ratio, _gasExcess)), f) } - return _ethQty(_gasExcess, _adjustmentFactor) / LibFixedPointMath.SCALING_FACTOR; + + return uint64(newGasExcess.min(type(uint64).max)); } - /// @dev exp(gas_qty / TARGET / ADJUSTMENT_QUOTIENT) - function _ethQty( - uint256 _gasExcess, - uint256 _adjustmentFactor - ) - private - pure - returns (uint256) - { - uint256 input = _gasExcess * LibFixedPointMath.SCALING_FACTOR / _adjustmentFactor; + /// @dev exp(_gasExcess / _gasTarget) / _gasTarget + function basefee(uint256 _gasExcess, uint256 _gasTarget) internal pure returns (uint256) { + uint256 fee = ethQty(_gasExcess, _gasTarget) / _gasTarget; + return fee == 0 ? 1 : fee; + } + + /// @dev exp(_gasExcess / _gasTarget) + function ethQty(uint256 _gasExcess, uint256 _gasTarget) internal pure returns (uint256) { + if (_gasTarget == 0) revert EIP1559_INVALID_PARAMS(); + + uint256 input = LibFixedPointMath.SCALING_FACTOR * _gasExcess / _gasTarget; if (input > LibFixedPointMath.MAX_EXP_INPUT) { input = LibFixedPointMath.MAX_EXP_INPUT; } - return uint256(LibFixedPointMath.exp(int256(input))); + return uint256(LibFixedPointMath.exp(int256(input))) / LibFixedPointMath.SCALING_FACTOR; } } diff --git a/packages/protocol/contracts/L2/TaikoL2.sol b/packages/protocol/contracts/L2/TaikoL2.sol index 1fcfe68709..68b73e4873 100644 --- a/packages/protocol/contracts/L2/TaikoL2.sol +++ b/packages/protocol/contracts/L2/TaikoL2.sol @@ -35,12 +35,12 @@ contract TaikoL2 is EssentialContract { /// @notice The gas excess value used to calculate the base fee. /// @dev Slot 3. - uint64 public gasExcess; + uint64 public parentGasExcess; /// @notice The last synced L1 block height. uint64 public lastSyncedBlock; uint64 private parentTimestamp; - uint64 private __deprecated2; // was __currentBlockTimestamp + uint64 private parentGasTarget; /// @notice The L1's chain ID. uint64 public l1ChainId; @@ -49,8 +49,8 @@ contract TaikoL2 is EssentialContract { /// @notice Emitted when the latest L1 block details are anchored to L2. /// @param parentHash The hash of the parent block. - /// @param gasExcess The gas excess value used to calculate the base fee. - event Anchored(bytes32 parentHash, uint64 gasExcess); + /// @param parentGasExcess The gas excess value used to calculate the base fee. + event Anchored(bytes32 parentHash, uint64 parentGasExcess); error L2_BASEFEE_MISMATCH(); error L2_FORK_ERROR(); @@ -65,12 +65,12 @@ contract TaikoL2 is EssentialContract { /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. /// @param _rollupAddressManager The address of the {AddressManager} contract. /// @param _l1ChainId The ID of the base layer. - /// @param _gasExcess The initial gasExcess. + /// @param _initialGasExcess The initial parentGasExcess. function init( address _owner, address _rollupAddressManager, uint64 _l1ChainId, - uint64 _gasExcess + uint64 _initialGasExcess ) external initializer @@ -95,11 +95,21 @@ contract TaikoL2 is EssentialContract { } l1ChainId = _l1ChainId; - gasExcess = _gasExcess; - parentTimestamp = uint64(block.timestamp); + parentGasExcess = _initialGasExcess; (publicInputHash,) = _calcPublicInputHash(block.number); } + /// @dev Reinitialize some state variables. + /// We may want to init the basefee to a default value using one of the following values. + /// - _initialGasExcess = 274*5_000_000 => basefee =0.01 gwei + /// - _initialGasExcess = 282*5_000_000 => basefee =0.05 gwei + /// - _initialGasExcess = 288*5_000_000 => basefee =0.1 gwei + function init2(uint64 _initialGasExcess) external onlyOwner reinitializer(2) { + parentGasExcess = _initialGasExcess; + parentTimestamp = uint64(block.timestamp); + parentGasTarget = 0; + } + /// @notice Anchors the latest L1 block details to L2 for cross-layer /// message verification. /// @dev This function can be called freely as the golden touch private key is publicly known, @@ -134,7 +144,7 @@ contract TaikoL2 is EssentialContract { uint64 _anchorBlockId, bytes32 _anchorStateRoot, uint32 _parentGasUsed, - uint32 _gasTargetPerL1Block, + uint32 _gasIssuancePerSecond, uint8 _basefeeAdjustmentQuotient ) external @@ -145,7 +155,7 @@ contract TaikoL2 is EssentialContract { _anchorBlockId, _anchorStateRoot, _parentGasUsed, - _gasTargetPerL1Block, + _gasIssuancePerSecond, _basefeeAdjustmentQuotient ); } @@ -177,21 +187,20 @@ contract TaikoL2 is EssentialContract { /// @param _anchorBlockId The synced L1 height in the next Taiko block /// @param _parentGasUsed Gas used in the parent block. /// @return basefee_ The calculated EIP-1559 base fee per gas. - /// @return gasExcess_ The new gasExcess value. + /// @return parentGasExcess_ The new parentGasExcess value. function getBasefee( uint64 _anchorBlockId, uint32 _parentGasUsed ) public view - returns (uint256 basefee_, uint64 gasExcess_) + returns (uint256 basefee_, uint64 parentGasExcess_) { LibL2Config.Config memory config = getConfig(); - (basefee_, gasExcess_) = Lib1559Math.calc1559BaseFee( - config.gasTargetPerL1Block, - config.basefeeAdjustmentQuotient, - gasExcess, + (basefee_, parentGasExcess_) = Lib1559Math.calc1559BaseFee( + uint256(config.gasTargetPerL1Block) * config.basefeeAdjustmentQuotient, + parentGasExcess, uint64(_anchorBlockId - lastSyncedBlock) * config.gasTargetPerL1Block, _parentGasUsed ); @@ -225,29 +234,28 @@ contract TaikoL2 is EssentialContract { /// @notice Calculates the basefee and the new gas excess value based on parent gas used and gas /// excess. - /// @param _gasTargetPerL1Block The gas target for L2 based on each L1 block. + /// @param _gasIssuancePerSecond The gas target for L2 per second. /// @param _blocktime The time between this block and the parent block. /// @param _adjustmentQuotient The gas adjustment quotient. - /// @param _gasExcess The current gas excess value. + /// @param _parentGasExcess The current gas excess value. /// @param _parentGasUsed Total gas used by the parent block. /// @return basefee_ Next block's base fee. - /// @return gasExcess_ The new gas excess value. + /// @return parentGasExcess_ The new gas excess value. function calculateBaseFee( - uint32 _gasTargetPerL1Block, + uint32 _gasIssuancePerSecond, uint64 _blocktime, uint8 _adjustmentQuotient, - uint64 _gasExcess, + uint64 _parentGasExcess, uint32 _parentGasUsed ) public pure - returns (uint256 basefee_, uint64 gasExcess_) + returns (uint256 basefee_, uint64 parentGasExcess_) { return Lib1559Math.calc1559BaseFee( - _gasTargetPerL1Block, - _adjustmentQuotient, - _gasExcess, - _blocktime * _gasTargetPerL1Block / 12, + uint256(_gasIssuancePerSecond) * _adjustmentQuotient, + _parentGasExcess, + _blocktime * _gasIssuancePerSecond, _parentGasUsed ); } @@ -256,7 +264,7 @@ contract TaikoL2 is EssentialContract { uint64 _anchorBlockId, bytes32 _anchorStateRoot, uint32 _parentGasUsed, - uint32 _gasTargetPerL1Block, + uint32 _gasIssuancePerSecond, uint8 _basefeeAdjustmentQuotient ) private @@ -276,16 +284,26 @@ contract TaikoL2 is EssentialContract { _calcPublicInputHash(parentId); if (publicInputHash != currentPublicInputHash) revert L2_PUBLIC_INPUT_HASH_MISMATCH(); + // Check if the gas settings has changed + bool postFork = block.number >= ontakeForkHeight(); + uint64 newGasTarget = uint64(_gasIssuancePerSecond) * _basefeeAdjustmentQuotient; + if (postFork && newGasTarget != parentGasTarget) { + // adjust parentGasExcess to keep the basefee unchanged. Note that due to math + // calculation precision, the basefee may change slightly. + parentGasExcess = + Lib1559Math.adjustExcess(parentGasExcess, parentGasTarget, newGasTarget); + } + // Verify the base fee per gas is correct - (uint256 basefee, uint64 newGasExcess) = block.number < ontakeForkHeight() - ? getBasefee(_anchorBlockId, _parentGasUsed) - : calculateBaseFee( - _gasTargetPerL1Block, + (uint256 basefee, uint64 newGasExcess) = postFork + ? calculateBaseFee( + _gasIssuancePerSecond, uint64(block.timestamp - parentTimestamp), _basefeeAdjustmentQuotient, - gasExcess, + parentGasExcess, _parentGasUsed - ); + ) + : getBasefee(_anchorBlockId, _parentGasUsed); if (!skipFeeCheck() && block.basefee != basefee) revert L2_BASEFEE_MISMATCH(); @@ -300,13 +318,13 @@ contract TaikoL2 is EssentialContract { } // Update state variables - bytes32 parentHash = blockhash(parentId); l2Hashes[parentId] = parentHash; publicInputHash = newPublicInputHash; - gasExcess = newGasExcess; + parentGasExcess = newGasExcess; parentTimestamp = uint64(block.timestamp); + parentGasTarget = newGasTarget; emit Anchored(parentHash, newGasExcess); } diff --git a/packages/protocol/contracts/hekla/HeklaTaikoL1.sol b/packages/protocol/contracts/hekla/HeklaTaikoL1.sol index 1e8e8c0136..32299e5d74 100644 --- a/packages/protocol/contracts/hekla/HeklaTaikoL1.sol +++ b/packages/protocol/contracts/hekla/HeklaTaikoL1.sol @@ -22,7 +22,7 @@ contract HeklaTaikoL1 is TaikoL1 { maxAnchorHeightOffset: 64, basefeeAdjustmentQuotient: 8, basefeeSharingPctg: 75, - gasTargetPerL1Block: 60_000_000, + gasIssuancePerSecond: 5_000_000, ontakeForkHeight: 720_000 // = 7200 * 100 }); } diff --git a/packages/protocol/contracts/mainnet/MainnetTaikoL1.sol b/packages/protocol/contracts/mainnet/MainnetTaikoL1.sol index fb09b4b385..c2ff8c232c 100644 --- a/packages/protocol/contracts/mainnet/MainnetTaikoL1.sol +++ b/packages/protocol/contracts/mainnet/MainnetTaikoL1.sol @@ -32,7 +32,7 @@ contract MainnetTaikoL1 is TaikoL1 { maxAnchorHeightOffset: 64, basefeeAdjustmentQuotient: 8, basefeeSharingPctg: 75, - gasTargetPerL1Block: 60_000_000, + gasIssuancePerSecond: 5_000_000, ontakeForkHeight: 374_400 // = 7200 * 52 }); } diff --git a/packages/protocol/contracts/thirdparty/solmate/LibFixedPointMath.sol b/packages/protocol/contracts/thirdparty/solmate/LibFixedPointMath.sol index 2ad599363c..df7fd59d00 100644 --- a/packages/protocol/contracts/thirdparty/solmate/LibFixedPointMath.sol +++ b/packages/protocol/contracts/thirdparty/solmate/LibFixedPointMath.sol @@ -79,4 +79,82 @@ library LibFixedPointMath { ); } } + + function ln(int256 x) internal pure returns (int256 r) { + unchecked { + require(x > 0, "UNDEFINED"); + + // 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) + int256 k = int256(log2(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 + 3_273_285_459_638_523_848_632_254_066_296; + p = ((p * x) >> 96) + 24_828_157_081_833_163_892_658_089_445_524; + p = ((p * x) >> 96) + 43_456_485_725_739_037_958_740_375_743_393; + p = ((p * x) >> 96) - 11_111_509_109_440_967_052_023_855_526_967; + p = ((p * x) >> 96) - 45_023_709_667_254_063_763_336_534_515_857; + p = ((p * x) >> 96) - 14_706_773_417_378_608_786_704_636_184_526; + p = p * x - (795_164_235_651_350_426_258_249_787_498 << 96); + + // 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 + 5_573_035_233_440_673_466_300_451_813_936; + q = ((q * x) >> 96) + 71_694_874_799_317_883_764_090_561_454_958; + q = ((q * x) >> 96) + 283_447_036_172_924_575_727_196_451_306_956; + q = ((q * x) >> 96) + 401_686_690_394_027_663_651_624_208_769_553; + q = ((q * x) >> 96) + 204_048_457_590_392_012_362_485_061_816_622; + q = ((q * x) >> 96) + 31_853_899_698_501_571_402_653_359_427_138; + q = ((q * x) >> 96) + 909_429_971_244_387_300_277_376_558_375; + 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. + // 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 *= 1_677_202_110_996_718_588_342_820_967_067_443_963_516_166; + // add ln(2) * k * 5e18 * 2**192 + r += + 16_597_577_552_685_614_221_487_285_958_193_947_469_193_820_559_219_878_177_908_093_499_208_371 + * k; + // add ln(2**96 / 10**18) * 5e18 * 2**192 + r += + 600_920_179_829_731_861_736_702_779_321_621_459_595_472_258_049_074_101_567_377_883_020_018_308; + // base conversion: mul 2**18 / 2**192 + r >>= 174; + } + } + + function log2(uint256 x) internal pure returns (uint256 r) { + require(x > 0, "UNDEFINED"); + + 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))) + } + } } diff --git a/packages/protocol/test/L2/Lib1559Math.t.sol b/packages/protocol/test/L2/Lib1559Math.t.sol index a4d275d26b..e05e9ddf10 100644 --- a/packages/protocol/test/L2/Lib1559Math.t.sol +++ b/packages/protocol/test/L2/Lib1559Math.t.sol @@ -6,33 +6,60 @@ import "../TaikoTest.sol"; contract TestLib1559Math is TaikoTest { using LibMath for uint256; - function test_eip1559_math() external pure { - LibL2Config.Config memory config = LibL2Config.get(); - uint256 adjustmentFactor = config.gasTargetPerL1Block * config.basefeeAdjustmentQuotient; - - uint256 baseFee; - uint256 i; - uint256 target = 0.01 gwei; + function test_ethQty() external { + assertEq(Lib1559Math.ethQty(0, 60_000_000 * 8), 1); + assertEq(Lib1559Math.ethQty(60_000_000, 60_000_000 * 8), 1); + assertEq(Lib1559Math.ethQty(60_000_000 * 100, 60_000_000 * 8), 268_337); + assertEq(Lib1559Math.ethQty(60_000_000 * 200, 60_000_000 * 8), 72_004_899_337); + } - for (uint256 k; k < 5; ++k) { - for (; baseFee < target; ++i) { - baseFee = Lib1559Math.basefee(config.gasTargetPerL1Block * i, adjustmentFactor); + function test_basefee() external pure { + uint256 basefee; + for (uint256 i; basefee <= 5000;) { + // uint 0.01 gwei + basefee = Lib1559Math.basefee(i * 5_000_000, 5_000_000 * 8) / 10_000_000; + if (basefee != 0) { + console2.log("basefee (uint 0.01gwei) after", i, "seconds:", basefee); } - console2.log("base fee:", baseFee); - console2.log(" gasExcess:", config.gasTargetPerL1Block * i); - console2.log(" i:", i); - target *= 10; + i += 1; } } - function test_eip1559_math_max() external pure { - LibL2Config.Config memory config = LibL2Config.get(); - uint256 adjustmentFactor = config.gasTargetPerL1Block * config.basefeeAdjustmentQuotient; + function test_change_of_quotient_and_gips() public { + uint64 excess = 150 * 2_000_000; + uint64 target = 4 * 2_000_000; + uint256 unit = 10_000_000; // 0.01 gwei + + // uint 0.01 gwei + uint256 baselineBasefee = Lib1559Math.basefee(excess, target) / unit; + console2.log("baseline basefee: ", baselineBasefee); + + uint256 basefee = Lib1559Math.basefee(excess, target * 2) / unit; + console2.log("basefee will decrease if target increases:", basefee); - uint256 gasExcess = type(uint64).max; - uint256 baseFee = Lib1559Math.basefee(gasExcess, adjustmentFactor); + basefee = Lib1559Math.basefee(excess, target / 2) / unit; + console2.log("basefee will increase if target decreases:", basefee); - console2.log("base fee (gwei):", baseFee / 1 gwei); - console2.log(" gasExcess:", gasExcess); + console2.log("maintain basefee when target increases"); + { + uint64 newTarget = 5 * 2_000_000; + uint64 newExcess = Lib1559Math.adjustExcess(excess, target, newTarget); + basefee = Lib1559Math.basefee(newExcess, newTarget) / unit; + console2.log("old gas excess: ", excess); + console2.log("new gas excess: ", newExcess); + console2.log("basefee: ", basefee); + assertEq(baselineBasefee, basefee); + } + + console2.log("maintain basefee when target decreases"); + { + uint64 newTarget = 3 * 2_000_000; + uint64 newExcess = Lib1559Math.adjustExcess(excess, target, newTarget); + basefee = Lib1559Math.basefee(newExcess, newTarget) / unit; + console2.log("old gas excess: ", excess); + console2.log("new gas excess: ", newExcess); + console2.log("basefee: ", basefee); + assertEq(baselineBasefee, basefee); + } } } diff --git a/packages/protocol/test/L2/TaikoL2EIP1559Configurable.sol b/packages/protocol/test/L2/TaikoL2EIP1559Configurable.sol index e8402ce58f..75b2cc0529 100644 --- a/packages/protocol/test/L2/TaikoL2EIP1559Configurable.sol +++ b/packages/protocol/test/L2/TaikoL2EIP1559Configurable.sol @@ -34,7 +34,7 @@ contract TaikoL2EIP1559Configurable is TaikoL2 { if (_newConfig.basefeeAdjustmentQuotient == 0) revert L2_INVALID_CONFIG(); customConfig = _newConfig; - gasExcess = _newGasExcess; + parentGasExcess = _newGasExcess; emit ConfigAndExcessChanged(_newConfig, _newGasExcess); } diff --git a/packages/protocol/utils/generate_genesis/taikoL2.ts b/packages/protocol/utils/generate_genesis/taikoL2.ts index 9e631d35f6..30d33fedd4 100644 --- a/packages/protocol/utils/generate_genesis/taikoL2.ts +++ b/packages/protocol/utils/generate_genesis/taikoL2.ts @@ -515,7 +515,7 @@ async function generateContractConfigs( // TaikoL2 => CrossChainOwned l1ChainId, // TaikoL2 - gasExcess: param1559.gasExcess, + parentGasExcess: param1559.gasExcess, publicInputHash: `${ethers.utils.solidityKeccak256( ["bytes32[256]"], [