Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol): apply a min value for gas excess #16555

Merged
merged 4 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading