Skip to content

Commit b5ca794

Browse files
committed
feat(feynman): update L1GasPriceOracle (#124)
1 parent b84bd7f commit b5ca794

File tree

3 files changed

+139
-2
lines changed

3 files changed

+139
-2
lines changed

src/L2/predeploys/IL1GasPriceOracle.sol

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ interface IL1GasPriceOracle {
2323
/// @param scalar The current blob fee scalar updated.
2424
event BlobScalarUpdated(uint256 scalar);
2525

26+
/// @notice Emitted when current compression penalty threshold is updated.
27+
/// @param threshold The new compression penalty threshold.
28+
event PenaltyThresholdUpdated(uint256 threshold);
29+
30+
/// @notice Emitted when current compression penalty factor is updated.
31+
/// @param factor The new compression penalty factor.
32+
event PenaltyFactorUpdated(uint256 factor);
33+
2634
/// @notice Emitted when current l1 base fee is updated.
2735
/// @param l1BaseFee The current l1 base fee updated.
2836
event L1BaseFeeUpdated(uint256 l1BaseFee);
@@ -47,6 +55,12 @@ interface IL1GasPriceOracle {
4755
/// @notice Return the current l1 blob fee scalar.
4856
function blobScalar() external view returns (uint256);
4957

58+
/// @notice Return the current compression penalty threshold.
59+
function penaltyThreshold() external view returns (uint256);
60+
61+
/// @notice Return the current compression penalty factor.
62+
function penaltyFactor() external view returns (uint256);
63+
5064
/// @notice Return the latest known l1 base fee.
5165
function l1BaseFee() external view returns (uint256);
5266

src/L2/predeploys/L1GasPriceOracle.sol

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle {
3939
/// @dev Thrown when we enable Curie fork after Curie fork.
4040
error ErrAlreadyInCurieFork();
4141

42+
/// @dev Thrown when the compression penalty threshold exceeds `MAX_PENALTY_THRESHOLD`,
43+
/// or is less than 1 * PRECISION.
44+
error ErrInvalidPenaltyThreshold();
45+
46+
/// @dev Thrown when the compression penalty factor exceeds `MAX_PENALTY_FACTOR`,
47+
/// or is less than 1 * PRECISION.
48+
error ErrInvalidPenaltyFactor();
49+
50+
/// @dev Thrown when we enable Feynman fork after Feynman fork.
51+
error ErrAlreadyInFeynmanFork();
52+
4253
/*************
4354
* Constants *
4455
*************/
@@ -70,6 +81,14 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle {
7081
/// So, the value should not exceed 10^9 * 1e9 normally.
7182
uint256 private constant MAX_BLOB_SCALAR = 10**9 * PRECISION;
7283

84+
/// @dev The maximum possible compression penalty threshold after Feynman.
85+
/// The value should not exceed 10^9 * 1e9 normally.
86+
uint256 private constant MAX_PENALTY_THRESHOLD = 10**9 * PRECISION;
87+
88+
/// @dev The maximum possible compression penalty factor after Feynman.
89+
/// The value should not exceed 10^9 * 1e9 normally.
90+
uint256 private constant MAX_PENALTY_FACTOR = 10**9 * PRECISION;
91+
7392
/*************
7493
* Variables *
7594
*************/
@@ -98,6 +117,15 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle {
98117
/// @notice Indicates whether the network has gone through the Curie upgrade.
99118
bool public isCurie;
100119

120+
/// @inheritdoc IL1GasPriceOracle
121+
uint256 public override penaltyThreshold;
122+
123+
/// @inheritdoc IL1GasPriceOracle
124+
uint256 public override penaltyFactor;
125+
126+
/// @notice Indicates whether the network has gone through the Feynman upgrade.
127+
bool public isFeynman;
128+
101129
/*************
102130
* Modifiers *
103131
*************/
@@ -121,7 +149,9 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle {
121149

122150
/// @inheritdoc IL1GasPriceOracle
123151
function getL1Fee(bytes memory _data) external view override returns (uint256) {
124-
if (isCurie) {
152+
if (isFeynman) {
153+
return _getL1FeeFeynman(_data);
154+
} else if (isCurie) {
125155
return _getL1FeeCurie(_data);
126156
} else {
127157
return _getL1FeeBeforeCurie(_data);
@@ -130,7 +160,7 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle {
130160

131161
/// @inheritdoc IL1GasPriceOracle
132162
function getL1GasUsed(bytes memory _data) public view override returns (uint256) {
133-
if (isCurie) {
163+
if (isFeynman || isCurie) {
134164
// It is near zero since we put all transactions to blob.
135165
return 0;
136166
} else {
@@ -202,6 +232,24 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle {
202232
emit BlobScalarUpdated(_scalar);
203233
}
204234

235+
/// Allows the owner to modify the penaltyThreshold.
236+
/// @param _threshold New threshold
237+
function setPenaltyThreshold(uint256 _threshold) external onlyOwner {
238+
if (_threshold < PRECISION || _threshold > MAX_PENALTY_THRESHOLD) revert ErrInvalidPenaltyThreshold();
239+
240+
penaltyThreshold = _threshold;
241+
emit PenaltyThresholdUpdated(_threshold);
242+
}
243+
244+
/// Allows the owner to modify the penaltyFactor.
245+
/// @param _factor New factor
246+
function setPenaltyFactor(uint256 _factor) external onlyOwner {
247+
if (_factor < PRECISION || _factor > MAX_PENALTY_FACTOR) revert ErrInvalidPenaltyFactor();
248+
249+
penaltyFactor = _factor;
250+
emit PenaltyFactorUpdated(_factor);
251+
}
252+
205253
/// @notice Update whitelist contract.
206254
/// @dev This function can only called by contract owner.
207255
/// @param _newWhitelist The address of new whitelist contract.
@@ -222,6 +270,16 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle {
222270
isCurie = true;
223271
}
224272

273+
/// @notice Enable the Feynman fork (callable by contract owner).
274+
///
275+
/// @dev Since this is a predeploy contract, we will directly set the slot while hard fork
276+
/// to avoid external owner operations.
277+
/// The reason that we keep this function is for easy unit testing.
278+
function enableFeynman() external onlyOwner {
279+
if (isFeynman) revert ErrAlreadyInFeynmanFork();
280+
isFeynman = true;
281+
}
282+
225283
/**********************
226284
* Internal Functions *
227285
**********************/
@@ -264,4 +322,16 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle {
264322
// We have bounded the value of `commitScalar` and `blobScalar`, the whole expression won't overflow.
265323
return (commitScalar * l1BaseFee + blobScalar * _data.length * l1BlobBaseFee) / PRECISION;
266324
}
325+
326+
/// @dev Internal function to compute the L1 portion of the fee based on the size of the rlp encoded input
327+
/// transaction, the current L1 base fee, and the various dynamic parameters, after the Feynman fork.
328+
/// @param _data Signed fully RLP-encoded transaction to get the L1 fee for.
329+
/// @return L1 fee that should be paid for the tx
330+
function _getL1FeeFeynman(bytes memory _data) private view returns (uint256) {
331+
// We have bounded the value of `commitScalar`, `blobScalar`, and `penalty`, the whole expression won't overflow.
332+
return
333+
((commitScalar * l1BaseFee + blobScalar * l1BlobBaseFee) * _data.length * penaltyFactor) /
334+
PRECISION /
335+
PRECISION;
336+
}
267337
}

src/test/L1GasPriceOracle.t.sol

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,23 @@ contract L1GasPriceOracleTest is DSTestPlus {
135135
oracle.enableCurie();
136136
}
137137

138+
function testEnableFeynman() external {
139+
// call by non-owner, should revert
140+
hevm.startPrank(address(1));
141+
hevm.expectRevert("caller is not the owner");
142+
oracle.enableFeynman();
143+
hevm.stopPrank();
144+
145+
// call by owner, should succeed
146+
assertBoolEq(oracle.isFeynman(), false);
147+
oracle.enableFeynman();
148+
assertBoolEq(oracle.isFeynman(), true);
149+
150+
// enable twice, should revert
151+
hevm.expectRevert(L1GasPriceOracle.ErrAlreadyInFeynmanFork.selector);
152+
oracle.enableFeynman();
153+
}
154+
138155
function testSetL1BaseFee(uint256 _baseFee) external {
139156
_baseFee = bound(_baseFee, 0, 1e9 * 20000); // max 20k gwei
140157

@@ -232,4 +249,40 @@ contract L1GasPriceOracleTest is DSTestPlus {
232249
(_commitScalar * _baseFee + _blobScalar * _blobBaseFee * _data.length) / PRECISION
233250
);
234251
}
252+
253+
function testGetL1GasUsedFeynman(bytes memory _data) external {
254+
oracle.enableFeynman();
255+
assertEq(oracle.getL1GasUsed(_data), 0);
256+
}
257+
258+
function testGetL1FeeFeynman(
259+
uint256 _baseFee,
260+
uint256 _blobBaseFee,
261+
uint256 _commitScalar,
262+
uint256 _blobScalar,
263+
uint256 _penaltyThreshold,
264+
uint256 _penaltyFactor,
265+
bytes memory _data
266+
) external {
267+
_baseFee = bound(_baseFee, 0, 1e9 * 20000); // max 20k gwei
268+
_blobBaseFee = bound(_blobBaseFee, 0, 1e9 * 20000); // max 20k gwei
269+
_commitScalar = bound(_commitScalar, 0, MAX_COMMIT_SCALAR);
270+
_blobScalar = bound(_blobScalar, 0, MAX_BLOB_SCALAR);
271+
_penaltyThreshold = bound(_penaltyThreshold, 1e9, 1e9 * 5);
272+
_penaltyFactor = bound(_penaltyFactor, 1e9, 1e9 * 10); // min 1x, max 10x penalty
273+
274+
oracle.enableFeynman();
275+
oracle.setCommitScalar(_commitScalar);
276+
oracle.setBlobScalar(_blobScalar);
277+
oracle.setL1BaseFeeAndBlobBaseFee(_baseFee, _blobBaseFee);
278+
oracle.setPenaltyThreshold(_penaltyThreshold);
279+
oracle.setPenaltyFactor(_penaltyFactor);
280+
281+
assertEq(
282+
oracle.getL1Fee(_data),
283+
((_commitScalar * _baseFee + _blobScalar * _blobBaseFee) * _data.length * _penaltyFactor) /
284+
PRECISION /
285+
PRECISION
286+
);
287+
}
235288
}

0 commit comments

Comments
 (0)