Skip to content

Commit

Permalink
feat(protocol): apply a min value for gas excess (#16555)
Browse files Browse the repository at this point in the history
  • Loading branch information
dantaik committed Mar 29, 2024
1 parent 13a443b commit 6e1dfe2
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 70 deletions.
3 changes: 2 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 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
27 changes: 16 additions & 11 deletions packages/protocol/test/L2/Lib1559Math.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,33 @@ contract TestLib1559Math is TaikoTest {
using LibMath for uint256;

function test_eip1559_math() external {
uint256 gasTarget = 60_000_000;
uint256 adjustmentQuotient = 8;
uint256 adjustmentFactor = gasTarget * adjustmentQuotient;
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(gasTarget * i, adjustmentFactor);
console2.log("baseFee:", i, baseFee);
baseFee = Lib1559Math.basefee(config.gasTargetPerL1Block * i, adjustmentFactor);
console2.log("base fee:", i, baseFee);
}

// basefee will reach 1 gwei if gasExcess > 19620000000
console2.log("basefee will reach 1 gwei if gasExcess >", gasTarget * i);
// 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(gasTarget * i, adjustmentFactor);
console2.log("baseFee:", i, baseFee);
baseFee = Lib1559Math.basefee(config.gasTargetPerL1Block * i, adjustmentFactor);
console2.log("base fee:", i, baseFee);
}

// basefee will reach 10 gwei if gasExcess > 20760000000
console2.log("basefee will reach 10 gwei if gasExcess >", gasTarget * i);
// 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 6e1dfe2

Please sign in to comment.