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

refactor(protocol): further improve EIP1559 on L2 #14724

Merged
merged 3 commits into from
Sep 19, 2023
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
124 changes: 49 additions & 75 deletions packages/protocol/contracts/L2/TaikoL2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,9 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {
bytes32 signalRoot;
}

struct EIP1559Params {
uint64 basefee;
uint32 gasIssuedPerSecond;
uint64 gasExcessMax;
uint64 gasTarget;
uint64 ratio2x1x;
}

struct EIP1559Config {
uint128 xscale;
uint128 yscale;
uint64 xscale;
uint32 gasIssuedPerSecond;
}

Expand All @@ -48,15 +40,11 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {

// A hash to check the integrity of public inputs.
bytes32 public publicInputHash; // slot 3

EIP1559Config public eip1559Config; // slot 4

uint64 public parentTimestamp; // slot 5
uint64 public parentTimestamp; // slot 4
uint64 public latestSyncedL1Height;
uint64 public gasExcess;
uint64 private __reserved1;

uint256[145] private __gap;
uint256[146] private __gap;

// Captures all block variables mentioned in
// https://docs.soliditylang.org/en/v0.8.20/units-and-global-variables.html
Expand All @@ -71,8 +59,6 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {
uint64 chainid
);

event EIP1559ConfigUpdated(EIP1559Config config, uint64 gasExcess);

error L2_BASEFEE_MISMATCH();
error L2_INVALID_1559_PARAMS();
error L2_INVALID_CHAIN_ID();
Expand All @@ -82,20 +68,14 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {

/// @notice Initializes the TaikoL2 contract.
/// @param _addressManager Address of the {AddressManager} contract.
/// @param _param1559 EIP-1559 parameters to set up the gas pricing model.
function init(
address _addressManager,
EIP1559Params calldata _param1559
)
external
initializer
{
function init(address _addressManager) external initializer {
EssentialContract._init(_addressManager);

if (block.number > 1) revert L2_TOO_LATE();

if (block.chainid <= 1 || block.chainid >= type(uint64).max) {
revert L2_INVALID_CHAIN_ID();
}
if (block.number > 1) revert L2_TOO_LATE();

parentTimestamp = uint64(block.timestamp);
(publicInputHash,) = _calcPublicInputHash(block.number);
Expand All @@ -104,8 +84,6 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {
uint256 parentHeight = block.number - 1;
_l2Hashes[parentHeight] = blockhash(parentHeight);
}

updateEIP1559Config(_param1559);
}

/// @notice Anchors the latest L1 block details to L2 for cross-layer
Expand Down Expand Up @@ -154,6 +132,11 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {
});
}

// To make sure when EIP-1559 is enabled, the basefee is non-zero
// (Geth never uses 0 values for basefee)
if (basefee == 0) {
basefee = 1;
}
// On L2, basefee is not burnt, but sent to a treasury instead.
// The circuits will need to verify the basefee recipient is the
// designated address.
Expand All @@ -179,41 +162,6 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {
});
}

/// @notice Updates EIP-1559 configurations.
/// @param _param1559 EIP-1559 parameters to set up the gas pricing model.
function updateEIP1559Config(EIP1559Params calldata _param1559)
public
onlyOwner
{
if (_param1559.gasIssuedPerSecond == 0) {
delete eip1559Config;
delete gasExcess;
} else {
if (
_param1559.basefee == 0 || _param1559.gasExcessMax == 0
|| _param1559.gasTarget == 0 || _param1559.ratio2x1x == 0
) revert L2_INVALID_1559_PARAMS();

(uint128 xscale, uint128 yscale) = Lib1559Math.calculateScales({
xExcessMax: _param1559.gasExcessMax,
price: _param1559.basefee,
target: _param1559.gasTarget,
ratio2x1x: _param1559.ratio2x1x
});

if (xscale == 0 || xscale >= type(uint64).max || yscale == 0) {
revert L2_INVALID_1559_PARAMS();
}
eip1559Config.yscale = yscale;
eip1559Config.xscale = uint64(xscale);
eip1559Config.gasIssuedPerSecond = _param1559.gasIssuedPerSecond;

gasExcess = _param1559.gasExcessMax / 2;
}

emit EIP1559ConfigUpdated(eip1559Config, gasExcess);
}

/// @notice Gets the basefee and gas excess using EIP-1559 configuration for
/// the given parameters.
/// @param timeSinceParent Time elapsed since the parent block's timestamp.
Expand Down Expand Up @@ -270,16 +218,48 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {
}
}

/// @notice Retrieves the current EIP-1559 configuration details.
/// @return The current EIP-1559 configuration details, including the
/// yscale, xscale, and gasIssuedPerSecond parameters.
/// @notice Cauclates the EIP-1559 configurations.
function calcEIP1559Config(
uint64 basefee,
uint32 gasIssuedPerSecond,
uint64 gasExcessMax,
uint64 gasTarget,
uint64 ratio2x1x
)
public
pure
returns (EIP1559Config memory config)
{
if (
gasIssuedPerSecond == 0 || basefee == 0 || gasExcessMax == 0
|| gasTarget == 0 || ratio2x1x == 0
) revert L2_INVALID_1559_PARAMS();

(config.xscale, config.yscale) = Lib1559Math.calculateScales({
xExcessMax: gasExcessMax,
price: basefee,
target: gasTarget,
ratio2x1x: ratio2x1x
});

if (config.xscale == 0 || config.yscale == 0) {
revert L2_INVALID_1559_PARAMS();
}
config.gasIssuedPerSecond = gasIssuedPerSecond;
}

/// @notice Returns the current EIP-1559 configuration details.
/// @return config The current EIP-1559 configuration details.
function getEIP1559Config()
public
view
pure
virtual
returns (EIP1559Config memory)
returns (EIP1559Config memory config)
{
return eip1559Config;
// The following values are caculated in TestTaikoL2_1559.sol.
config.xscale = 1_488_514_844;
config.yscale = 358_298_803_609_133_338_138_868_404_779;
config.gasIssuedPerSecond = 12_500_000;
}

function _calcPublicInputHash(uint256 blockId)
Expand Down Expand Up @@ -337,12 +317,6 @@ contract TaikoL2 is EssentialContract, TaikoL2Signer, ICrossChainSync {
xExcess: _gasExcess,
xPurchase: 0
});

if (_basefee == 0) {
// To make sure when EIP-1559 is enabled, the basefee is non-zero
// (Geth never uses 0 values for basefee)
_basefee = 1;
}
}
}

Expand Down
18 changes: 9 additions & 9 deletions packages/protocol/test/L2/TaikoL2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ contract TestTaikoL2 is TestBase {
uint256 private logIndex;

function setUp() public {
uint16 rand = 2;
TaikoL2.EIP1559Params memory param1559 = TaikoL2.EIP1559Params({
basefee: (uint256(BLOCK_GAS_LIMIT * 10) * rand).toUint64(),
gasIssuedPerSecond: 1_000_000,
gasExcessMax: (uint256(15_000_000) * 256 * rand).toUint64(),
gasTarget: (uint256(6_000_000) * rand).toUint64(),
ratio2x1x: 11_177
});
// uint16 rand = 2;
// TaikoL2.EIP1559Params memory param1559 = TaikoL2.EIP1559Params({
// basefee: (uint256(BLOCK_GAS_LIMIT * 10) * rand).toUint64(),
// gasIssuedPerSecond: 1_000_000,
// gasExcessMax: (uint256(15_000_000) * 256 * rand).toUint64(),
// gasTarget: (uint256(6_000_000) * rand).toUint64(),
// ratio2x1x: 11_177
// });

L2 = new TaikoL2();
address dummyAddressManager = getRandomAddress();
L2.init(dummyAddressManager, param1559);
L2.init(dummyAddressManager);

vm.roll(block.number + 1);
vm.warp(block.timestamp + 30);
Expand Down
35 changes: 20 additions & 15 deletions packages/protocol/test/L2/TaikoL2_1559.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,14 @@ contract TestTaikoL2_1559 is TestBase {
uint64 gasExcessMax = gasIssuedPerSecond * maxSeconds;

uint64 initialBasefee = ethereumBasefeeNow / costFactor;
uint64 ratio2x1x = 11_250; // ~12.5% increase
uint64 gasTarget = gasIssuedPerSecond * ethereumBlockTime;

TaikoL2.EIP1559Params memory param1559 = TaikoL2.EIP1559Params({
basefee: initialBasefee,
gasIssuedPerSecond: gasIssuedPerSecond,
gasExcessMax: gasExcessMax,
gasTarget: gasIssuedPerSecond * ethereumBlockTime,
ratio2x1x: 11_250 // ~12.5% increase
});

console2.log("basefee :", param1559.basefee);
console2.log("gasIssuedPerSecond:", param1559.gasIssuedPerSecond);
console2.log("gasExcessMax :", param1559.gasExcessMax);
console2.log("gasTarget :", param1559.gasTarget);
console2.log("ratio2x1x :", param1559.ratio2x1x);
console2.log("basefee :", initialBasefee);
console2.log("gasIssuedPerSecond:", gasIssuedPerSecond);
console2.log("gasExcessMax :", gasExcessMax);
console2.log("gasTarget :", gasTarget);
console2.log("ratio2x1x :", ratio2x1x);

// basefee : 1120000000
// gasIssuedPerSecond: 12500000
Expand All @@ -51,7 +45,18 @@ contract TestTaikoL2_1559 is TestBase {
// ratio2x1x : 11250

TaikoL2 L2 = new TaikoL2();
address dummyAddressManager = getRandomAddress();
L2.init(dummyAddressManager, param1559);
L2.init(getRandomAddress());

TaikoL2.EIP1559Config memory config = L2.calcEIP1559Config(
initialBasefee,
gasIssuedPerSecond,
gasExcessMax,
gasTarget,
ratio2x1x
);

console2.log("config.xscale : ", config.xscale);
console2.log("config.yscale : ", config.yscale);
console2.log("config.gasIssuedPerSecond: ", config.gasIssuedPerSecond);
}
}