github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/src/L2/GasPriceOracle.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity 0.8.15;
     3  
     4  import { ISemver } from "src/universal/ISemver.sol";
     5  import { Predeploys } from "src/libraries/Predeploys.sol";
     6  import { L1Block } from "src/L2/L1Block.sol";
     7  
     8  /// @custom:proxied
     9  /// @custom:predeploy 0x420000000000000000000000000000000000000F
    10  /// @title GasPriceOracle
    11  /// @notice This contract maintains the variables responsible for computing the L1 portion of the
    12  ///         total fee charged on L2. Before Bedrock, this contract held variables in state that were
    13  ///         read during the state transition function to compute the L1 portion of the transaction
    14  ///         fee. After Bedrock, this contract now simply proxies the L1Block contract, which has
    15  ///         the values used to compute the L1 portion of the fee in its state.
    16  ///
    17  ///         The contract exposes an API that is useful for knowing how large the L1 portion of the
    18  ///         transaction fee will be. The following events were deprecated with Bedrock:
    19  ///         - event OverheadUpdated(uint256 overhead);
    20  ///         - event ScalarUpdated(uint256 scalar);
    21  ///         - event DecimalsUpdated(uint256 decimals);
    22  contract GasPriceOracle is ISemver {
    23      /// @notice Number of decimals used in the scalar.
    24      uint256 public constant DECIMALS = 6;
    25  
    26      /// @notice Semantic version.
    27      /// @custom:semver 1.2.0
    28      string public constant version = "1.2.0";
    29  
    30      /// @notice Indicates whether the network has gone through the Ecotone upgrade.
    31      bool public isEcotone;
    32  
    33      /// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input
    34      ///         transaction, the current L1 base fee, and the various dynamic parameters.
    35      /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.
    36      /// @return L1 fee that should be paid for the tx
    37      function getL1Fee(bytes memory _data) external view returns (uint256) {
    38          if (isEcotone) {
    39              return _getL1FeeEcotone(_data);
    40          }
    41          return _getL1FeeBedrock(_data);
    42      }
    43  
    44      /// @notice Set chain to be Ecotone chain (callable by depositor account)
    45      function setEcotone() external {
    46          require(
    47              msg.sender == L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).DEPOSITOR_ACCOUNT(),
    48              "GasPriceOracle: only the depositor account can set isEcotone flag"
    49          );
    50          require(isEcotone == false, "GasPriceOracle: Ecotone already active");
    51          isEcotone = true;
    52      }
    53  
    54      /// @notice Retrieves the current gas price (base fee).
    55      /// @return Current L2 gas price (base fee).
    56      function gasPrice() public view returns (uint256) {
    57          return block.basefee;
    58      }
    59  
    60      /// @notice Retrieves the current base fee.
    61      /// @return Current L2 base fee.
    62      function baseFee() public view returns (uint256) {
    63          return block.basefee;
    64      }
    65  
    66      /// @custom:legacy
    67      /// @notice Retrieves the current fee overhead.
    68      /// @return Current fee overhead.
    69      function overhead() public view returns (uint256) {
    70          require(!isEcotone, "GasPriceOracle: overhead() is deprecated");
    71          return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();
    72      }
    73  
    74      /// @custom:legacy
    75      /// @notice Retrieves the current fee scalar.
    76      /// @return Current fee scalar.
    77      function scalar() public view returns (uint256) {
    78          require(!isEcotone, "GasPriceOracle: scalar() is deprecated");
    79          return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();
    80      }
    81  
    82      /// @notice Retrieves the latest known L1 base fee.
    83      /// @return Latest known L1 base fee.
    84      function l1BaseFee() public view returns (uint256) {
    85          return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();
    86      }
    87  
    88      /// @notice Retrieves the current blob base fee.
    89      /// @return Current blob base fee.
    90      function blobBaseFee() public view returns (uint256) {
    91          return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFee();
    92      }
    93  
    94      /// @notice Retrieves the current base fee scalar.
    95      /// @return Current base fee scalar.
    96      function baseFeeScalar() public view returns (uint32) {
    97          return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).baseFeeScalar();
    98      }
    99  
   100      /// @notice Retrieves the current blob base fee scalar.
   101      /// @return Current blob base fee scalar.
   102      function blobBaseFeeScalar() public view returns (uint32) {
   103          return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFeeScalar();
   104      }
   105  
   106      /// @custom:legacy
   107      /// @notice Retrieves the number of decimals used in the scalar.
   108      /// @return Number of decimals used in the scalar.
   109      function decimals() public pure returns (uint256) {
   110          return DECIMALS;
   111      }
   112  
   113      /// @notice Computes the amount of L1 gas used for a transaction. Adds 68 bytes
   114      ///         of padding to account for the fact that the input does not have a signature.
   115      /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.
   116      /// @return Amount of L1 gas used to publish the transaction.
   117      function getL1GasUsed(bytes memory _data) public view returns (uint256) {
   118          uint256 l1GasUsed = _getCalldataGas(_data);
   119          if (isEcotone) {
   120              return l1GasUsed;
   121          }
   122          return l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();
   123      }
   124  
   125      /// @notice Computation of the L1 portion of the fee for Bedrock.
   126      /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.
   127      /// @return L1 fee that should be paid for the tx
   128      function _getL1FeeBedrock(bytes memory _data) internal view returns (uint256) {
   129          uint256 l1GasUsed = _getCalldataGas(_data);
   130          uint256 fee = (l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead()) * l1BaseFee()
   131              * L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();
   132          return fee / (10 ** DECIMALS);
   133      }
   134  
   135      /// @notice L1 portion of the fee after Ecotone.
   136      /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.
   137      /// @return L1 fee that should be paid for the tx
   138      function _getL1FeeEcotone(bytes memory _data) internal view returns (uint256) {
   139          uint256 l1GasUsed = _getCalldataGas(_data);
   140          uint256 scaledBaseFee = baseFeeScalar() * 16 * l1BaseFee();
   141          uint256 scaledBlobBaseFee = blobBaseFeeScalar() * blobBaseFee();
   142          uint256 fee = l1GasUsed * (scaledBaseFee + scaledBlobBaseFee);
   143          return fee / (16 * 10 ** DECIMALS);
   144      }
   145  
   146      /// @notice L1 gas estimation calculation.
   147      /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.
   148      /// @return Amount of L1 gas used to publish the transaction.
   149      function _getCalldataGas(bytes memory _data) internal pure returns (uint256) {
   150          uint256 total = 0;
   151          uint256 length = _data.length;
   152          for (uint256 i = 0; i < length; i++) {
   153              if (_data[i] == 0) {
   154                  total += 4;
   155              } else {
   156                  total += 16;
   157              }
   158          }
   159          return total + (68 * 16);
   160      }
   161  }