Skip to content

Commit

Permalink
[Functions] Use @eth-optimism/contracts-bedrock GasPriceOracle (smart…
Browse files Browse the repository at this point in the history
…contractkit#11275)

* (chore): Add @eth-optimism/contracts-bedrock v0.16.2 to vendor

* Use GasPriceOracle in Functions ChainSpecificUtil
  • Loading branch information
justinkaseman authored Nov 14, 2023
1 parent 9471f2e commit 039ffa9
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.19;

import {ArbGasInfo} from "../../../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol";
import {OVM_GasPriceOracle} from "../../../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol";
import {GasPriceOracle} from "../../../../vendor/@eth-optimism/contracts-bedrock/v0.16.2/src/L2/GasPriceOracle.sol";

/// @dev A library that abstracts out opcodes that behave differently across chains.
/// @dev The methods below return values that are pertinent to the given chain.
Expand All @@ -24,10 +24,10 @@ library ChainSpecificUtil {
/// @dev L1_FEE_DATA_PADDING includes 35 bytes for L1 data padding for Optimism
bytes internal constant L1_FEE_DATA_PADDING =
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
/// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_GasPriceOracle precompile on Optimism.
/// @dev OVM_GASPRICEORACLE_ADDR is the address of the GasPriceOracle precompile on Optimism.
/// @dev reference: https://community.optimism.io/docs/developers/build/transaction-fees/#estimating-the-l1-data-fee
address private constant OVM_GASPRICEORACLE_ADDR = address(0x420000000000000000000000000000000000000F);
OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR);
GasPriceOracle private constant OVM_GASPRICEORACLE = GasPriceOracle(OVM_GASPRICEORACLE_ADDR);

uint256 private constant OP_MAINNET_CHAIN_ID = 10;
uint256 private constant OP_GOERLI_CHAIN_ID = 420;
Expand All @@ -44,7 +44,7 @@ library ChainSpecificUtil {
/// @notice for the current transaction.
/// @notice When on a known Arbitrum chain, it uses ArbGas.getCurrentTxL1GasFees to get the fees.
/// @notice On Arbitrum, the provided calldata is not used to calculate the fees.
/// @notice On Optimism, the provided calldata is passed to the OVM_GasPriceOracle predeploy
/// @notice On Optimism, the provided calldata is passed to the GasPriceOracle predeploy
/// @notice and getL1Fee is called to get the fees.
function _getCurrentTxL1GasFees(bytes memory txCallData) internal view returns (uint256 l1FeeWei) {
uint256 chainid = block.chainid;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import { ISemver } from "../universal/ISemver.sol";
import { Predeploys } from "../libraries/Predeploys.sol";
import { L1Block } from "./L1Block.sol";

/// @custom:proxied
/// @custom:predeploy 0x420000000000000000000000000000000000000F
/// @title GasPriceOracle
/// @notice This contract maintains the variables responsible for computing the L1 portion of the
/// total fee charged on L2. Before Bedrock, this contract held variables in state that were
/// read during the state transition function to compute the L1 portion of the transaction
/// fee. After Bedrock, this contract now simply proxies the L1Block contract, which has
/// the values used to compute the L1 portion of the fee in its state.
///
/// The contract exposes an API that is useful for knowing how large the L1 portion of the
/// transaction fee will be. The following events were deprecated with Bedrock:
/// - event OverheadUpdated(uint256 overhead);
/// - event ScalarUpdated(uint256 scalar);
/// - event DecimalsUpdated(uint256 decimals);
contract GasPriceOracle is ISemver {
/// @notice Number of decimals used in the scalar.
uint256 public constant DECIMALS = 6;

/// @notice Semantic version.
/// @custom:semver 1.1.0
string public constant version = "1.1.0";

/// @notice Computes the L1 portion of the fee based on the size of the rlp encoded input
/// transaction, the current L1 base fee, and the various dynamic parameters.
/// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for.
/// @return L1 fee that should be paid for the tx
function getL1Fee(bytes memory _data) external view returns (uint256) {
uint256 l1GasUsed = getL1GasUsed(_data);
uint256 l1Fee = l1GasUsed * l1BaseFee();
uint256 divisor = 10 ** DECIMALS;
uint256 unscaled = l1Fee * scalar();
uint256 scaled = unscaled / divisor;
return scaled;
}

/// @notice Retrieves the current gas price (base fee).
/// @return Current L2 gas price (base fee).
function gasPrice() public view returns (uint256) {
return block.basefee;
}

/// @notice Retrieves the current base fee.
/// @return Current L2 base fee.
function baseFee() public view returns (uint256) {
return block.basefee;
}

/// @notice Retrieves the current fee overhead.
/// @return Current fee overhead.
function overhead() public view returns (uint256) {
return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead();
}

/// @notice Retrieves the current fee scalar.
/// @return Current fee scalar.
function scalar() public view returns (uint256) {
return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar();
}

/// @notice Retrieves the latest known L1 base fee.
/// @return Latest known L1 base fee.
function l1BaseFee() public view returns (uint256) {
return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).basefee();
}

/// @custom:legacy
/// @notice Retrieves the number of decimals used in the scalar.
/// @return Number of decimals used in the scalar.
function decimals() public pure returns (uint256) {
return DECIMALS;
}

/// @notice Computes the amount of L1 gas used for a transaction. Adds the overhead which
/// represents the per-transaction gas overhead of posting the transaction and state
/// roots to L1. Adds 68 bytes of padding to account for the fact that the input does
/// not have a signature.
/// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for.
/// @return Amount of L1 gas used to publish the transaction.
function getL1GasUsed(bytes memory _data) public view returns (uint256) {
uint256 total = 0;
uint256 length = _data.length;
for (uint256 i = 0; i < length; i++) {
if (_data[i] == 0) {
total += 4;
} else {
total += 16;
}
}
uint256 unsigned = total + overhead();
return unsigned + (68 * 16);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import { ISemver } from "../universal/ISemver.sol";

/// @custom:proxied
/// @custom:predeploy 0x4200000000000000000000000000000000000015
/// @title L1Block
/// @notice The L1Block predeploy gives users access to information about the last known L1 block.
/// Values within this contract are updated once per epoch (every L1 block) and can only be
/// set by the "depositor" account, a special system address. Depositor account transactions
/// are created by the protocol whenever we move to a new epoch.
contract L1Block is ISemver {
/// @notice Address of the special depositor account.
address public constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001;

/// @notice The latest L1 block number known by the L2 system.
uint64 public number;

/// @notice The latest L1 timestamp known by the L2 system.
uint64 public timestamp;

/// @notice The latest L1 basefee.
uint256 public basefee;

/// @notice The latest L1 blockhash.
bytes32 public hash;

/// @notice The number of L2 blocks in the same epoch.
uint64 public sequenceNumber;

/// @notice The versioned hash to authenticate the batcher by.
bytes32 public batcherHash;

/// @notice The overhead value applied to the L1 portion of the transaction fee.
uint256 public l1FeeOverhead;

/// @notice The scalar value applied to the L1 portion of the transaction fee.
uint256 public l1FeeScalar;

/// @custom:semver 1.1.0
string public constant version = "1.1.0";

/// @notice Updates the L1 block values.
/// @param _number L1 blocknumber.
/// @param _timestamp L1 timestamp.
/// @param _basefee L1 basefee.
/// @param _hash L1 blockhash.
/// @param _sequenceNumber Number of L2 blocks since epoch start.
/// @param _batcherHash Versioned hash to authenticate batcher by.
/// @param _l1FeeOverhead L1 fee overhead.
/// @param _l1FeeScalar L1 fee scalar.
function setL1BlockValues(
uint64 _number,
uint64 _timestamp,
uint256 _basefee,
bytes32 _hash,
uint64 _sequenceNumber,
bytes32 _batcherHash,
uint256 _l1FeeOverhead,
uint256 _l1FeeScalar
)
external
{
require(msg.sender == DEPOSITOR_ACCOUNT, "L1Block: only the depositor account can set L1 block values");

number = _number;
timestamp = _timestamp;
basefee = _basefee;
hash = _hash;
sequenceNumber = _sequenceNumber;
batcherHash = _batcherHash;
l1FeeOverhead = _l1FeeOverhead;
l1FeeScalar = _l1FeeScalar;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title Predeploys
/// @notice Contains constant addresses for contracts that are pre-deployed to the L2 system.
library Predeploys {
/// @notice Address of the L2ToL1MessagePasser predeploy.
address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016;

/// @notice Address of the L2CrossDomainMessenger predeploy.
address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007;

/// @notice Address of the L2StandardBridge predeploy.
address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010;

/// @notice Address of the L2ERC721Bridge predeploy.
address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014;

//// @notice Address of the SequencerFeeWallet predeploy.
address internal constant SEQUENCER_FEE_WALLET = 0x4200000000000000000000000000000000000011;

/// @notice Address of the OptimismMintableERC20Factory predeploy.
address internal constant OPTIMISM_MINTABLE_ERC20_FACTORY = 0x4200000000000000000000000000000000000012;

/// @notice Address of the OptimismMintableERC721Factory predeploy.
address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY = 0x4200000000000000000000000000000000000017;

/// @notice Address of the L1Block predeploy.
address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015;

/// @notice Address of the GasPriceOracle predeploy. Includes fee information
/// and helpers for computing the L1 portion of the transaction fee.
address internal constant GAS_PRICE_ORACLE = 0x420000000000000000000000000000000000000F;

/// @custom:legacy
/// @notice Address of the L1MessageSender predeploy. Deprecated. Use L2CrossDomainMessenger
/// or access tx.origin (or msg.sender) in a L1 to L2 transaction instead.
address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001;

/// @custom:legacy
/// @notice Address of the DeployerWhitelist predeploy. No longer active.
address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002;

/// @custom:legacy
/// @notice Address of the LegacyERC20ETH predeploy. Deprecated. Balances are migrated to the
/// state trie as of the Bedrock upgrade. Contract has been locked and write functions
/// can no longer be accessed.
address internal constant LEGACY_ERC20_ETH = 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000;

/// @custom:legacy
/// @notice Address of the L1BlockNumber predeploy. Deprecated. Use the L1Block predeploy
/// instead, which exposes more information about the L1 state.
address internal constant L1_BLOCK_NUMBER = 0x4200000000000000000000000000000000000013;

/// @custom:legacy
/// @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated
/// L2ToL1MessagePasser contract instead.
address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000;

/// @notice Address of the ProxyAdmin predeploy.
address internal constant PROXY_ADMIN = 0x4200000000000000000000000000000000000018;

/// @notice Address of the BaseFeeVault predeploy.
address internal constant BASE_FEE_VAULT = 0x4200000000000000000000000000000000000019;

/// @notice Address of the L1FeeVault predeploy.
address internal constant L1_FEE_VAULT = 0x420000000000000000000000000000000000001A;

/// @notice Address of the GovernanceToken predeploy.
address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042;

/// @notice Address of the SchemaRegistry predeploy.
address internal constant SCHEMA_REGISTRY = 0x4200000000000000000000000000000000000020;

/// @notice Address of the EAS predeploy.
address internal constant EAS = 0x4200000000000000000000000000000000000021;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title ISemver
/// @notice ISemver is a simple contract for ensuring that contracts are
/// versioned using semantic versioning.
interface ISemver {
/// @notice Getter for the semantic version of the contract. This is not
/// meant to be used onchain but instead meant to be used by offchain
/// tooling.
/// @return Semver contract version as a string.
function version() external view returns (string memory);
}

0 comments on commit 039ffa9

Please sign in to comment.