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 }