Source Code
Overview
ETH Balance
More Info
ContractCreator
Multichain Info
N/A
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer Ownersh... | 7480224 | 106 days ago | IN | 0 ETH | 0.00000274 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
8587786 | 2 mins ago | 0 ETH | ||||
8587786 | 2 mins ago | 0 ETH | ||||
8587786 | 2 mins ago | 0 ETH | ||||
8587725 | 12 mins ago | 0 ETH | ||||
8587725 | 12 mins ago | 0 ETH | ||||
8587725 | 12 mins ago | 0 ETH | ||||
8587668 | 23 mins ago | 0 ETH | ||||
8587668 | 23 mins ago | 0 ETH | ||||
8587668 | 23 mins ago | 0 ETH | ||||
8587610 | 33 mins ago | 0 ETH | ||||
8587610 | 33 mins ago | 0 ETH | ||||
8587610 | 33 mins ago | 0 ETH | ||||
8587551 | 43 mins ago | 0 ETH | ||||
8587551 | 43 mins ago | 0 ETH | ||||
8587551 | 43 mins ago | 0 ETH | ||||
8587494 | 53 mins ago | 0 ETH | ||||
8587494 | 53 mins ago | 0 ETH | ||||
8587494 | 53 mins ago | 0 ETH | ||||
8587434 | 1 hr ago | 0 ETH | ||||
8587434 | 1 hr ago | 0 ETH | ||||
8587434 | 1 hr ago | 0 ETH | ||||
8587375 | 1 hr ago | 0 ETH | ||||
8587375 | 1 hr ago | 0 ETH | ||||
8587375 | 1 hr ago | 0 ETH | ||||
8587318 | 1 hr ago | 0 ETH |
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xCc189F3f...5DEaA08B4 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
ScrollModule
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; import {IScrollL1GasPriceOracle} from "../../vendor/@scroll-tech/contracts/src/L2/predeploys/IScrollL1GasPriceOracle.sol"; import {ChainModuleBase} from "./ChainModuleBase.sol"; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; contract ScrollModule is ChainModuleBase, ConfirmedOwner { error InvalidL1FeeCoefficient(uint8 coefficient); event L1FeeCoefficientSet(uint8 coefficient); /// @dev SCROLL_L1_FEE_DATA_PADDING includes 140 bytes for L1 data padding for Scroll /// @dev according to testing, this padding allows automation registry to properly estimates L1 data fee with 3-5% buffer /// @dev this MAY NOT work for a different product and this may get out of date if transmit function is changed bytes private constant SCROLL_L1_FEE_DATA_PADDING = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; /// @dev SCROLL_ORACLE_ADDR is the address of the ScrollL1GasPriceOracle precompile on Scroll. /// @dev reference: https://docs.scroll.io/en/developers/transaction-fees-on-scroll/#estimating-the-l1-data-fee address private constant SCROLL_ORACLE_ADDR = 0x5300000000000000000000000000000000000002; IScrollL1GasPriceOracle private constant SCROLL_ORACLE = IScrollL1GasPriceOracle(SCROLL_ORACLE_ADDR); /// @dev L1 fee coefficient can be applied to reduce possibly inflated gas cost uint8 private s_l1FeeCoefficient = 100; uint256 private constant FIXED_GAS_OVERHEAD = 45_000; uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 170; constructor() ConfirmedOwner(msg.sender) {} function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { return (s_l1FeeCoefficient * _getL1Fee(dataSize)) / 100; } function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { return _getL1Fee(dataSize); } /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size * @param dataSize the size of calldata * @return l1Fee the L1 fee */ function _getL1Fee(uint256 dataSize) internal view returns (uint256 l1Fee) { // fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have all non zero-bytes. // Instead of setting bytes to non-zero, we initialize 'new bytes' of length 4*dataSize to cover for zero bytes. // this is the same as OP. bytes memory txCallData = new bytes(4 * dataSize); return SCROLL_ORACLE.getL1Fee(bytes.concat(txCallData, SCROLL_L1_FEE_DATA_PADDING)); } function getGasOverhead() external view override returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) { return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); } /* @notice this function sets a new coefficient for L1 fee estimation. * @dev this function can only be invoked by contract owner * @param coefficient the new coefficient */ function setL1FeeCalculation(uint8 coefficient) external onlyOwner { if (coefficient > 100) { revert InvalidL1FeeCoefficient(coefficient); } s_l1FeeCoefficient = coefficient; emit L1FeeCoefficientSet(coefficient); } /* @notice this function returns the s_l1FeeCoefficient * @return coefficient the current s_l1FeeCoefficient in effect */ function getL1FeeCoefficient() public view returns (uint256 coefficient) { return s_l1FeeCoefficient; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; import {ChainModuleBase} from "./ChainModuleBase.sol"; contract ArbitrumModule is ChainModuleBase { /// @dev ARB_SYS_ADDR is the address of the ArbSys precompile on Arbitrum. /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbSys.sol#L10 address private constant ARB_SYS_ADDR = 0x0000000000000000000000000000000000000064; ArbSys private constant ARB_SYS = ArbSys(ARB_SYS_ADDR); /// @dev ARB_GAS_ADDR is the address of the ArbGasInfo precompile on Arbitrum. /// @dev reference: https://github.com/OffchainLabs/nitro/blob/v2.0.14/contracts/src/precompiles/ArbGasInfo.sol#L10 address private constant ARB_GAS_ADDR = 0x000000000000000000000000000000000000006C; ArbGasInfo private constant ARB_GAS = ArbGasInfo(ARB_GAS_ADDR); uint256 private constant FIXED_GAS_OVERHEAD = 5000; uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; function blockHash(uint256 n) external view override returns (bytes32) { uint256 blockNum = ARB_SYS.arbBlockNumber(); if (n >= blockNum || blockNum - n > 256) { return ""; } return ARB_SYS.arbBlockHash(n); } function blockNumber() external view override returns (uint256) { return ARB_SYS.arbBlockNumber(); } function getCurrentL1Fee(uint256) external view override returns (uint256) { return ARB_GAS.getCurrentTxL1GasFees(); } function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { (, uint256 perL1CalldataByte, , , , ) = ARB_GAS.getPricesInWei(); return perL1CalldataByte * dataSize; } function getGasOverhead() external view override returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) { return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; import {IChainModule} from "../interfaces/IChainModule.sol"; contract ChainModuleBase is IChainModule { uint256 private constant FIXED_GAS_OVERHEAD = 300; uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; function blockNumber() external view virtual returns (uint256) { return block.number; } function blockHash(uint256 n) external view virtual returns (bytes32) { if (n >= block.number || block.number - n > 256) { return ""; } return blockhash(n); } function getCurrentL1Fee(uint256) external view virtual returns (uint256 l1Fee) { return 0; } function getMaxL1Fee(uint256) external view virtual returns (uint256 maxL1Fee) { return 0; } function getGasOverhead() external view virtual returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) { return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.9/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; import {ChainModuleBase} from "./ChainModuleBase.sol"; /** * @notice This contract is deprecated. Please use OptimismModuleV2 which utilizes the most recent offerings from OP * and can estimate L1 fee with much lower cost. */ contract OptimismModule is ChainModuleBase { /// @dev OP_L1_DATA_FEE_PADDING includes 80 bytes for L1 data padding for Optimism and BASE bytes private constant OP_L1_DATA_FEE_PADDING = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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 = 0x420000000000000000000000000000000000000F; OVM_GasPriceOracle private constant OVM_GASPRICEORACLE = OVM_GasPriceOracle(OVM_GASPRICEORACLE_ADDR); uint256 private constant FIXED_GAS_OVERHEAD = 60_000; uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 270; // @dev This will be updated to use the new function introduced by OP team function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { return _getL1Fee(dataSize); } function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { return _getL1Fee(dataSize); } /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size * @dev this function uses the getL1Fee function in OP gas price oracle. it estimates the exact L1 fee but it costs * a lot of gas to call. * @param dataSize the size of calldata * @return l1Fee the L1 fee */ function _getL1Fee(uint256 dataSize) internal view returns (uint256) { // fee is 4 per 0 byte, 16 per non-zero byte. Worst case we can have all non zero-bytes. // Instead of setting bytes to non-zero, we initialize 'new bytes' of length 4*dataSize to cover for zero bytes. bytes memory txCallData = new bytes(4 * dataSize); return OVM_GASPRICEORACLE.getL1Fee(bytes.concat(txCallData, OP_L1_DATA_FEE_PADDING)); } function getGasOverhead() external view override returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) { return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; import {GasPriceOracle as OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts-bedrock/v0.17.3/src/L2/GasPriceOracle.sol"; import {ChainModuleBase} from "./ChainModuleBase.sol"; import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; /** * @notice OptimismModuleV2 provides a cost-efficient way to get L1 fee on OP stack. * After EIP-4844 is implemented in OP stack, the new OP upgrade includes a new function getL1FeeUpperBound to estimate * the upper bound of current transaction's L1 fee. */ contract OptimismModuleV2 is ChainModuleBase, ConfirmedOwner { error InvalidL1FeeCoefficient(uint8 coefficient); event L1FeeCoefficientSet(uint8 coefficient); /// @dev OVM_GASPRICEORACLE_ADDR is the address of the OVM_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); /// @dev L1 fee coefficient is used to account for the impact of data compression on the l1 fee /// getL1FeeUpperBound returns the upper bound of l1 fee so this configurable coefficient will help /// charge a predefined percentage of the upper bound. uint8 private s_l1FeeCoefficient = 100; uint256 private constant FIXED_GAS_OVERHEAD = 28_000; uint256 private constant PER_CALLDATA_BYTE_GAS_OVERHEAD = 0; constructor() ConfirmedOwner(msg.sender) {} function getCurrentL1Fee(uint256 dataSize) external view override returns (uint256) { return (s_l1FeeCoefficient * _getL1Fee(dataSize)) / 100; } function getMaxL1Fee(uint256 dataSize) external view override returns (uint256) { return _getL1Fee(dataSize); } /* @notice this function provides an estimation for L1 fee incurred by calldata of a certain size * @dev this function uses the newly provided getL1FeeUpperBound function in OP gas price oracle. this helps * estimate L1 fee with much lower cost * @param dataSize the size of calldata * @return l1Fee the L1 fee */ function _getL1Fee(uint256 dataSize) internal view returns (uint256) { return OVM_GASPRICEORACLE.getL1FeeUpperBound(dataSize); } function getGasOverhead() external pure override returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead) { return (FIXED_GAS_OVERHEAD, PER_CALLDATA_BYTE_GAS_OVERHEAD); } /* @notice this function sets a new coefficient for L1 fee estimation. * @dev this function can only be invoked by contract owner * @param coefficient the new coefficient */ function setL1FeeCalculation(uint8 coefficient) external onlyOwner { if (coefficient > 100) { revert InvalidL1FeeCoefficient(coefficient); } s_l1FeeCoefficient = coefficient; emit L1FeeCoefficientSet(coefficient); } /* @notice this function returns the s_l1FeeCoefficient * @return coefficient the current s_l1FeeCoefficient in effect */ function getL1FeeCoefficient() public view returns (uint256 coefficient) { return s_l1FeeCoefficient; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.0; interface IChainModule { /* @notice this function provides the block number of current chain. * @dev certain chains have its own function to retrieve block number, e.g. Arbitrum * @return blockNumber the block number of the current chain. */ function blockNumber() external view returns (uint256 blockNumber); /* @notice this function provides the block hash of a block number. * @dev this function can usually look back 256 blocks at most, unless otherwise specified * @param blockNumber the block number * @return blockHash the block hash of the input block number */ function blockHash(uint256 blockNumber) external view returns (bytes32 blockHash); /* @notice this function provides the L1 fee of current transaction. * @dev retrieve the L1 data fee for a L2 transaction. it should return 0 for L1 chains. it should * return 0 for L2 chains if they don't have L1 fee component. * @param dataSize the calldata size of the current transaction * @return l1Fee the L1 fee in wei incurred by calldata of this data size */ function getCurrentL1Fee(uint256 dataSize) external view returns (uint256 l1Fee); /* @notice this function provides the max possible L1 fee of current transaction. * @dev retrieve the max possible L1 data fee for a L2 transaction. it should return 0 for L1 chains. it should * return 0 for L2 chains if they don't have L1 fee component. * @param dataSize the calldata size of the current transaction * @return maxL1Fee the max possible L1 fee in wei incurred by calldata of this data size */ function getMaxL1Fee(uint256 dataSize) external view returns (uint256 maxL1Fee); /* @notice this function provides the overheads of calling this chain module. * @return chainModuleFixedOverhead the fixed overhead incurred by calling this chain module * @return chainModulePerByteOverhead the fixed overhead per byte incurred by calling this chain module with calldata */ function getGasOverhead() external view returns (uint256 chainModuleFixedOverhead, uint256 chainModulePerByteOverhead); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {ConfirmedOwnerWithProposal} from "./ConfirmedOwnerWithProposal.sol"; /// @title The ConfirmedOwner contract /// @notice A contract with helpers for basic contract ownership. contract ConfirmedOwner is ConfirmedOwnerWithProposal { constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IOwnable} from "../interfaces/IOwnable.sol"; /// @title The ConfirmedOwner contract /// @notice A contract with helpers for basic contract ownership. contract ConfirmedOwnerWithProposal is IOwnable { address private s_owner; address private s_pendingOwner; event OwnershipTransferRequested(address indexed from, address indexed to); event OwnershipTransferred(address indexed from, address indexed to); constructor(address newOwner, address pendingOwner) { // solhint-disable-next-line gas-custom-errors require(newOwner != address(0), "Cannot set owner to zero"); s_owner = newOwner; if (pendingOwner != address(0)) { _transferOwnership(pendingOwner); } } /// @notice Allows an owner to begin transferring ownership to a new address. function transferOwnership(address to) public override onlyOwner { _transferOwnership(to); } /// @notice Allows an ownership transfer to be completed by the recipient. function acceptOwnership() external override { // solhint-disable-next-line gas-custom-errors require(msg.sender == s_pendingOwner, "Must be proposed owner"); address oldOwner = s_owner; s_owner = msg.sender; s_pendingOwner = address(0); emit OwnershipTransferred(oldOwner, msg.sender); } /// @notice Get the current owner function owner() public view override returns (address) { return s_owner; } /// @notice validate, transfer ownership, and emit relevant events function _transferOwnership(address to) private { // solhint-disable-next-line gas-custom-errors require(to != msg.sender, "Cannot transfer to self"); s_pendingOwner = to; emit OwnershipTransferRequested(s_owner, to); } /// @notice validate access function _validateOwnership() internal view { // solhint-disable-next-line gas-custom-errors require(msg.sender == s_owner, "Only callable by owner"); } /// @notice Reverts if called by anyone other than the contract owner. modifier onlyOwner() { _validateOwnership(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IOwnable { function owner() external returns (address); function transferOwnership(address recipient) external; function acceptOwnership() external; }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/OffchainLabs/nitro-contracts/blob/main/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.4.21 <0.9.0; /// @title Provides insight into the cost of using the chain. /// @notice These methods have been adjusted to account for Nitro's heavy use of calldata compression. /// Of note to end-users, we no longer make a distinction between non-zero and zero-valued calldata bytes. /// Precompiled contract that exists in every Arbitrum chain at 0x000000000000000000000000000000000000006c. interface ArbGasInfo { /// @notice Get gas prices for a provided aggregator /// @return return gas prices in wei /// ( /// per L2 tx, /// per L1 calldata byte /// per storage allocation, /// per ArbGas base, /// per ArbGas congestion, /// per ArbGas total /// ) function getPricesInWeiWithAggregator(address aggregator) external view returns ( uint256, uint256, uint256, uint256, uint256, uint256 ); /// @notice Get gas prices. Uses the caller's preferred aggregator, or the default if the caller doesn't have a preferred one. /// @return return gas prices in wei /// ( /// per L2 tx, /// per L1 calldata byte /// per storage allocation, /// per ArbGas base, /// per ArbGas congestion, /// per ArbGas total /// ) function getPricesInWei() external view returns ( uint256, uint256, uint256, uint256, uint256, uint256 ); /// @notice Get prices in ArbGas for the supplied aggregator /// @return (per L2 tx, per L1 calldata byte, per storage allocation) function getPricesInArbGasWithAggregator(address aggregator) external view returns ( uint256, uint256, uint256 ); /// @notice Get prices in ArbGas. Assumes the callers preferred validator, or the default if caller doesn't have a preferred one. /// @return (per L2 tx, per L1 calldata byte, per storage allocation) function getPricesInArbGas() external view returns ( uint256, uint256, uint256 ); /// @notice Get the gas accounting parameters. `gasPoolMax` is always zero, as the exponential pricing model has no such notion. /// @return (speedLimitPerSecond, gasPoolMax, maxTxGasLimit) function getGasAccountingParams() external view returns ( uint256, uint256, uint256 ); /// @notice Get the minimum gas price needed for a tx to succeed function getMinimumGasPrice() external view returns (uint256); /// @notice Get ArbOS's estimate of the L1 basefee in wei function getL1BaseFeeEstimate() external view returns (uint256); /// @notice Get how slowly ArbOS updates its estimate of the L1 basefee function getL1BaseFeeEstimateInertia() external view returns (uint64); /// @notice Get the L1 pricer reward rate, in wei per unit /// Available in ArbOS version 11 function getL1RewardRate() external view returns (uint64); /// @notice Get the L1 pricer reward recipient /// Available in ArbOS version 11 function getL1RewardRecipient() external view returns (address); /// @notice Deprecated -- Same as getL1BaseFeeEstimate() function getL1GasPriceEstimate() external view returns (uint256); /// @notice Get L1 gas fees paid by the current transaction function getCurrentTxL1GasFees() external view returns (uint256); /// @notice Get the backlogged amount of gas burnt in excess of the speed limit function getGasBacklog() external view returns (uint64); /// @notice Get how slowly ArbOS updates the L2 basefee in response to backlogged gas function getPricingInertia() external view returns (uint64); /// @notice Get the forgivable amount of backlogged gas ArbOS will ignore when raising the basefee function getGasBacklogTolerance() external view returns (uint64); /// @notice Returns the surplus of funds for L1 batch posting payments (may be negative). function getL1PricingSurplus() external view returns (int256); /// @notice Returns the base charge (in L1 gas) attributed to each data batch in the calldata pricer function getPerBatchGasCharge() external view returns (int64); /// @notice Returns the cost amortization cap in basis points function getAmortizedCostCapBips() external view returns (uint64); /// @notice Returns the available funds from L1 fees function getL1FeesAvailable() external view returns (uint256); /// @notice Returns the equilibration units parameter for L1 price adjustment algorithm /// Available in ArbOS version 20 function getL1PricingEquilibrationUnits() external view returns (uint256); /// @notice Returns the last time the L1 calldata pricer was updated. /// Available in ArbOS version 20 function getLastL1PricingUpdateTime() external view returns (uint64); /// @notice Returns the amount of L1 calldata payments due for rewards (per the L1 reward rate) /// Available in ArbOS version 20 function getL1PricingFundsDueForRewards() external view returns (uint256); /// @notice Returns the amount of L1 calldata posted since the last update. /// Available in ArbOS version 20 function getL1PricingUnitsSinceUpdate() external view returns (uint64); /// @notice Returns the L1 pricing surplus as of the last update (may be negative). /// Available in ArbOS version 20 function getLastL1PricingSurplus() external view returns (int256); }
// Copyright 2021-2022, Offchain Labs, Inc. // For license information, see https://github.com/nitro/blob/master/LICENSE // SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.4.21 <0.9.0; /** * @title System level functionality * @notice For use by contracts to interact with core L2-specific functionality. * Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. */ interface ArbSys { /** * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0) * @return block number as int */ function arbBlockNumber() external view returns (uint256); /** * @notice Get Arbitrum block hash (reverts unless currentBlockNum-256 <= arbBlockNum < currentBlockNum) * @return block hash */ function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32); /** * @notice Gets the rollup's unique chain identifier * @return Chain identifier as int */ function arbChainID() external view returns (uint256); /** * @notice Get internal version number identifying an ArbOS build * @return version number as int */ function arbOSVersion() external view returns (uint256); /** * @notice Returns 0 since Nitro has no concept of storage gas * @return uint 0 */ function getStorageGasAvailable() external view returns (uint256); /** * @notice (deprecated) check if current call is top level (meaning it was triggered by an EoA or a L1 contract) * @dev this call has been deprecated and may be removed in a future release * @return true if current execution frame is not a call by another L2 contract */ function isTopLevelCall() external view returns (bool); /** * @notice map L1 sender contract address to its L2 alias * @param sender sender address * @param unused argument no longer used * @return aliased sender address */ function mapL1SenderContractAddressToL2Alias(address sender, address unused) external pure returns (address); /** * @notice check if the caller (of this caller of this) is an aliased L1 contract address * @return true iff the caller's address is an alias for an L1 contract address */ function wasMyCallersAddressAliased() external view returns (bool); /** * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing * @return address of the caller's caller, without applying L1 contract address aliasing */ function myCallersAddressWithoutAliasing() external view returns (address); /** * @notice Send given amount of Eth to dest from sender. * This is a convenience function, which is equivalent to calling sendTxToL1 with empty data. * @param destination recipient address on L1 * @return unique identifier for this L2-to-L1 transaction. */ function withdrawEth(address destination) external payable returns (uint256); /** * @notice Send a transaction to L1 * @dev it is not possible to execute on the L1 any L2-to-L1 transaction which contains data * to a contract address without any code (as enforced by the Bridge contract). * @param destination recipient address on L1 * @param data (optional) calldata for L1 contract call * @return a unique identifier for this L2-to-L1 transaction. */ function sendTxToL1(address destination, bytes calldata data) external payable returns (uint256); /** * @notice Get send Merkle tree state * @return size number of sends in the history * @return root root hash of the send history * @return partials hashes of partial subtrees in the send history tree */ function sendMerkleTreeState() external view returns ( uint256 size, bytes32 root, bytes32[] memory partials ); /** * @notice creates a send txn from L2 to L1 * @param position = (level << 192) + leaf = (0 << 192) + leaf = leaf */ event L2ToL1Tx( address caller, address indexed destination, uint256 indexed hash, uint256 indexed position, uint256 arbBlockNum, uint256 ethBlockNum, uint256 timestamp, uint256 callvalue, bytes data ); /// @dev DEPRECATED in favour of the new L2ToL1Tx event above after the nitro upgrade event L2ToL1Transaction( address caller, address indexed destination, uint256 indexed uniqueId, uint256 indexed batchNumber, uint256 indexInBatch, uint256 arbBlockNum, uint256 ethBlockNum, uint256 timestamp, uint256 callvalue, bytes data ); /** * @notice logs a merkle branch for proof synthesis * @param reserved an index meant only to align the 4th index with L2ToL1Transaction's 4th event * @param hash the merkle hash * @param position = (level << 192) + leaf */ event SendMerkleUpdate( uint256 indexed reserved, bytes32 indexed hash, uint256 indexed position ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/transmissions11/solmate/blob/97bdb2003b70382996a79a406813f76417b1cf90/src/utils/LibString.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract /// @notice Library for converting numbers into strings and other string operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) /// /// Note: /// For performance and bytecode compactness, most of the string operations are restricted to /// byte strings (7-bit ASCII), except where otherwise specified. /// Usage of byte string operations on charsets with runes spanning two or more bytes /// can lead to undefined behavior. library LibString { /// @dev Returns a string from a small bytes32 string. /// `s` must be null-terminated, or behavior will be undefined. function fromSmallString(bytes32 s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let n := 0 for { } byte(n, s) { n := add(n, 1) } { } // Scan for '\0'. mstore(result, n) let o := add(result, 0x20) mstore(o, s) mstore(add(o, n), 0) mstore(0x40, add(result, 0x40)) } } /// @dev Returns the string as a normalized null-terminated small string. function toSmallString(string memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { result := mload(s) if iszero(lt(result, 33)) { mstore(0x00, 0xec92f9a3) // `TooBigForSmallString()`. revert(0x1c, 0x04) } result := shl(shl(3, sub(32, result)), mload(add(s, result))) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/Vectorized/solady/blob/3e8031b16417154dc2beae71b7b45f415d29566b/src/utils/LibZip.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract /// @notice Library for compressing and decompressing bytes. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibZip.sol) /// @author Calldata compression by clabby (https://github.com/clabby/op-kompressor) /// @author FastLZ by ariya (https://github.com/ariya/FastLZ) /// /// @dev Note: /// The accompanying solady.js library includes implementations of /// FastLZ and calldata operations for convenience. library LibZip { /// @dev Returns the compressed `data`. function flzCompress(bytes memory data) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { function ms8(d_, v_) -> _d { mstore8(d_, v_) _d := add(d_, 1) } function u24(p_) -> _u { let w := mload(p_) _u := or(shl(16, byte(2, w)), or(shl(8, byte(1, w)), byte(0, w))) } function cmp(p_, q_, e_) -> _l { for { e_ := sub(e_, q_) } lt(_l, e_) { _l := add(_l, 1) } { e_ := mul(iszero(byte(0, xor(mload(add(p_, _l)), mload(add(q_, _l))))), e_) } } function literals(runs_, src_, dest_) -> _o { for { _o := dest_ } iszero(lt(runs_, 0x20)) { runs_ := sub(runs_, 0x20) } { mstore(ms8(_o, 31), mload(src_)) _o := add(_o, 0x21) src_ := add(src_, 0x20) } if iszero(runs_) { leave } mstore(ms8(_o, sub(runs_, 1)), mload(src_)) _o := add(1, add(_o, runs_)) } function match(l_, d_, o_) -> _o { for { d_ := sub(d_, 1) } iszero(lt(l_, 263)) { l_ := sub(l_, 262) } { o_ := ms8(ms8(ms8(o_, add(224, shr(8, d_))), 253), and(0xff, d_)) } if iszero(lt(l_, 7)) { _o := ms8(ms8(ms8(o_, add(224, shr(8, d_))), sub(l_, 7)), and(0xff, d_)) leave } _o := ms8(ms8(o_, add(shl(5, l_), shr(8, d_))), and(0xff, d_)) } function setHash(i_, v_) { let p := add(mload(0x40), shl(2, i_)) mstore(p, xor(mload(p), shl(224, xor(shr(224, mload(p)), v_)))) } function getHash(i_) -> _h { _h := shr(224, mload(add(mload(0x40), shl(2, i_)))) } function hash(v_) -> _r { _r := and(shr(19, mul(2654435769, v_)), 0x1fff) } function setNextHash(ip_, ipStart_) -> _ip { setHash(hash(u24(ip_)), sub(ip_, ipStart_)) _ip := add(ip_, 1) } codecopy(mload(0x40), codesize(), 0x8000) // Zeroize the hashmap. let op := add(mload(0x40), 0x8000) let a := add(data, 0x20) let ipStart := a let ipLimit := sub(add(ipStart, mload(data)), 13) for { let ip := add(2, a) } lt(ip, ipLimit) {} { let r := 0 let d := 0 for {} 1 {} { let s := u24(ip) let h := hash(s) r := add(ipStart, getHash(h)) setHash(h, sub(ip, ipStart)) d := sub(ip, r) if iszero(lt(ip, ipLimit)) { break } ip := add(ip, 1) if iszero(gt(d, 0x1fff)) { if eq(s, u24(r)) { break } } } if iszero(lt(ip, ipLimit)) { break } ip := sub(ip, 1) if gt(ip, a) { op := literals(sub(ip, a), a, op) } let l := cmp(add(r, 3), add(ip, 3), add(ipLimit, 9)) op := match(l, d, op) ip := setNextHash(setNextHash(add(ip, l), ipStart), ipStart) a := ip } op := literals(sub(add(ipStart, mload(data)), a), a, op) result := mload(0x40) let t := add(result, 0x8000) let n := sub(op, t) mstore(result, n) // Store the length. // Copy the result to compact the memory, overwriting the hashmap. let o := add(result, 0x20) for { let i } lt(i, n) { i := add(i, 0x20) } { mstore(add(o, i), mload(add(t, i))) } mstore(add(o, n), 0) // Zeroize the slot after the string. mstore(0x40, add(add(o, n), 0x20)) // Allocate the memory. } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/L2/GasPriceOracle.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract import {ISemver} from "../universal/ISemver.sol"; import {Predeploys} from "../libraries/Predeploys.sol"; import {L1Block} from "../L2/L1Block.sol"; import {Constants} from "../libraries/Constants.sol"; import {LibZip} from "../deps/LibZip.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.3.0 string public constant version = "1.3.0"; /// @notice This is the intercept value for the linear regression used to estimate the final size of the /// compressed transaction. int32 private constant COST_INTERCEPT = -42_585_600; /// @notice This is the coefficient value for the linear regression used to estimate the final size of the /// compressed transaction. uint32 private constant COST_FASTLZ_COEF = 836_500; /// @notice This is the minimum bound for the fastlz to brotli size estimation. Any estimations below this /// are set to this value. uint256 private constant MIN_TRANSACTION_SIZE = 100; /// @notice Indicates whether the network has gone through the Ecotone upgrade. bool public isEcotone; /// @notice Indicates whether the network has gone through the Fjord upgrade. bool public isFjord; /// @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) { if (isFjord) { return _getL1FeeFjord(_data); } else if (isEcotone) { return _getL1FeeEcotone(_data); } return _getL1FeeBedrock(_data); } /// @notice returns an upper bound for the L1 fee for a given transaction size. /// It is provided for callers who wish to estimate L1 transaction costs in the /// write path, and is much more gas efficient than `getL1Fee`. /// It assumes the worst case of fastlz upper-bound which covers %99.99 txs. /// @param _unsignedTxSize Unsigned fully RLP-encoded transaction size to get the L1 fee for. /// @return L1 estimated upper-bound fee that should be paid for the tx function getL1FeeUpperBound(uint256 _unsignedTxSize) external view returns (uint256) { require(isFjord, "GasPriceOracle: getL1FeeUpperBound only supports Fjord"); // Add 68 to the size to account for unsigned tx: uint256 txSize = _unsignedTxSize + 68; // txSize / 255 + 16 is the pratical fastlz upper-bound covers %99.99 txs. uint256 flzUpperBound = txSize + txSize / 255 + 16; return _fjordL1Cost(flzUpperBound); } /// @notice Set chain to be Ecotone chain (callable by depositor account) function setEcotone() external { require( msg.sender == Constants.DEPOSITOR_ACCOUNT, "GasPriceOracle: only the depositor account can set isEcotone flag" ); require(isEcotone == false, "GasPriceOracle: Ecotone already active"); isEcotone = true; } /// @notice Set chain to be Fjord chain (callable by depositor account) function setFjord() external { require( msg.sender == Constants.DEPOSITOR_ACCOUNT, "GasPriceOracle: only the depositor account can set isFjord flag" ); require(isEcotone, "GasPriceOracle: Fjord can only be activated after Ecotone"); require(isFjord == false, "GasPriceOracle: Fjord already active"); isFjord = true; } /// @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; } /// @custom:legacy /// @notice Retrieves the current fee overhead. /// @return Current fee overhead. function overhead() public view returns (uint256) { require(!isEcotone, "GasPriceOracle: overhead() is deprecated"); return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); } /// @custom:legacy /// @notice Retrieves the current fee scalar. /// @return Current fee scalar. function scalar() public view returns (uint256) { require(!isEcotone, "GasPriceOracle: scalar() is deprecated"); 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(); } /// @notice Retrieves the current blob base fee. /// @return Current blob base fee. function blobBaseFee() public view returns (uint256) { return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFee(); } /// @notice Retrieves the current base fee scalar. /// @return Current base fee scalar. function baseFeeScalar() public view returns (uint32) { return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).baseFeeScalar(); } /// @notice Retrieves the current blob base fee scalar. /// @return Current blob base fee scalar. function blobBaseFeeScalar() public view returns (uint32) { return L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).blobBaseFeeScalar(); } /// @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 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. /// @custom:deprecated This method does not accurately estimate the gas used for a transaction. /// If you are calculating fees use getL1Fee or getL1FeeUpperBound. function getL1GasUsed(bytes memory _data) public view returns (uint256) { if (isFjord) { // Add 68 to the size to account for unsigned tx // Assume the compressed data is mostly non-zero, and would pay 16 gas per calldata byte // Divide by 1e6 due to the scaling factor of the linear regression return (_fjordLinearRegression(LibZip.flzCompress(_data).length + 68) * 16) / 1e6; } uint256 l1GasUsed = _getCalldataGas(_data); if (isEcotone) { return l1GasUsed; } return l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead(); } /// @notice Computation of the L1 portion of the fee for Bedrock. /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. /// @return L1 fee that should be paid for the tx function _getL1FeeBedrock(bytes memory _data) internal view returns (uint256) { uint256 l1GasUsed = _getCalldataGas(_data); uint256 fee = (l1GasUsed + L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeOverhead()) * l1BaseFee() * L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).l1FeeScalar(); return fee / (10 ** DECIMALS); } /// @notice L1 portion of the fee after Ecotone. /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. /// @return L1 fee that should be paid for the tx function _getL1FeeEcotone(bytes memory _data) internal view returns (uint256) { uint256 l1GasUsed = _getCalldataGas(_data); uint256 scaledBaseFee = baseFeeScalar() * 16 * l1BaseFee(); uint256 scaledBlobBaseFee = blobBaseFeeScalar() * blobBaseFee(); uint256 fee = l1GasUsed * (scaledBaseFee + scaledBlobBaseFee); return fee / (16 * 10 ** DECIMALS); } /// @notice L1 portion of the fee after Fjord. /// @param _data Unsigned fully RLP-encoded transaction to get the L1 fee for. /// @return L1 fee that should be paid for the tx function _getL1FeeFjord(bytes memory _data) internal view returns (uint256) { return _fjordL1Cost(LibZip.flzCompress(_data).length + 68); } /// @notice L1 gas estimation calculation. /// @param _data Unsigned fully RLP-encoded transaction to get the L1 gas for. /// @return Amount of L1 gas used to publish the transaction. function _getCalldataGas(bytes memory _data) internal pure 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; } } return total + (68 * 16); } /// @notice Fjord L1 cost based on the compressed and original tx size. /// @param _fastLzSize estimated compressed tx size. /// @return Fjord L1 fee that should be paid for the tx function _fjordL1Cost(uint256 _fastLzSize) internal view returns (uint256) { // Apply the linear regression to estimate the Brotli 10 size uint256 estimatedSize = _fjordLinearRegression(_fastLzSize); uint256 feeScaled = baseFeeScalar() * 16 * l1BaseFee() + blobBaseFeeScalar() * blobBaseFee(); return (estimatedSize * feeScaled) / (10 ** (DECIMALS * 2)); } /// @notice Takes the fastLz size compression and returns the estimated Brotli /// @param _fastLzSize fastlz compressed tx size. /// @return Number of bytes in the compressed transaction function _fjordLinearRegression(uint256 _fastLzSize) internal pure returns (uint256) { int256 estimatedSize = COST_INTERCEPT + int256(COST_FASTLZ_COEF * _fastLzSize); if (estimatedSize < int256(MIN_TRANSACTION_SIZE) * 1e6) { estimatedSize = int256(MIN_TRANSACTION_SIZE) * 1e6; } return uint256(estimatedSize); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/L2/L1Block.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract import {ISemver} from "../universal/ISemver.sol"; import {Constants} from "../libraries/Constants.sol"; import {GasPayingToken, IGasToken} from "../libraries/GasPayingToken.sol"; import "../libraries/L1BlockErrors.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, IGasToken { /// @notice Event emitted when the gas paying token is set. event GasPayingTokenSet(address indexed token, uint8 indexed decimals, bytes32 name, bytes32 symbol); /// @notice Address of the special depositor account. function DEPOSITOR_ACCOUNT() public pure returns (address addr_) { addr_ = Constants.DEPOSITOR_ACCOUNT; } /// @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 base fee. 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 scalar value applied to the L1 blob base fee portion of the blob-capable L1 cost func. uint32 public blobBaseFeeScalar; /// @notice The scalar value applied to the L1 base fee portion of the blob-capable L1 cost func. uint32 public baseFeeScalar; /// @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. /// @custom:legacy uint256 public l1FeeOverhead; /// @notice The scalar value applied to the L1 portion of the transaction fee. /// @custom:legacy uint256 public l1FeeScalar; /// @notice The latest L1 blob base fee. uint256 public blobBaseFee; /// @custom:semver 1.4.1-beta.1 function version() public pure virtual returns (string memory) { return "1.4.1-beta.1"; } /// @notice Returns the gas paying token, its decimals, name and symbol. /// If nothing is set in state, then it means ether is used. function gasPayingToken() public view returns (address addr_, uint8 decimals_) { (addr_, decimals_) = GasPayingToken.getToken(); } /// @notice Returns the gas paying token name. /// If nothing is set in state, then it means ether is used. function gasPayingTokenName() public view returns (string memory name_) { name_ = GasPayingToken.getName(); } /// @notice Returns the gas paying token symbol. /// If nothing is set in state, then it means ether is used. function gasPayingTokenSymbol() public view returns (string memory symbol_) { symbol_ = GasPayingToken.getSymbol(); } /// @notice Getter for custom gas token paying networks. Returns true if the /// network uses a custom gas token. function isCustomGasToken() public view returns (bool) { (address token, ) = gasPayingToken(); return token != Constants.ETHER; } /// @custom:legacy /// @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; } /// @notice Updates the L1 block values for an Ecotone upgraded chain. /// Params are packed and passed in as raw msg.data instead of ABI to reduce calldata size. /// Params are expected to be in the following order: /// 1. _baseFeeScalar L1 base fee scalar /// 2. _blobBaseFeeScalar L1 blob base fee scalar /// 3. _sequenceNumber Number of L2 blocks since epoch start. /// 4. _timestamp L1 timestamp. /// 5. _number L1 blocknumber. /// 6. _basefee L1 base fee. /// 7. _blobBaseFee L1 blob base fee. /// 8. _hash L1 blockhash. /// 9. _batcherHash Versioned hash to authenticate batcher by. function setL1BlockValuesEcotone() external { address depositor = DEPOSITOR_ACCOUNT(); assembly { // Revert if the caller is not the depositor account. if xor(caller(), depositor) { mstore(0x00, 0x3cc50b45) // 0x3cc50b45 is the 4-byte selector of "NotDepositor()" revert(0x1C, 0x04) // returns the stored 4-byte selector from above } // sequencenum (uint64), blobBaseFeeScalar (uint32), baseFeeScalar (uint32) sstore(sequenceNumber.slot, shr(128, calldataload(4))) // number (uint64) and timestamp (uint64) sstore(number.slot, shr(128, calldataload(20))) sstore(basefee.slot, calldataload(36)) // uint256 sstore(blobBaseFee.slot, calldataload(68)) // uint256 sstore(hash.slot, calldataload(100)) // bytes32 sstore(batcherHash.slot, calldataload(132)) // bytes32 } } /// @notice Sets the gas paying token for the L2 system. Can only be called by the special /// depositor account. This function is not called on every L2 block but instead /// only called by specially crafted L1 deposit transactions. function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external { if (msg.sender != DEPOSITOR_ACCOUNT()) revert NotDepositor(); GasPayingToken.set({_token: _token, _decimals: _decimals, _name: _name, _symbol: _symbol}); emit GasPayingTokenSet({token: _token, decimals: _decimals, name: _name, symbol: _symbol}); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/Constants.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract /// @title Constants /// @notice Constants is a library for storing constants. Simple! Don't put everything in here, just /// the stuff used in multiple contracts. Constants that only apply to a single contract /// should be defined in that contract instead. library Constants { /// @notice Special address to be used as the tx origin for gas estimation calls in the /// OptimismPortal and CrossDomainMessenger calls. You only need to use this address if /// the minimum gas limit specified by the user is not actually enough to execute the /// given message and you're attempting to estimate the actual necessary gas limit. We /// use address(1) because it's the ecrecover precompile and therefore guaranteed to /// never have any code on any EVM chain. address internal constant ESTIMATION_ADDRESS = address(1); /// @notice Value used for the L2 sender storage slot in both the OptimismPortal and the /// CrossDomainMessenger contracts before an actual sender is set. This value is /// non-zero to reduce the gas cost of message passing transactions. address internal constant DEFAULT_L2_SENDER = 0x000000000000000000000000000000000000dEaD; /// @notice The storage slot that holds the address of a proxy implementation. /// @dev `bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)` bytes32 internal constant PROXY_IMPLEMENTATION_ADDRESS = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /// @notice The storage slot that holds the address of the owner. /// @dev `bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)` bytes32 internal constant PROXY_OWNER_ADDRESS = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /// @notice The address that represents ether when dealing with ERC20 token addresses. address internal constant ETHER = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /// @notice The address that represents the system caller responsible for L1 attributes /// transactions. address internal constant DEPOSITOR_ACCOUNT = 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/GasPayingToken.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract import {Storage} from "./Storage.sol"; import {Constants} from "./Constants.sol"; import {LibString} from "../deps/LibString.sol"; /// @title IGasToken /// @notice Implemented by contracts that are aware of the custom gas token used /// by the L2 network. interface IGasToken { /// @notice Getter for the ERC20 token address that is used to pay for gas and its decimals. function gasPayingToken() external view returns (address, uint8); /// @notice Returns the gas token name. function gasPayingTokenName() external view returns (string memory); /// @notice Returns the gas token symbol. function gasPayingTokenSymbol() external view returns (string memory); /// @notice Returns true if the network uses a custom gas token. function isCustomGasToken() external view returns (bool); } /// @title GasPayingToken /// @notice Handles reading and writing the custom gas token to storage. /// To be used in any place where gas token information is read or /// written to state. If multiple contracts use this library, the /// values in storage should be kept in sync between them. library GasPayingToken { /// @notice The storage slot that contains the address and decimals of the gas paying token bytes32 internal constant GAS_PAYING_TOKEN_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtoken")) - 1); /// @notice The storage slot that contains the ERC20 `name()` of the gas paying token bytes32 internal constant GAS_PAYING_TOKEN_NAME_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtokenname")) - 1); /// @notice the storage slot that contains the ERC20 `symbol()` of the gas paying token bytes32 internal constant GAS_PAYING_TOKEN_SYMBOL_SLOT = bytes32(uint256(keccak256("opstack.gaspayingtokensymbol")) - 1); /// @notice Reads the gas paying token and its decimals from the magic /// storage slot. If nothing is set in storage, then the ether /// address is returned instead. function getToken() internal view returns (address addr_, uint8 decimals_) { bytes32 slot = Storage.getBytes32(GAS_PAYING_TOKEN_SLOT); addr_ = address(uint160(uint256(slot) & uint256(type(uint160).max))); if (addr_ == address(0)) { addr_ = Constants.ETHER; decimals_ = 18; } else { decimals_ = uint8(uint256(slot) >> 160); } } /// @notice Reads the gas paying token's name from the magic storage slot. /// If nothing is set in storage, then the ether name, 'Ether', is returned instead. function getName() internal view returns (string memory name_) { (address addr, ) = getToken(); if (addr == Constants.ETHER) { name_ = "Ether"; } else { name_ = LibString.fromSmallString(Storage.getBytes32(GAS_PAYING_TOKEN_NAME_SLOT)); } } /// @notice Reads the gas paying token's symbol from the magic storage slot. /// If nothing is set in storage, then the ether symbol, 'ETH', is returned instead. function getSymbol() internal view returns (string memory symbol_) { (address addr, ) = getToken(); if (addr == Constants.ETHER) { symbol_ = "ETH"; } else { symbol_ = LibString.fromSmallString(Storage.getBytes32(GAS_PAYING_TOKEN_SYMBOL_SLOT)); } } /// @notice Writes the gas paying token, its decimals, name and symbol to the magic storage slot. function set(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) internal { Storage.setBytes32(GAS_PAYING_TOKEN_SLOT, bytes32((uint256(_decimals) << 160) | uint256(uint160(_token)))); Storage.setBytes32(GAS_PAYING_TOKEN_NAME_SLOT, _name); Storage.setBytes32(GAS_PAYING_TOKEN_SYMBOL_SLOT, _symbol); } /// @notice Maps a string to a normalized null-terminated small string. function sanitize(string memory _str) internal pure returns (bytes32) { require(bytes(_str).length <= 32, "GasPayingToken: string cannot be greater than 32 bytes"); return LibString.toSmallString(_str); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/L1BlockErrors.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract /// @notice Error returns when a non-depositor account tries to set L1 block values. error NotDepositor(); /// @notice Error when a chain ID is not in the interop dependency set. error NotDependency(); /// @notice Error when the interop dependency set size is too large. error DependencySetSizeTooLarge(); /// @notice Error when a chain ID already in the interop dependency set is attempted to be added. error AlreadyDependency(); /// @notice Error when the chain's chain ID is attempted to be removed from the interop dependency set. error CantRemovedDependency();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/Predeploys.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract /// @title Predeploys /// @notice Contains constant addresses for protocol contracts that are pre-deployed to the L2 system. // This excludes the preinstalls (non-protocol contracts). library Predeploys { /// @notice Number of predeploy-namespace addresses reserved for protocol usage. uint256 internal constant PREDEPLOY_COUNT = 2048; /// @custom:legacy /// @notice Address of the LegacyMessagePasser predeploy. Deprecate. Use the updated /// L2ToL1MessagePasser contract instead. address internal constant LEGACY_MESSAGE_PASSER = 0x4200000000000000000000000000000000000000; /// @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. /// Not embedded into new OP-Stack chains. address internal constant L1_MESSAGE_SENDER = 0x4200000000000000000000000000000000000001; /// @custom:legacy /// @notice Address of the DeployerWhitelist predeploy. No longer active. address internal constant DEPLOYER_WHITELIST = 0x4200000000000000000000000000000000000002; /// @notice Address of the canonical WETH contract. address internal constant WETH = 0x4200000000000000000000000000000000000006; /// @notice Address of the L2CrossDomainMessenger predeploy. address internal constant L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000007; /// @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; /// @notice Address of the L2StandardBridge predeploy. address internal constant L2_STANDARD_BRIDGE = 0x4200000000000000000000000000000000000010; //// @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; /// @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; /// @notice Address of the L2ERC721Bridge predeploy. address internal constant L2_ERC721_BRIDGE = 0x4200000000000000000000000000000000000014; /// @notice Address of the L1Block predeploy. address internal constant L1_BLOCK_ATTRIBUTES = 0x4200000000000000000000000000000000000015; /// @notice Address of the L2ToL1MessagePasser predeploy. address internal constant L2_TO_L1_MESSAGE_PASSER = 0x4200000000000000000000000000000000000016; /// @notice Address of the OptimismMintableERC721Factory predeploy. address internal constant OPTIMISM_MINTABLE_ERC721_FACTORY = 0x4200000000000000000000000000000000000017; /// @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 SchemaRegistry predeploy. address internal constant SCHEMA_REGISTRY = 0x4200000000000000000000000000000000000020; /// @notice Address of the EAS predeploy. address internal constant EAS = 0x4200000000000000000000000000000000000021; /// @notice Address of the GovernanceToken predeploy. address internal constant GOVERNANCE_TOKEN = 0x4200000000000000000000000000000000000042; /// @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; /// @notice Address of the CrossL2Inbox predeploy. address internal constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000022; /// @notice Address of the L2ToL2CrossDomainMessenger predeploy. address internal constant L2_TO_L2_CROSS_DOMAIN_MESSENGER = 0x4200000000000000000000000000000000000023; /// @notice Returns the name of the predeploy at the given address. function getName(address _addr) internal pure returns (string memory out_) { require(isPredeployNamespace(_addr), "Predeploys: address must be a predeploy"); if (_addr == LEGACY_MESSAGE_PASSER) return "LegacyMessagePasser"; if (_addr == L1_MESSAGE_SENDER) return "L1MessageSender"; if (_addr == DEPLOYER_WHITELIST) return "DeployerWhitelist"; if (_addr == WETH) return "WETH"; if (_addr == L2_CROSS_DOMAIN_MESSENGER) return "L2CrossDomainMessenger"; if (_addr == GAS_PRICE_ORACLE) return "GasPriceOracle"; if (_addr == L2_STANDARD_BRIDGE) return "L2StandardBridge"; if (_addr == SEQUENCER_FEE_WALLET) return "SequencerFeeVault"; if (_addr == OPTIMISM_MINTABLE_ERC20_FACTORY) return "OptimismMintableERC20Factory"; if (_addr == L1_BLOCK_NUMBER) return "L1BlockNumber"; if (_addr == L2_ERC721_BRIDGE) return "L2ERC721Bridge"; if (_addr == L1_BLOCK_ATTRIBUTES) return "L1Block"; if (_addr == L2_TO_L1_MESSAGE_PASSER) return "L2ToL1MessagePasser"; if (_addr == OPTIMISM_MINTABLE_ERC721_FACTORY) return "OptimismMintableERC721Factory"; if (_addr == PROXY_ADMIN) return "ProxyAdmin"; if (_addr == BASE_FEE_VAULT) return "BaseFeeVault"; if (_addr == L1_FEE_VAULT) return "L1FeeVault"; if (_addr == SCHEMA_REGISTRY) return "SchemaRegistry"; if (_addr == EAS) return "EAS"; if (_addr == GOVERNANCE_TOKEN) return "GovernanceToken"; if (_addr == LEGACY_ERC20_ETH) return "LegacyERC20ETH"; if (_addr == CROSS_L2_INBOX) return "CrossL2Inbox"; if (_addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER) return "L2ToL2CrossDomainMessenger"; revert("Predeploys: unnamed predeploy"); } /// @notice Returns true if the predeploy is not proxied. function notProxied(address _addr) internal pure returns (bool) { return _addr == GOVERNANCE_TOKEN || _addr == WETH; } /// @notice Returns true if the address is a defined predeploy that is embedded into new OP-Stack chains. function isSupportedPredeploy(address _addr, bool _useInterop) internal pure returns (bool) { return _addr == LEGACY_MESSAGE_PASSER || _addr == DEPLOYER_WHITELIST || _addr == WETH || _addr == L2_CROSS_DOMAIN_MESSENGER || _addr == GAS_PRICE_ORACLE || _addr == L2_STANDARD_BRIDGE || _addr == SEQUENCER_FEE_WALLET || _addr == OPTIMISM_MINTABLE_ERC20_FACTORY || _addr == L1_BLOCK_NUMBER || _addr == L2_ERC721_BRIDGE || _addr == L1_BLOCK_ATTRIBUTES || _addr == L2_TO_L1_MESSAGE_PASSER || _addr == OPTIMISM_MINTABLE_ERC721_FACTORY || _addr == PROXY_ADMIN || _addr == BASE_FEE_VAULT || _addr == L1_FEE_VAULT || _addr == SCHEMA_REGISTRY || _addr == EAS || _addr == GOVERNANCE_TOKEN || (_useInterop && _addr == CROSS_L2_INBOX) || (_useInterop && _addr == L2_TO_L2_CROSS_DOMAIN_MESSENGER); } function isPredeployNamespace(address _addr) internal pure returns (bool) { return uint160(_addr) >> 11 == uint160(0x4200000000000000000000000000000000000000) >> 11; } /// @notice Function to compute the expected address of the predeploy implementation /// in the genesis state. function predeployToCodeNamespace(address _addr) internal pure returns (address) { require(isPredeployNamespace(_addr), "Predeploys: can only derive code-namespace address for predeploy addresses"); return address( uint160((uint256(uint160(_addr)) & 0xffff) | uint256(uint160(0xc0D3C0d3C0d3C0D3c0d3C0d3c0D3C0d3c0d30000))) ); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/libraries/Storage.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract /// @title Storage /// @notice Storage handles reading and writing to arbitary storage locations library Storage { /// @notice Returns an address stored in an arbitrary storage slot. /// These storage slots decouple the storage layout from /// solc's automation. /// @param _slot The storage slot to retrieve the address from. function getAddress(bytes32 _slot) internal view returns (address addr_) { assembly { addr_ := sload(_slot) } } /// @notice Stores an address in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the address in. /// @param _address The protocol version to store /// @dev WARNING! This function must be used cautiously, as it allows for overwriting addresses /// in arbitrary storage slots. function setAddress(bytes32 _slot, address _address) internal { assembly { sstore(_slot, _address) } } /// @notice Returns a uint256 stored in an arbitrary storage slot. /// These storage slots decouple the storage layout from /// solc's automation. /// @param _slot The storage slot to retrieve the address from. function getUint(bytes32 _slot) internal view returns (uint256 value_) { assembly { value_ := sload(_slot) } } /// @notice Stores a value in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the address in. /// @param _value The protocol version to store /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values /// in arbitrary storage slots. function setUint(bytes32 _slot, uint256 _value) internal { assembly { sstore(_slot, _value) } } /// @notice Returns a bytes32 stored in an arbitrary storage slot. /// These storage slots decouple the storage layout from /// solc's automation. /// @param _slot The storage slot to retrieve the address from. function getBytes32(bytes32 _slot) internal view returns (bytes32 value_) { assembly { value_ := sload(_slot) } } /// @notice Stores a bytes32 value in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the address in. /// @param _value The bytes32 value to store. /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values /// in arbitrary storage slots. function setBytes32(bytes32 _slot, bytes32 _value) internal { assembly { sstore(_slot, _value) } } /// @notice Stores a bool value in an arbitrary storage slot, `_slot`. /// @param _slot The storage slot to store the bool in. /// @param _value The bool value to store /// @dev WARNING! This function must be used cautiously, as it allows for overwriting values /// in arbitrary storage slots. function setBool(bytes32 _slot, bool _value) internal { assembly { sstore(_slot, _value) } } /// @notice Returns a bool stored in an arbitrary storage slot. /// @param _slot The storage slot to retrieve the bool from. function getBool(bytes32 _slot) internal view returns (bool value_) { assembly { value_ := sload(_slot) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @notice: IMPORTANT NOTICE for anyone who wants to use this contract /// @notice Source: https://github.com/ethereum-optimism/optimism/blob/71b93116738ee98c9f8713b1a5dfe626ce06c1b2/packages/contracts-bedrock/src/universal/ISemver.sol /// @notice The original code was trimmed down to include only the necessary interface elements required to interact with GasPriceOracle /// @notice We need this file so that Solidity compiler will not complain because some functions don't exist /// @notice In reality, we don't embed this code into our own contracts, instead we make cross-contract calls on predeployed GasPriceOracle contract /// @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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; /* External Imports */ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; /** * @title OVM_GasPriceOracle * @dev This contract exposes the current l2 gas price, a measure of how congested the network * currently is. This measure is used by the Sequencer to determine what fee to charge for * transactions. When the system is more congested, the l2 gas price will increase and fees * will also increase as a result. * * All public variables are set while generating the initial L2 state. The * constructor doesn't run in practice as the L2 state generation script uses * the deployed bytecode instead of running the initcode. */ contract OVM_GasPriceOracle is Ownable { /************* * Variables * *************/ // Current L2 gas price uint256 public gasPrice; // Current L1 base fee uint256 public l1BaseFee; // Amortized cost of batch submission per transaction uint256 public overhead; // Value to scale the fee up by uint256 public scalar; // Number of decimals of the scalar uint256 public decimals; /*************** * Constructor * ***************/ /** * @param _owner Address that will initially own this contract. */ constructor(address _owner) Ownable() { transferOwnership(_owner); } /********** * Events * **********/ event GasPriceUpdated(uint256); event L1BaseFeeUpdated(uint256); event OverheadUpdated(uint256); event ScalarUpdated(uint256); event DecimalsUpdated(uint256); /******************** * Public Functions * ********************/ /** * Allows the owner to modify the l2 gas price. * @param _gasPrice New l2 gas price. */ // slither-disable-next-line external-function function setGasPrice(uint256 _gasPrice) public onlyOwner { gasPrice = _gasPrice; emit GasPriceUpdated(_gasPrice); } /** * Allows the owner to modify the l1 base fee. * @param _baseFee New l1 base fee */ // slither-disable-next-line external-function function setL1BaseFee(uint256 _baseFee) public onlyOwner { l1BaseFee = _baseFee; emit L1BaseFeeUpdated(_baseFee); } /** * Allows the owner to modify the overhead. * @param _overhead New overhead */ // slither-disable-next-line external-function function setOverhead(uint256 _overhead) public onlyOwner { overhead = _overhead; emit OverheadUpdated(_overhead); } /** * Allows the owner to modify the scalar. * @param _scalar New scalar */ // slither-disable-next-line external-function function setScalar(uint256 _scalar) public onlyOwner { scalar = _scalar; emit ScalarUpdated(_scalar); } /** * Allows the owner to modify the decimals. * @param _decimals New decimals */ // slither-disable-next-line external-function function setDecimals(uint256 _decimals) public onlyOwner { decimals = _decimals; emit DecimalsUpdated(_decimals); } /** * Computes the L1 portion of the fee * based on the size of the RLP encoded tx * and the current l1BaseFee * @param _data Unsigned RLP encoded tx, 6 elements * @return L1 fee that should be paid for the tx */ // slither-disable-next-line external-function function getL1Fee(bytes memory _data) public 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; } // solhint-disable max-line-length /** * Computes the amount of L1 gas used for a transaction * The overhead represents the per batch gas overhead of * posting both transaction and state roots to L1 given larger * batch sizes. * 4 gas for 0 byte * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L33 * 16 gas for non zero byte * https://github.com/ethereum/go-ethereum/blob/9ada4a2e2c415e6b0b51c50e901336872e028872/params/protocol_params.go#L87 * This will need to be updated if calldata gas prices change * Account for the transaction being unsigned * Padding is added to account for lack of signature on transaction * 1 byte for RLP V prefix * 1 byte for V * 1 byte for RLP R prefix * 32 bytes for R * 1 byte for RLP S prefix * 32 bytes for S * Total: 68 bytes of padding * @param _data Unsigned RLP encoded tx, 6 elements * @return Amount of L1 gas used for a transaction */ // solhint-enable max-line-length function getL1GasUsed(bytes memory _data) public view returns (uint256) { uint256 total = 0; for (uint256 i = 0; i < _data.length; i++) { if (_data[i] == 0) { total += 4; } else { total += 16; } } uint256 unsigned = total + overhead; return unsigned + (68 * 16); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; interface IScrollL1GasPriceOracle { /********** * Events * **********/ /// @notice Emitted when current fee overhead is updated. /// @param overhead The current fee overhead updated. event OverheadUpdated(uint256 overhead); /// @notice Emitted when current fee scalar is updated. /// @param scalar The current fee scalar updated. event ScalarUpdated(uint256 scalar); /// @notice Emitted when current l1 base fee is updated. /// @param l1BaseFee The current l1 base fee updated. event L1BaseFeeUpdated(uint256 l1BaseFee); /************************* * Public View Functions * *************************/ /// @notice Return the current l1 fee overhead. function overhead() external view returns (uint256); /// @notice Return the current l1 fee scalar. function scalar() external view returns (uint256); /// @notice Return the latest known l1 base fee. function l1BaseFee() external view returns (uint256); /// @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); /// @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 74 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) external view returns (uint256); /***************************** * Public Mutating Functions * *****************************/ /// @notice Allows whitelisted caller to modify the l1 base fee. /// @param _l1BaseFee New l1 base fee. function setL1BaseFee(uint256 _l1BaseFee) external; }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint8","name":"coefficient","type":"uint8"}],"name":"InvalidL1FeeCoefficient","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"coefficient","type":"uint8"}],"name":"L1FeeCoefficientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"n","type":"uint256"}],"name":"blockHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dataSize","type":"uint256"}],"name":"getCurrentL1Fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGasOverhead","outputs":[{"internalType":"uint256","name":"chainModuleFixedOverhead","type":"uint256"},{"internalType":"uint256","name":"chainModulePerByteOverhead","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getL1FeeCoefficient","outputs":[{"internalType":"uint256","name":"coefficient","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"dataSize","type":"uint256"}],"name":"getMaxL1Fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"coefficient","type":"uint8"}],"name":"setL1FeeCalculation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100be5760003560e01c80638da5cb5b11610076578063de9ee35e1161005b578063de9ee35e1461016a578063f22559a014610180578063f2fde38b1461019357600080fd5b80638da5cb5b1461011f578063d10a944e1461014757600080fd5b80637810d12a116100a75780637810d12a146100ef57806379ba50971461010257806385df51fd1461010c57600080fd5b806312544140146100c357806357e871e7146100e9575b600080fd5b6100d66100d136600461069d565b6101a6565b6040519081526020015b60405180910390f35b436100d6565b6100d66100fd36600461069d565b6101b7565b61010a6101f6565b005b6100d661011a36600461069d565b6102f8565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e0565b60015474010000000000000000000000000000000000000000900460ff166100d6565b6040805161afc8815260aa6020820152016100e0565b61010a61018e3660046106b6565b610325565b61010a6101a13660046106d9565b6103f0565b60006101b182610404565b92915050565b600060646101c483610404565b6001546101ec919074010000000000000000000000000000000000000000900460ff1661073e565b6101b19190610755565b60015473ffffffffffffffffffffffffffffffffffffffff16331461027c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6000438210158061031357506101006103118343610790565b115b1561032057506000919050565b504090565b61032d610525565b60648160ff161115610370576040517f1a8a06a000000000000000000000000000000000000000000000000000000000815260ff82166004820152602401610273565b600180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000060ff8416908102919091179091556040519081527f29ec9e31de0d3fe0208a7ccb792bbc26a854f123146110daa3a77219cb74a5549060200160405180910390a150565b6103f8610525565b610401816105a8565b50565b60008061041283600461073e565b67ffffffffffffffff81111561042a5761042a6107a3565b6040519080825280601f01601f191660200182016040528015610454576020820181803683370190505b50905073530000000000000000000000000000000000000273ffffffffffffffffffffffffffffffffffffffff166349948e0e826040518060c00160405280608c8152602001610890608c91396040516020016104b29291906107f6565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016104dd9190610825565b602060405180830381865afa1580156104fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051e9190610876565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146105a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610273565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610627576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610273565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156106af57600080fd5b5035919050565b6000602082840312156106c857600080fd5b813560ff8116811461051e57600080fd5b6000602082840312156106eb57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461051e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176101b1576101b161070f565b60008261078b577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b818103818111156101b1576101b161070f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60005b838110156107ed5781810151838201526020016107d5565b50506000910152565b600083516108088184602088016107d2565b83519083019061081c8183602088016107d2565b01949350505050565b60208152600082518060208401526108448160408501602087016107d2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561088857600080fd5b505191905056feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa164736f6c6343000813000a
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.