diff --git a/src/L2/predeploys/IL1GasPriceOracle.sol b/src/L2/predeploys/IL1GasPriceOracle.sol index 114903e0..cbb3c3f9 100644 --- a/src/L2/predeploys/IL1GasPriceOracle.sol +++ b/src/L2/predeploys/IL1GasPriceOracle.sol @@ -23,10 +23,6 @@ interface IL1GasPriceOracle { /// @param scalar The current blob fee scalar updated. event BlobScalarUpdated(uint256 scalar); - /// @notice Emitted when current compression penalty threshold is updated. - /// @param threshold The new compression penalty threshold. - event PenaltyThresholdUpdated(uint256 threshold); - /// @notice Emitted when current compression penalty factor is updated. /// @param factor The new compression penalty factor. event PenaltyFactorUpdated(uint256 factor); @@ -56,6 +52,7 @@ interface IL1GasPriceOracle { function blobScalar() external view returns (uint256); /// @notice Return the current compression penalty threshold. + /// @custom:deprecated The penalty threshold parameter is deprecated after the Galileo fork. function penaltyThreshold() external view returns (uint256); /// @notice Return the current compression penalty factor. diff --git a/src/L2/predeploys/L1GasPriceOracle.sol b/src/L2/predeploys/L1GasPriceOracle.sol index 28a03792..b41f59ab 100644 --- a/src/L2/predeploys/L1GasPriceOracle.sol +++ b/src/L2/predeploys/L1GasPriceOracle.sol @@ -39,17 +39,15 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { /// @dev Thrown when we enable Curie fork after Curie fork. error ErrAlreadyInCurieFork(); - /// @dev Thrown when the compression penalty threshold exceeds `MAX_PENALTY_THRESHOLD`, - /// or is less than 1 * PRECISION. - error ErrInvalidPenaltyThreshold(); - - /// @dev Thrown when the compression penalty factor exceeds `MAX_PENALTY_FACTOR`, - /// or is less than 1 * PRECISION. + /// @dev Thrown when the penalty factor is zero. error ErrInvalidPenaltyFactor(); /// @dev Thrown when we enable Feynman fork after Feynman fork. error ErrAlreadyInFeynmanFork(); + /// @dev Thrown when we enable Galileo fork after Galileo fork. + error ErrAlreadyInGalileoFork(); + /************* * Constants * *************/ @@ -81,14 +79,6 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { /// So, the value should not exceed 10^9 * 1e9 normally. uint256 private constant MAX_BLOB_SCALAR = 10**9 * PRECISION; - /// @dev The maximum possible compression penalty threshold after Feynman. - /// The value should not exceed 10^9 * 1e9 normally. - uint256 private constant MAX_PENALTY_THRESHOLD = 10**9 * PRECISION; - - /// @dev The maximum possible compression penalty factor after Feynman. - /// The value should not exceed 10^9 * 1e9 normally. - uint256 private constant MAX_PENALTY_FACTOR = 10**9 * PRECISION; - /************* * Variables * *************/ @@ -117,8 +107,9 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { /// @notice Indicates whether the network has gone through the Curie upgrade. bool public isCurie; - /// @inheritdoc IL1GasPriceOracle - uint256 public override penaltyThreshold; + /// @custom:deprecated The penalty threshold parameter is deprecated after the Galileo fork. + // slither-disable-next-line uninitialized-state + uint256 public __penaltyThreshold; /// @inheritdoc IL1GasPriceOracle uint256 public override penaltyFactor; @@ -126,6 +117,18 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { /// @notice Indicates whether the network has gone through the Feynman upgrade. bool public isFeynman; + /// @notice Indicates whether the network has gone through the Galileo upgrade. + bool public isGalileo; + + /****************** + * View functions * + ******************/ + + /// @inheritdoc IL1GasPriceOracle + function penaltyThreshold() external view override returns (uint256) { + return __penaltyThreshold; + } + /************* * Modifiers * *************/ @@ -149,7 +152,9 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { /// @inheritdoc IL1GasPriceOracle function getL1Fee(bytes memory _data) external view override returns (uint256) { - if (isFeynman) { + if (isGalileo) { + return _getL1FeeGalileo(_data); + } else if (isFeynman) { return _getL1FeeFeynman(_data); } else if (isCurie) { return _getL1FeeCurie(_data); @@ -160,7 +165,7 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { /// @inheritdoc IL1GasPriceOracle function getL1GasUsed(bytes memory _data) public view override returns (uint256) { - if (isFeynman || isCurie) { + if (isGalileo || isFeynman || isCurie) { // It is near zero since we put all transactions to blob. return 0; } else { @@ -232,20 +237,10 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { emit BlobScalarUpdated(_scalar); } - /// Allows the owner to modify the penaltyThreshold. - /// @param _threshold New threshold - function setPenaltyThreshold(uint256 _threshold) external onlyOwner { - if (_threshold < PRECISION || _threshold > MAX_PENALTY_THRESHOLD) revert ErrInvalidPenaltyThreshold(); - - penaltyThreshold = _threshold; - emit PenaltyThresholdUpdated(_threshold); - } - /// Allows the owner to modify the penaltyFactor. /// @param _factor New factor function setPenaltyFactor(uint256 _factor) external onlyOwner { - if (_factor < PRECISION || _factor > MAX_PENALTY_FACTOR) revert ErrInvalidPenaltyFactor(); - + if (_factor == 0) revert ErrInvalidPenaltyFactor(); penaltyFactor = _factor; emit PenaltyFactorUpdated(_factor); } @@ -280,6 +275,16 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { isFeynman = true; } + /// @notice Enable the Galileo fork (callable by contract owner). + /// + /// @dev Since this is a predeploy contract, we will directly set the slot while hard fork + /// to avoid external owner operations. + /// The reason that we keep this function is for easy unit testing. + function enableGalileo() external onlyOwner { + if (isGalileo) revert ErrAlreadyInGalileoFork(); + isGalileo = true; + } + /********************** * Internal Functions * **********************/ @@ -334,4 +339,14 @@ contract L1GasPriceOracle is OwnableBase, IL1GasPriceOracle { PRECISION / PRECISION; } + + /// @dev Internal function to compute the L1 portion of the fee based on the size of the compressed rlp- + /// encoded input transaction, the current L1 base fee, and the various dynamic parameters, after the Galileo fork. + /// @param _data Signed fully RLP-encoded transaction to get the L1 fee for, compressed using zstd. + /// @return L1 fee that should be paid for the tx + function _getL1FeeGalileo(bytes memory _data) private view returns (uint256) { + uint256 baseTerm = (commitScalar * l1BaseFee + blobScalar * l1BlobBaseFee) * _data.length; + uint256 penaltyTerm = (baseTerm * _data.length) / penaltyFactor; + return (baseTerm + penaltyTerm) / PRECISION; + } } diff --git a/src/test/L1GasPriceOracle.t.sol b/src/test/L1GasPriceOracle.t.sol index 7dff1cfb..8c092fa5 100644 --- a/src/test/L1GasPriceOracle.t.sol +++ b/src/test/L1GasPriceOracle.t.sol @@ -260,7 +260,6 @@ contract L1GasPriceOracleTest is DSTestPlus { uint256 _blobBaseFee, uint256 _commitScalar, uint256 _blobScalar, - uint256 _penaltyThreshold, uint256 _penaltyFactor, bytes memory _data ) external { @@ -268,14 +267,16 @@ contract L1GasPriceOracleTest is DSTestPlus { _blobBaseFee = bound(_blobBaseFee, 0, 1e9 * 20000); // max 20k gwei _commitScalar = bound(_commitScalar, 0, MAX_COMMIT_SCALAR); _blobScalar = bound(_blobScalar, 0, MAX_BLOB_SCALAR); - _penaltyThreshold = bound(_penaltyThreshold, 1e9, 1e9 * 5); + // Note: setPenaltyThreshold is deprecated + // _penaltyThreshold = bound(_penaltyThreshold, 1e9, 1e9 * 5); _penaltyFactor = bound(_penaltyFactor, 1e9, 1e9 * 10); // min 1x, max 10x penalty oracle.enableFeynman(); oracle.setCommitScalar(_commitScalar); oracle.setBlobScalar(_blobScalar); oracle.setL1BaseFeeAndBlobBaseFee(_baseFee, _blobBaseFee); - oracle.setPenaltyThreshold(_penaltyThreshold); + // Note: setPenaltyThreshold is deprecated + // oracle.setPenaltyThreshold(_penaltyThreshold); oracle.setPenaltyFactor(_penaltyFactor); assertEq( @@ -285,4 +286,30 @@ contract L1GasPriceOracleTest is DSTestPlus { PRECISION ); } + + function testGetL1FeeGalileo( + uint256 _baseFee, + uint256 _blobBaseFee, + uint256 _commitScalar, + uint256 _blobScalar, + uint256 _penaltyFactor, + bytes memory _data + ) external { + _baseFee = bound(_baseFee, 0, 1e9 * 20000); // max 20k gwei + _blobBaseFee = bound(_blobBaseFee, 0, 1e9 * 20000); // max 20k gwei + _commitScalar = bound(_commitScalar, 0, MAX_COMMIT_SCALAR); + _blobScalar = bound(_blobScalar, 0, MAX_BLOB_SCALAR); + _penaltyFactor = bound(_penaltyFactor, 1, 1e9 * 100); + + oracle.enableGalileo(); + oracle.setCommitScalar(_commitScalar); + oracle.setBlobScalar(_blobScalar); + oracle.setL1BaseFeeAndBlobBaseFee(_baseFee, _blobBaseFee); + oracle.setPenaltyFactor(_penaltyFactor); + + uint256 _baseTerm = (_commitScalar * _baseFee + _blobScalar * _blobBaseFee) * _data.length; + uint256 _penaltyTerm = (_baseTerm * _data.length) / _penaltyFactor; + + assertEq(oracle.getL1Fee(_data), (_baseTerm + _penaltyTerm) / PRECISION); + } }