Skip to content

Commit

Permalink
test(protocol): calculate what gasExcess value will push basefee to 1…
Browse files Browse the repository at this point in the history
…gwei then 10gwei (#16550)

Co-authored-by: David <[email protected]>
  • Loading branch information
dantaik and davidtaikocha committed Mar 29, 2024
1 parent 6ad16f5 commit 10872d9
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 84 deletions.
5 changes: 4 additions & 1 deletion packages/protocol/contracts/L2/Lib1559Math.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ library Lib1559Math {
function calc1559BaseFee(
uint32 _gasTargetPerL1Block,
uint8 _adjustmentQuotient,
uint64 _gasExcessMinValue,
uint64 _gasExcess,
uint64 _gasIssuance,
uint32 _parentGasUsed
Expand All @@ -29,7 +30,7 @@ library Lib1559Math {
// value as this has already happened
uint256 excess = uint256(_gasExcess) + _parentGasUsed;
excess = excess > _gasIssuance ? excess - _gasIssuance : 1;
gasExcess_ = uint64(excess.min(type(uint64).max));
gasExcess_ = uint64(excess.min(type(uint64).max).max(_gasExcessMinValue));

// The base fee per gas used by this block is the spot price at the
// bonding curve, regardless the actual amount of gas used by this
Expand All @@ -56,6 +57,8 @@ library Lib1559Math {
revert EIP1559_INVALID_PARAMS();
}

// Note that `/ _adjustmentFactor` can be removed which will make basefee increment faster.
// Alternatively, a larger initial value can be used for `_gasExcess`.
return _ethQty(_gasExcess, _adjustmentFactor) / LibFixedPointMath.SCALING_FACTOR
/ _adjustmentFactor;
}
Expand Down
24 changes: 24 additions & 0 deletions packages/protocol/contracts/L2/LibL2Config.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

/// @title LibL2Config
library LibL2Config {
struct Config {
uint32 gasTargetPerL1Block;
uint8 basefeeAdjustmentQuotient;
uint64 gasExcessMinValue;
}

/// @notice Returns EIP1559 related configurations.
/// @return config_ struct containing configuration parameters.
function get() internal pure returns (Config memory config_) {
// Assuming we sell 3x more blockspace than Ethereum: 15_000_000 * 4
// Note that Brecht's concern is that this value may be too large.
// We need to monitor L2 state growth and lower this value when necessary.
config_.gasTargetPerL1Block = 60_000_000;
config_.basefeeAdjustmentQuotient = 8;

// This value is picked to make the min base fee close to but slightly smaller than 0.1gwei
config_.gasExcessMinValue = 18_435_000_000;
}
}
17 changes: 5 additions & 12 deletions packages/protocol/contracts/L2/TaikoL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "../libs/LibAddress.sol";
import "../signal/ISignalService.sol";
import "../signal/LibSignals.sol";
import "./Lib1559Math.sol";
import "./LibL2Config.sol";

/// @title TaikoL2
/// @notice Taiko L2 is a smart contract that handles cross-layer message
Expand All @@ -21,11 +22,6 @@ contract TaikoL2 is EssentialContract {
using LibAddress for address;
using SafeERC20 for IERC20;

struct Config {
uint32 gasTargetPerL1Block;
uint8 basefeeAdjustmentQuotient;
}

/// @notice Golden touch address is the only address that can do the anchor transaction.
address public constant GOLDEN_TOUCH_ADDRESS = 0x0000777735367b36bC9B61C50022d9D0700dB4Ec;

Expand Down Expand Up @@ -208,12 +204,13 @@ contract TaikoL2 is EssentialContract {
view
returns (uint256 basefee_, uint64 gasExcess_)
{
Config memory config = getConfig();
LibL2Config.Config memory config = getConfig();
uint64 gasIssuance = uint64(_l1BlockId - lastSyncedBlock) * config.gasTargetPerL1Block;

(basefee_, gasExcess_) = Lib1559Math.calc1559BaseFee(
config.gasTargetPerL1Block,
config.basefeeAdjustmentQuotient,
config.gasExcessMinValue,
gasExcess,
gasIssuance,
_parentGasUsed
Expand All @@ -232,12 +229,8 @@ contract TaikoL2 is EssentialContract {

/// @notice Returns EIP1559 related configurations.
/// @return config_ struct containing configuration parameters.
function getConfig() public view virtual returns (Config memory config_) {
// Assuming we sell 3x more blockspace than Ethereum: 15_000_000 * 4
// Note that Brecht's concern is that this value may be too large.
// We need to monitor L2 state growth and lower this value when necessary.
config_.gasTargetPerL1Block = 60_000_000;
config_.basefeeAdjustmentQuotient = 8;
function getConfig() public view virtual returns (LibL2Config.Config memory) {
return LibL2Config.get();
}

/// @notice Tells if we need to validate basefee (for simulation).
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/genesis/test_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ module.exports = {
};
},
param1559: {
gasExcess: 1,
gasExcess: 20000000000,
},
predeployERC20: true,
};
Expand Down
51 changes: 27 additions & 24 deletions packages/protocol/test/L2/Lib1559Math.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,33 @@ contract TestLib1559Math is TaikoTest {
using LibMath for uint256;

function test_eip1559_math() external {
uint256 gasTarget = 15 * 1e6 * 10;
uint256 adjustmentQuotient = 8;
uint256 adjustmentFactor = gasTarget * adjustmentQuotient;
// The expected values are calculated in eip1559_util.py
_assertAmostEq(
999_999_916,
Lib1559Math.basefee({ _gasExcess: 49_954_623_777, _adjustmentFactor: adjustmentFactor })
);

_assertAmostEq(
48_246_703_821_869_050_543_408_253_349_256_099_602_613_005_189_120,
Lib1559Math.basefee({
_gasExcess: LibFixedPointMath.MAX_EXP_INPUT * adjustmentFactor
/ LibFixedPointMath.SCALING_FACTOR,
_adjustmentFactor: adjustmentFactor
})
);
}
LibL2Config.Config memory config = LibL2Config.get();
uint256 adjustmentFactor = config.gasTargetPerL1Block * config.basefeeAdjustmentQuotient;

uint256 baseFee;
uint256 i;

baseFee = Lib1559Math.basefee(config.gasExcessMinValue, adjustmentFactor);
assertEq(baseFee, 99_627_953); // slightly smaller than 0.1gwei
console2.log("gasExcessMinValue:", config.gasExcessMinValue);
console2.log("min base fee:", baseFee);

for (; baseFee < 1 gwei; ++i) {
baseFee = Lib1559Math.basefee(config.gasTargetPerL1Block * i, adjustmentFactor);
console2.log("base fee:", i, baseFee);
}

// base fee will reach 1 gwei if gasExcess > 19620000000
console2.log("base fee will reach 1 gwei if gasExcess >", config.gasTargetPerL1Block * i);
assertEq(i, 327);

for (; baseFee < 10 gwei; ++i) {
baseFee = Lib1559Math.basefee(config.gasTargetPerL1Block * i, adjustmentFactor);
console2.log("base fee:", i, baseFee);
}

// Assert the different between two number is smaller than 1/1000000
function _assertAmostEq(uint256 _a, uint256 _b) private {
uint256 min = _a.min(_b);
uint256 max = _a.max(_b);
assertTrue(max > 0 && ((max - min) * 1_000_000) / max <= 1);
console2.log(_a, " <> ", _b);
// base fee will reach 10 gwei if gasExcess > 20760000000
console2.log("base fee will reach 10 gwei if gasExcess >", config.gasTargetPerL1Block * i);
assertEq(i, 346);
}
}
43 changes: 4 additions & 39 deletions packages/protocol/test/L2/TaikoL2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ contract TestTaikoL2 is TaikoTest {
)
);

L2.setConfigAndExcess(TaikoL2.Config(gasTarget, quotient), gasExcess);
L2.setConfigAndExcess(
LibL2Config.Config(gasTarget, quotient, uint64(gasTarget) * 300), gasExcess
);

ss.authorize(address(L2), true);

Expand All @@ -67,46 +69,9 @@ contract TestTaikoL2 is TaikoTest {
vm.deal(address(L2), 100 ether);
}

function test_L2_AnchorTx_with_constant_block_time() external {
for (uint256 i; i < 100; ++i) {
vm.fee(1);

vm.prank(L2.GOLDEN_TOUCH_ADDRESS());
_anchor(BLOCK_GAS_LIMIT);

vm.roll(block.number + 1);
vm.warp(block.timestamp + 30);
}
}

function test_L2_AnchorTx_with_decreasing_block_time() external {
for (uint256 i; i < 32; ++i) {
vm.fee(1);

vm.prank(L2.GOLDEN_TOUCH_ADDRESS());
_anchor(BLOCK_GAS_LIMIT);

vm.roll(block.number + 1);
vm.warp(block.timestamp + 30 - i);
}
}

function test_L2_AnchorTx_with_increasing_block_time() external {
for (uint256 i; i < 30; ++i) {
vm.fee(1);

vm.prank(L2.GOLDEN_TOUCH_ADDRESS());
_anchor(BLOCK_GAS_LIMIT);

vm.roll(block.number + 1);

vm.warp(block.timestamp + 30 + i);
}
}

// calling anchor in the same block more than once should fail
function test_L2_AnchorTx_revert_in_same_block() external {
vm.fee(1);
vm.fee(40_253_331);

vm.prank(L2.GOLDEN_TOUCH_ADDRESS());
_anchor(BLOCK_GAS_LIMIT);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "./TaikoL2.sol";
import "../../contracts/L2/TaikoL2.sol";

/// @title TaikoL2EIP1559Configurable
/// @notice TaikoL2 with a setter to change EIP-1559 configurations and states.
/// @custom:security-contact [email protected]
contract TaikoL2EIP1559Configurable is TaikoL2 {
/// @notice EIP-1559 configuration.
Config public customConfig;
LibL2Config.Config public customConfig;

uint256[49] private __gap;

/// @notice Emits when the EIP-1559 configuration and gas excess are changed.
/// @param config The new EIP-1559 config.
/// @param gasExcess The new gas excess.
event ConfigAndExcessChanged(Config config, uint64 gasExcess);
event ConfigAndExcessChanged(LibL2Config.Config config, uint64 gasExcess);

error L2_INVALID_CONFIG();

/// @notice Sets EIP1559 configuration and gas excess.
/// @param _newConfig The new EIP1559 config.
/// @param _newGasExcess The new gas excess
function setConfigAndExcess(
Config memory _newConfig,
LibL2Config.Config memory _newConfig,
uint64 _newGasExcess
)
external
Expand All @@ -40,7 +40,7 @@ contract TaikoL2EIP1559Configurable is TaikoL2 {
}

/// @inheritdoc TaikoL2
function getConfig() public view override returns (Config memory) {
function getConfig() public view override returns (LibL2Config.Config memory) {
return customConfig;
}
}
4 changes: 3 additions & 1 deletion packages/protocol/test/L2/TaikoL2NoFeeCheck.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ contract TestTaikoL2NoFeeCheck is TaikoTest {
)
);

L2.setConfigAndExcess(TaikoL2.Config(gasTarget, quotient), gasExcess);
L2.setConfigAndExcess(
LibL2Config.Config(gasTarget, quotient, uint64(gasTarget) * 300), gasExcess
);

ss.authorize(address(L2), true);

Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/test/TaikoTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import "../contracts/L1/hooks/AssignmentHook.sol";
import "../contracts/L1/provers/GuardianProver.sol";

import "../contracts/L2/Lib1559Math.sol";
import "../contracts/L2/TaikoL2EIP1559Configurable.sol";
import "../contracts/L2/TaikoL2.sol";
import "../contracts/L2/DelegateOwner.sol";

Expand All @@ -41,6 +40,7 @@ import "../contracts/team/airdrop/ERC20Airdrop2.sol";
import "../contracts/team/airdrop/ERC721Airdrop.sol";

import "../test/common/erc20/FreeMintERC20.sol";
import "../test/L2/TaikoL2EIP1559Configurable.sol";

import "./DeployCapability.sol";
import "./HelperContracts.sol";
Expand Down

0 comments on commit 10872d9

Please sign in to comment.