More Info
Private Name Tags
ContractCreator
GENESIS at txn GENESIS_4200000000000000000000000000000000000006
TokenTracker

Latest 25 from a total of 367,229 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Withdraw | 11698581 | 9 secs ago | IN | 0 ETH | 0 | ||||
Approve | 11698568 | 22 secs ago | IN | 0 ETH | 0.00000006 | ||||
Deposit | 11698556 | 34 secs ago | IN | 0.0002 ETH | 0 | ||||
Withdraw | 11698533 | 57 secs ago | IN | 0 ETH | 0 | ||||
Deposit | 11698511 | 1 min ago | IN | 0.0002 ETH | 0 | ||||
Withdraw | 11698477 | 1 min ago | IN | 0 ETH | 0 | ||||
Withdraw | 11698476 | 1 min ago | IN | 0 ETH | 0.00000004 | ||||
Deposit | 11698441 | 2 mins ago | IN | 0.0002 ETH | 0 | ||||
Deposit | 11698429 | 2 mins ago | IN | 0.000016 ETH | 0.00000004 | ||||
Deposit | 11698427 | 2 mins ago | IN | 0.00001487 ETH | 0.00000004 | ||||
Deposit | 11698425 | 2 mins ago | IN | 0.00001347 ETH | 0.00000004 | ||||
Deposit | 11698423 | 2 mins ago | IN | 0.00001375 ETH | 0.00000004 | ||||
Deposit | 11698421 | 2 mins ago | IN | 0.00014763 ETH | 0.00000006 | ||||
Deposit | 11698411 | 2 mins ago | IN | 0.000018 ETH | 0.00000004 | ||||
Deposit | 11698410 | 3 mins ago | IN | 0.00001345 ETH | 0.00000004 | ||||
Approve | 11698410 | 3 mins ago | IN | 0 ETH | 0.00000006 | ||||
Withdraw | 11698408 | 3 mins ago | IN | 0 ETH | 0 | ||||
Deposit | 11698398 | 3 mins ago | IN | 0.00001452 ETH | 0.00000004 | ||||
Deposit | 11698397 | 3 mins ago | IN | 0.00001567 ETH | 0.00000004 | ||||
Deposit | 11698395 | 3 mins ago | IN | 0.00001243 ETH | 0.00000004 | ||||
Deposit | 11698394 | 3 mins ago | IN | 0.00001765 ETH | 0.00000004 | ||||
Deposit | 11698384 | 3 mins ago | IN | 0.0002 ETH | 0 | ||||
Withdraw | 11698381 | 3 mins ago | IN | 0 ETH | 0.00000005 | ||||
Deposit | 11698334 | 4 mins ago | IN | 0.00015601 ETH | 0.00000006 | ||||
Deposit | 11698315 | 4 mins ago | IN | 0.00014435 ETH | 0.00000004 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
11698581 | 9 secs ago | 0.0002 ETH | ||||
11698554 | 36 secs ago | 0.008 ETH | ||||
11698549 | 41 secs ago | 0.00804163 ETH | ||||
11698548 | 42 secs ago | 0.04997533 ETH | ||||
11698546 | 44 secs ago | 0.29636584 ETH | ||||
11698540 | 50 secs ago | 0.0004 ETH | ||||
11698535 | 55 secs ago | 0.014 ETH | ||||
11698533 | 57 secs ago | 0.0002 ETH | ||||
11698526 | 1 min ago | 0.0012 ETH | ||||
11698523 | 1 min ago | 0.00539141 ETH | ||||
11698522 | 1 min ago | 0.00000017 ETH | ||||
11698522 | 1 min ago | 0.002 ETH | ||||
11698517 | 1 min ago | 0.00014769 ETH | ||||
11698517 | 1 min ago | 0.00014769 ETH | ||||
11698503 | 1 min ago | 0.00868778 ETH | ||||
11698503 | 1 min ago | 0.002 ETH | ||||
11698500 | 1 min ago | 0.0001029 ETH | ||||
11698500 | 1 min ago | 0.0000222 ETH | ||||
11698499 | 1 min ago | 0.00000468 ETH | ||||
11698491 | 1 min ago | 0.0139878 ETH | ||||
11698480 | 1 min ago | 0.00001483 ETH | ||||
11698477 | 1 min ago | 0.0002 ETH | ||||
11698476 | 1 min ago | 0.00014763 ETH | ||||
11698474 | 1 min ago | 0.00001562 ETH | ||||
11698474 | 1 min ago | 0.00003124 ETH |
Latest 25 Deposits
Loading...
Loading
Contract Name:
WETH
Compiler Version
v0.8.15+commit.e14f2714
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import { WETH98 } from "src/dispute/weth/WETH98.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { L1Block } from "src/L2/L1Block.sol"; import { ISemver } from "src/universal/interfaces/ISemver.sol"; /// @title WETH contract that reads the name and symbol from the L1Block contract. /// Allows for nice rendering of token names for chains using custom gas token. contract WETH is WETH98, ISemver { /// @custom:semver 1.0.0-beta.1 string public constant version = "1.0.0-beta.1"; /// @notice Returns the name of the wrapped native asset. Will be "Wrapped Ether" /// if the native asset is Ether. function name() external view override returns (string memory name_) { name_ = string.concat("Wrapped ", L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingTokenName()); } /// @notice Returns the symbol of the wrapped native asset. Will be "WETH" if the /// native asset is Ether. function symbol() external view override returns (string memory symbol_) { symbol_ = string.concat("W", L1Block(Predeploys.L1_BLOCK_ATTRIBUTES).gasPayingTokenSymbol()); } }
// SPDX-License-Identifier: GPL-3.0 // Copyright (C) 2015, 2016, 2017 Dapphub // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // Based on WETH9 by Dapphub. // Modified by OP Labs. pragma solidity 0.8.15; import { IWETH } from "src/dispute/interfaces/IWETH.sol"; /// @title WETH98 /// @notice WETH98 is a version of WETH9 upgraded for Solidity 0.8.x. contract WETH98 is IWETH { uint8 public constant decimals = 18; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /// @notice Pipes to deposit. receive() external payable { deposit(); } /// @notice Pipes to deposit. fallback() external payable { deposit(); } /// @inheritdoc IWETH function name() external view virtual override returns (string memory) { return "Wrapped Ether"; } /// @inheritdoc IWETH function symbol() external view virtual override returns (string memory) { return "WETH"; } /// @inheritdoc IWETH function deposit() public payable virtual { balanceOf[msg.sender] += msg.value; emit Deposit(msg.sender, msg.value); } /// @inheritdoc IWETH function withdraw(uint256 wad) public virtual { require(balanceOf[msg.sender] >= wad); balanceOf[msg.sender] -= wad; payable(msg.sender).transfer(wad); emit Withdrawal(msg.sender, wad); } /// @inheritdoc IWETH function totalSupply() external view returns (uint256) { return address(this).balance; } /// @inheritdoc IWETH function approve(address guy, uint256 wad) external returns (bool) { allowance[msg.sender][guy] = wad; emit Approval(msg.sender, guy, wad); return true; } /// @inheritdoc IWETH function transfer(address dst, uint256 wad) external returns (bool) { return transferFrom(msg.sender, dst, wad); } /// @inheritdoc IWETH function transferFrom(address src, address dst, uint256 wad) public returns (bool) { require(balanceOf[src] >= wad); if (src != msg.sender && allowance[src][msg.sender] != type(uint256).max) { require(allowance[src][msg.sender] >= wad); allowance[src][msg.sender] -= wad; } balanceOf[src] -= wad; balanceOf[dst] += wad; emit Transfer(src, dst, wad); return true; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @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 Address of the SuperchainWETH predeploy. address internal constant SUPERCHAIN_WETH = 0x4200000000000000000000000000000000000024; /// @notice Address of the ETHLiquidity predeploy. address internal constant ETH_LIQUIDITY = 0x4200000000000000000000000000000000000025; /// @notice Address of the OptimismSuperchainERC20Factory predeploy. address internal constant OPTIMISM_SUPERCHAIN_ERC20_FACTORY = 0x4200000000000000000000000000000000000026; /// @notice Address of the OptimismSuperchainERC20Beacon predeploy. address internal constant OPTIMISM_SUPERCHAIN_ERC20_BEACON = 0x4200000000000000000000000000000000000027; // TODO: Precalculate the address of the implementation contract /// @notice Arbitrary address of the OptimismSuperchainERC20 implementation contract. address internal constant OPTIMISM_SUPERCHAIN_ERC20 = 0xB9415c6cA93bdC545D4c5177512FCC22EFa38F28; /// @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"; if (_addr == SUPERCHAIN_WETH) return "SuperchainWETH"; if (_addr == ETH_LIQUIDITY) return "ETHLiquidity"; if (_addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY) return "OptimismSuperchainERC20Factory"; if (_addr == OPTIMISM_SUPERCHAIN_ERC20_BEACON) return "OptimismSuperchainERC20Beacon"; 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) || (_useInterop && _addr == SUPERCHAIN_WETH) || (_useInterop && _addr == ETH_LIQUIDITY) || (_useInterop && _addr == OPTIMISM_SUPERCHAIN_ERC20_FACTORY) || (_useInterop && _addr == OPTIMISM_SUPERCHAIN_ERC20_BEACON); } 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.15; import { ISemver } from "src/universal/interfaces/ISemver.sol"; import { Constants } from "src/libraries/Constants.sol"; import { GasPayingToken, IGasToken } from "src/libraries/GasPayingToken.sol"; import "src/libraries/L1BlockErrors.sol"; /// @custom:proxied true /// @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.5.1-beta.1 function version() public pure virtual returns (string memory) { return "1.5.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() public { _setL1BlockValuesEcotone(); } /// @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() internal { 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; /// @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.0; /// @title IWETH /// @notice Interface for WETH9. interface IWETH { /// @notice Emitted when an approval is made. /// @param src The address that approved the transfer. /// @param guy The address that was approved to transfer. /// @param wad The amount that was approved to transfer. event Approval(address indexed src, address indexed guy, uint256 wad); /// @notice Emitted when a transfer is made. /// @param src The address that transferred the WETH. /// @param dst The address that received the WETH. /// @param wad The amount of WETH that was transferred. event Transfer(address indexed src, address indexed dst, uint256 wad); /// @notice Emitted when a deposit is made. /// @param dst The address that deposited the WETH. /// @param wad The amount of WETH that was deposited. event Deposit(address indexed dst, uint256 wad); /// @notice Emitted when a withdrawal is made. /// @param src The address that withdrew the WETH. /// @param wad The amount of WETH that was withdrawn. event Withdrawal(address indexed src, uint256 wad); /// @notice Returns the name of the token. /// @return The name of the token. function name() external view returns (string memory); /// @notice Returns the symbol of the token. /// @return The symbol of the token. function symbol() external view returns (string memory); /// @notice Returns the number of decimals the token uses. /// @return The number of decimals the token uses. function decimals() external pure returns (uint8); /// @notice Returns the balance of the given address. /// @param owner The address to query the balance of. /// @return The balance of the given address. function balanceOf(address owner) external view returns (uint256); /// @notice Returns the amount of WETH that the spender can transfer on behalf of the owner. /// @param owner The address that owns the WETH. /// @param spender The address that is approved to transfer the WETH. /// @return The amount of WETH that the spender can transfer on behalf of the owner. function allowance(address owner, address spender) external view returns (uint256); /// @notice Allows WETH to be deposited by sending ether to the contract. function deposit() external payable; /// @notice Withdraws an amount of ETH. /// @param wad The amount of ETH to withdraw. function withdraw(uint256 wad) external; /// @notice Returns the total supply of WETH. /// @return The total supply of WETH. function totalSupply() external view returns (uint256); /// @notice Approves the given address to transfer the WETH on behalf of the caller. /// @param guy The address that is approved to transfer the WETH. /// @param wad The amount that is approved to transfer. /// @return True if the approval was successful. function approve(address guy, uint256 wad) external returns (bool); /// @notice Transfers the given amount of WETH to the given address. /// @param dst The address to transfer the WETH to. /// @param wad The amount of WETH to transfer. /// @return True if the transfer was successful. function transfer(address dst, uint256 wad) external returns (bool); /// @notice Transfers the given amount of WETH from the given address to the given address. /// @param src The address to transfer the WETH from. /// @param dst The address to transfer the WETH to. /// @param wad The amount of WETH to transfer. /// @return True if the transfer was successful. function transferFrom(address src, address dst, uint256 wad) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; /// @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; /// @notice Returns the default values for the ResourceConfig. These are the recommended values /// for a production network. function DEFAULT_RESOURCE_CONFIG() internal pure returns (IResourceMetering.ResourceConfig memory) { IResourceMetering.ResourceConfig memory config = IResourceMetering.ResourceConfig({ maxResourceLimit: 20_000_000, elasticityMultiplier: 10, baseFeeMaxChangeDenominator: 8, minimumBaseFee: 1 gwei, systemTxMaxGas: 1_000_000, maximumBaseFee: type(uint128).max }); return config; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { Storage } from "src/libraries/Storage.sol"; import { Constants } from "src/libraries/Constants.sol"; import { LibString } from "@solady/utils/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 Error returns when a non-depositor account tries to set L1 block values. error NotDepositor(); /// @notice Error when a non-cross L2 Inbox sender tries to call the `isDeposit()` method. error NotCrossL2Inbox(); /// @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; interface IResourceMetering { struct ResourceParams { uint128 prevBaseFee; uint64 prevBoughtGas; uint64 prevBlockNum; } struct ResourceConfig { uint32 maxResourceLimit; uint8 elasticityMultiplier; uint8 baseFeeMaxChangeDenominator; uint32 minimumBaseFee; uint32 systemTxMaxGas; uint128 maximumBaseFee; } error OutOfGas(); event Initialized(uint8 version); function params() external view returns (uint128 prevBaseFee, uint64 prevBoughtGas, uint64 prevBlockNum); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @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.4; /// @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 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The length of the output is too small to contain all the hex digits. error HexLengthInsufficient(); /// @dev The length of the string is more than 32 bytes. error TooBigForSmallString(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the string. uint256 internal constant NOT_FOUND = type(uint256).max; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* DECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the base 10 decimal representation of `value`. function toString(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. str := add(mload(0x40), 0x80) // Update the free memory pointer to allocate. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str let w := not(0) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `sub(str, 1)`. // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } /// @dev Returns the base 10 decimal representation of `value`. function toString(int256 value) internal pure returns (string memory str) { if (value >= 0) { return toString(uint256(value)); } unchecked { str = toString(uint256(-value)); } /// @solidity memory-safe-assembly assembly { // We still have some spare memory space on the left, // as we have allocated 3 words (96 bytes) for up to 78 digits. let length := mload(str) // Load the string length. mstore(str, 0x2d) // Store the '-' character. str := sub(str, 1) // Move back the string pointer by a byte. mstore(str, add(length, 1)) // Update the string length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HEXADECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2 + 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) { str = toHexStringNoPrefix(value, length); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length. // We add 0x20 to the total and round down to a multiple of 0x20. // (0x20 + 0x20 + 0x02 + 0x20) = 0x62. str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f))) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let start := sub(str, add(length, length)) let w := not(1) // Tsk. let temp := value // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for {} 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(xor(str, start)) { break } } if temp { mstore(0x00, 0x2194895a) // `HexLengthInsufficient()`. revert(0x1c, 0x04) } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2 + 2` bytes. function toHexString(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x". /// The output excludes leading "0" from the `toHexString` output. /// `0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`. function toMinimalHexString(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present. let strLength := add(mload(str), 2) // Compute the length. mstore(add(str, o), 0x3078) // Write the "0x" prefix, accounting for leading zero. str := sub(add(str, o), 2) // Move the pointer, accounting for leading zero. mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output excludes leading "0" from the `toHexStringNoPrefix` output. /// `0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`. function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present. let strLength := mload(str) // Get the length. str := add(str, o) // Move the pointer, accounting for leading zero. mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2` bytes. function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x40 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0. str := add(mload(0x40), 0x80) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let w := not(1) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(temp) { break } } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte, /// and the alphabets are capitalized conditionally according to /// https://eips.ethereum.org/EIPS/eip-55 function toHexStringChecksummed(address value) internal pure returns (string memory str) { str = toHexString(value); /// @solidity memory-safe-assembly assembly { let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...` let o := add(str, 0x22) let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... ` let t := shl(240, 136) // `0b10001000 << 240` for { let i := 0 } 1 {} { mstore(add(i, i), mul(t, byte(i, hashed))) i := add(i, 1) if eq(i, 20) { break } } mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask))))) o := add(o, 0x20) mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask))))) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. function toHexString(address value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(address value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { str := mload(0x40) // Allocate the memory. // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x28 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80. mstore(0x40, add(str, 0x80)) // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) str := add(str, 2) mstore(str, 40) let o := add(str, 0x20) mstore(add(o, 40), 0) value := shl(96, value) // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let i := 0 } 1 {} { let p := add(o, add(i, i)) let temp := byte(i, value) mstore8(add(p, 1), mload(and(temp, 15))) mstore8(p, mload(shr(4, temp))) i := add(i, 1) if eq(i, 20) { break } } } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexString(bytes memory raw) internal pure returns (string memory str) { str = toHexStringNoPrefix(raw); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { let length := mload(raw) str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix. mstore(str, add(length, length)) // Store the length of the output. // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let o := add(str, 0x20) let end := add(raw, length) for {} iszero(eq(raw, end)) {} { raw := add(raw, 1) mstore8(add(o, 1), mload(and(mload(raw), 15))) mstore8(o, mload(and(shr(4, mload(raw)), 15))) o := add(o, 2) } mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate the memory. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RUNE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the number of UTF characters in the string. function runeCount(string memory s) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { mstore(0x00, div(not(0), 255)) mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506) let o := add(s, 0x20) let end := add(o, mload(s)) for { result := 1 } 1 { result := add(result, 1) } { o := add(o, byte(0, mload(shr(250, mload(o))))) if iszero(lt(o, end)) { break } } } } } /// @dev Returns if this string is a 7-bit ASCII string. /// (i.e. all characters codes are in [0..127]) function is7BitASCII(string memory s) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let mask := shl(7, div(not(0), 255)) result := 1 let n := mload(s) if n { let o := add(s, 0x20) let end := add(o, n) let last := mload(end) mstore(end, 0) for {} 1 {} { if and(mask, mload(o)) { result := 0 break } o := add(o, 0x20) if iszero(lt(o, end)) { break } } mstore(end, last) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // For performance and bytecode compactness, byte string operations are restricted // to 7-bit ASCII strings. All offsets are byte offsets, not UTF character offsets. // Usage of byte string operations on charsets with runes spanning two or more bytes // can lead to undefined behavior. /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`. function replace(string memory subject, string memory search, string memory replacement) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) let replacementLength := mload(replacement) subject := add(subject, 0x20) search := add(search, 0x20) replacement := add(replacement, 0x20) result := add(mload(0x40), 0x20) let subjectEnd := add(subject, subjectLength) if iszero(gt(searchLength, subjectLength)) { let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Copy the `replacement` one word at a time. for { let o := 0 } 1 {} { mstore(add(result, o), mload(add(replacement, o))) o := add(o, 0x20) if iszero(lt(o, replacementLength)) { break } } result := add(result, replacementLength) subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } } let resultRemainder := result result := add(mload(0x40), 0x20) let k := add(sub(resultRemainder, result), sub(subjectEnd, subject)) // Copy the rest of the string one word at a time. for {} lt(subject, subjectEnd) {} { mstore(resultRemainder, mload(subject)) resultRemainder := add(resultRemainder, 0x20) subject := add(subject, 0x20) } result := sub(result, 0x20) let last := add(add(result, 0x20), k) // Zeroize the slot after the string. mstore(last, 0) mstore(0x40, add(last, 0x20)) // Allocate the memory. mstore(result, k) // Store the length. } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for { let subjectLength := mload(subject) } 1 {} { if iszero(mload(search)) { if iszero(gt(from, subjectLength)) { result := from break } result := subjectLength break } let searchLength := mload(search) let subjectStart := add(subject, 0x20) result := not(0) // Initialize to `NOT_FOUND`. subject := add(subjectStart, from) let end := add(sub(add(subjectStart, subjectLength), searchLength), 1) let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(add(search, 0x20)) if iszero(and(lt(subject, end), lt(from, subjectLength))) { break } if iszero(lt(searchLength, 0x20)) { for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if iszero(shr(m, xor(mload(subject), s))) { if eq(keccak256(subject, searchLength), h) { result := sub(subject, subjectStart) break } } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } for {} 1 {} { if iszero(shr(m, xor(mload(subject), s))) { result := sub(subject, subjectStart) break } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = indexOf(subject, search, 0); } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for {} 1 {} { result := not(0) // Initialize to `NOT_FOUND`. let searchLength := mload(search) if gt(searchLength, mload(subject)) { break } let w := result let fromMax := sub(mload(subject), searchLength) if iszero(gt(fromMax, from)) { from := fromMax } let end := add(add(subject, 0x20), w) subject := add(add(subject, 0x20), from) if iszero(gt(subject, end)) { break } // As this function is not too often used, // we shall simply use keccak256 for smaller bytecode size. for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if eq(keccak256(subject, searchLength), h) { result := sub(subject, add(end, 1)) break } subject := add(subject, w) // `sub(subject, 1)`. if iszero(gt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = lastIndexOf(subject, search, uint256(int256(-1))); } /// @dev Returns true if `search` is found in `subject`, false otherwise. function contains(string memory subject, string memory search) internal pure returns (bool) { return indexOf(subject, search) != NOT_FOUND; } /// @dev Returns whether `subject` starts with `search`. function startsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( iszero(gt(searchLength, mload(subject))), eq( keccak256(add(subject, 0x20), searchLength), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns whether `subject` ends with `search`. function endsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) let subjectLength := mload(subject) // Whether `search` is not longer than `subject`. let withinRange := iszero(gt(searchLength, subjectLength)) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( withinRange, eq( keccak256( // `subject + 0x20 + max(subjectLength - searchLength, 0)`. add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))), searchLength ), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns `subject` repeated `times`. function repeat(string memory subject, uint256 times) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(or(iszero(times), iszero(subjectLength))) { subject := add(subject, 0x20) result := mload(0x40) let output := add(result, 0x20) for {} 1 {} { // Copy the `subject` one word at a time. for { let o := 0 } 1 {} { mstore(add(output, o), mload(add(subject, o))) o := add(o, 0x20) if iszero(lt(o, subjectLength)) { break } } output := add(output, subjectLength) times := sub(times, 1) if iszero(times) { break } } mstore(output, 0) // Zeroize the slot after the string. let resultLength := sub(output, add(result, 0x20)) mstore(result, resultLength) // Store the length. // Allocate the memory. mstore(0x40, add(result, add(resultLength, 0x20))) } } } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. function slice(string memory subject, uint256 start, uint256 end) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(gt(subjectLength, end)) { end := subjectLength } if iszero(gt(subjectLength, start)) { start := subjectLength } if lt(start, end) { result := mload(0x40) let resultLength := sub(end, start) mstore(result, resultLength) subject := add(subject, start) let w := not(0x1f) // Copy the `subject` one word at a time, backwards. for { let o := and(add(resultLength, 0x1f), w) } 1 {} { mstore(add(result, o), mload(add(subject, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(result, 0x20), resultLength), 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(result, and(add(resultLength, 0x3f), w))) } } } /// @dev Returns a copy of `subject` sliced from `start` to the end of the string. /// `start` is a byte offset. function slice(string memory subject, uint256 start) internal pure returns (string memory result) { result = slice(subject, start, uint256(int256(-1))); } /// @dev Returns all the indices of `search` in `subject`. /// The indices are byte offsets. function indicesOf(string memory subject, string memory search) internal pure returns (uint256[] memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) if iszero(gt(searchLength, subjectLength)) { subject := add(subject, 0x20) search := add(search, 0x20) result := add(mload(0x40), 0x20) let subjectStart := subject let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Append to `result`. mstore(result, sub(subject, subjectStart)) result := add(result, 0x20) // Advance `subject` by `searchLength`. subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } let resultEnd := result // Assign `result` to the free memory pointer. result := mload(0x40) // Store the length of `result`. mstore(result, shr(5, sub(resultEnd, add(result, 0x20)))) // Allocate memory for result. // We allocate one more word, so this array can be recycled for {split}. mstore(0x40, add(resultEnd, 0x20)) } } } /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string. function split(string memory subject, string memory delimiter) internal pure returns (string[] memory result) { uint256[] memory indices = indicesOf(subject, delimiter); /// @solidity memory-safe-assembly assembly { let w := not(0x1f) let indexPtr := add(indices, 0x20) let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1))) mstore(add(indicesEnd, w), mload(subject)) mstore(indices, add(mload(indices), 1)) let prevIndex := 0 for {} 1 {} { let index := mload(indexPtr) mstore(indexPtr, 0x60) if iszero(eq(index, prevIndex)) { let element := mload(0x40) let elementLength := sub(index, prevIndex) mstore(element, elementLength) // Copy the `subject` one word at a time, backwards. for { let o := and(add(elementLength, 0x1f), w) } 1 {} { mstore(add(element, o), mload(add(add(subject, prevIndex), o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(element, 0x20), elementLength), 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(element, and(add(elementLength, 0x3f), w))) // Store the `element` into the array. mstore(indexPtr, element) } prevIndex := add(index, mload(delimiter)) indexPtr := add(indexPtr, 0x20) if iszero(lt(indexPtr, indicesEnd)) { break } } result := indices if iszero(mload(delimiter)) { result := add(indices, 0x20) mstore(result, sub(mload(indices), 2)) } } } /// @dev Returns a concatenated string of `a` and `b`. /// Cheaper than `string.concat()` and does not de-align the free memory pointer. function concat(string memory a, string memory b) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let w := not(0x1f) result := mload(0x40) let aLength := mload(a) // Copy `a` one word at a time, backwards. for { let o := and(add(aLength, 0x20), w) } 1 {} { mstore(add(result, o), mload(add(a, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let bLength := mload(b) let output := add(result, aLength) // Copy `b` one word at a time, backwards. for { let o := and(add(bLength, 0x20), w) } 1 {} { mstore(add(output, o), mload(add(b, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let totalLength := add(aLength, bLength) let last := add(add(result, 0x20), totalLength) // Zeroize the slot after the string. mstore(last, 0) // Stores the length. mstore(result, totalLength) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, and(add(last, 0x1f), w)) } } /// @dev Returns a copy of the string in either lowercase or UPPERCASE. /// WARNING! This function is only compatible with 7-bit ASCII strings. function toCase(string memory subject, bool toUpper) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let length := mload(subject) if length { result := add(mload(0x40), 0x20) subject := add(subject, 1) let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff) let w := not(0) for { let o := length } 1 {} { o := add(o, w) let b := and(0xff, mload(add(subject, o))) mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20))) if iszero(o) { break } } result := mload(0x40) mstore(result, length) // Store the length. let last := add(add(result, 0x20), length) mstore(last, 0) // Zeroize the slot after the string. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } } /// @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 small string, with all bytes after the first null byte zeroized. function normalizeSmallString(bytes32 s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { for {} byte(result, s) { result := add(result, 1) } {} // Scan for '\0'. mstore(0x00, s) mstore(result, 0x00) result := mload(0x00) } } /// @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))) } } /// @dev Returns a lowercased copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function lower(string memory subject) internal pure returns (string memory result) { result = toCase(subject, false); } /// @dev Returns an UPPERCASED copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function upper(string memory subject) internal pure returns (string memory result) { result = toCase(subject, true); } /// @dev Escapes the string to be used within HTML tags. function escapeHTML(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) // Store the bytes of the packed offsets and strides into the scratch space. // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6. mstore(0x1f, 0x900094) mstore(0x08, 0xc0000000a6ab) // Store ""&'<>" into the scratch space. mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) // Not in `["\"","'","&","<",">"]`. if iszero(and(shl(c, 1), 0x500000c400000000)) { mstore8(result, c) result := add(result, 1) continue } let t := shr(248, mload(c)) mstore(result, mload(and(t, 0x1f))) result := add(result, shr(5, t)) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes. function escapeJSON(string memory s, bool addDoubleQuotes) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) if addDoubleQuotes { mstore8(result, 34) result := add(1, result) } // Store "\\u0000" in scratch space. // Store "0123456789abcdef" in scratch space. // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`. // into the scratch space. mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672) // Bitmask for detecting `["\"","\\"]`. let e := or(shl(0x22, 1), shl(0x5c, 1)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) if iszero(lt(c, 0x20)) { if iszero(and(shl(c, 1), e)) { // Not in `["\"","\\"]`. mstore8(result, c) result := add(result, 1) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), c) result := add(result, 2) continue } if iszero(and(shl(c, 1), 0x3700)) { // Not in `["\b","\t","\n","\f","\d"]`. mstore8(0x1d, mload(shr(4, c))) // Hex value. mstore8(0x1e, mload(and(c, 15))) // Hex value. mstore(result, mload(0x19)) // "\\u00XX". result := add(result, 6) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), mload(add(c, 8))) result := add(result, 2) } if addDoubleQuotes { mstore8(result, 34) result := add(1, result) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. function escapeJSON(string memory s) internal pure returns (string memory result) { result = escapeJSON(s, false); } /// @dev Returns whether `a` equals `b`. function eq(string memory a, string memory b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @dev Returns whether `a` equals `b`, where `b` is a null-terminated small string. function eqs(string memory a, bytes32 b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // These should be evaluated on compile time, as far as possible. let m := not(shl(7, div(not(iszero(b)), 255))) // `0x7f7f ...`. let x := not(or(m, or(b, add(m, and(b, m))))) let r := shl(7, iszero(iszero(shr(128, x)))) r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x)))))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item result := gt(eq(mload(a), add(iszero(x), xor(31, shr(3, r)))), xor(shr(add(8, r), b), shr(add(8, r), mload(add(a, 0x20))))) } } /// @dev Packs a single string with its length into a single word. /// Returns `bytes32(0)` if the length is zero or greater than 31. function packOne(string memory a) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { // We don't need to zero right pad the string, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes. mload(add(a, 0x1f)), // `length != 0 && length < 32`. Abuses underflow. // Assumes that the length is valid and within the block gas limit. lt(sub(mload(a), 1), 0x1f) ) } } /// @dev Unpacks a string packed using {packOne}. /// Returns the empty string if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packOne}, the output behavior is undefined. function unpackOne(bytes32 packed) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. result := mload(0x40) // Allocate 2 words (1 for the length, 1 for the bytes). mstore(0x40, add(result, 0x40)) // Zeroize the length slot. mstore(result, 0) // Store the length and bytes. mstore(add(result, 0x1f), packed) // Right pad with zeroes. mstore(add(add(result, 0x20), mload(result)), 0) } } /// @dev Packs two strings with their lengths into a single word. /// Returns `bytes32(0)` if combined length is zero or greater than 30. function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let aLength := mload(a) // We don't need to zero right pad the strings, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes of `a` and `b`. or( shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))), mload(sub(add(b, 0x1e), aLength)) ), // `totalLength != 0 && totalLength < 31`. Abuses underflow. // Assumes that the lengths are valid and within the block gas limit. lt(sub(add(aLength, mload(b)), 1), 0x1e) ) } } /// @dev Unpacks strings packed using {packTwo}. /// Returns the empty strings if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packTwo}, the output behavior is undefined. function unpackTwo(bytes32 packed) internal pure returns (string memory resultA, string memory resultB) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. resultA := mload(0x40) resultB := add(resultA, 0x40) // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words. mstore(0x40, add(resultB, 0x40)) // Zeroize the length slots. mstore(resultA, 0) mstore(resultB, 0) // Store the lengths and bytes. mstore(add(resultA, 0x1f), packed) mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA)))) // Right pad with zeroes. mstore(add(add(resultA, 0x20), mload(resultA)), 0) mstore(add(add(resultB, 0x20), mload(resultB)), 0) } } /// @dev Directly returns `a` without copying. function directReturn(string memory a) internal pure { assembly { // Assumes that the string does not start from the scratch space. let retStart := sub(a, 0x20) let retSize := add(mload(a), 0x40) // Right pad with zeroes. Just in case the string is produced // by a method that doesn't zero right pad. mstore(add(retStart, retSize), 0) // Store the return offset. mstore(retStart, 0x20) // End the transaction, returning the string. return(retStart, retSize) } } }
{ "remappings": [ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-v5/=lib/openzeppelin-contracts-v5/contracts/", "@rari-capital/solmate/=lib/solmate/", "@lib-keccak/=lib/lib-keccak/contracts/lib/", "@solady/=lib/solady/src/", "forge-std/=lib/forge-std/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "safe-contracts/=lib/safe-contracts/contracts/", "kontrol-cheatcodes/=lib/kontrol-cheatcodes/src/", "gelato/=lib/automate/contracts/", "@solady-test/=lib/lib-keccak/lib/solady/test/", "automate/=lib/automate/contracts/", "erc4626-tests/=lib/openzeppelin-contracts-v5/lib/erc4626-tests/", "hardhat/=lib/automate/node_modules/hardhat/", "lib-keccak/=lib/lib-keccak/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts-v5/=lib/openzeppelin-contracts-v5/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "prb-test/=lib/automate/lib/prb-test/src/", "prb/-est/=lib/automate/lib/prb-test/src/", "solady/=lib/solady/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 999999 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"guy","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"guy","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"name_","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080604052600436106100cb5760003560e01c806354fd4d5011610074578063a9059cbb1161004e578063a9059cbb1461024c578063d0e30db0146100da578063dd62ed3e1461026c576100da565b806354fd4d50146101c157806370a082311461020a57806395d89b4114610237576100da565b806323b872dd116100a557806323b872dd1461015a5780632e1a7d4d1461017a578063313ce5671461019a576100da565b806306fdde03146100e2578063095ea7b31461010d57806318160ddd1461013d576100da565b366100da576100d86102a4565b005b6100d86102a4565b3480156100ee57600080fd5b506100f76102ff565b60405161010491906107fb565b60405180910390f35b34801561011957600080fd5b5061012d610128366004610875565b6103ca565b6040519015158152602001610104565b34801561014957600080fd5b50475b604051908152602001610104565b34801561016657600080fd5b5061012d61017536600461089f565b610443565b34801561018657600080fd5b506100d86101953660046108db565b61065a565b3480156101a657600080fd5b506101af601281565b60405160ff9091168152602001610104565b3480156101cd57600080fd5b506100f76040518060400160405280600c81526020017f312e302e302d626574612e31000000000000000000000000000000000000000081525081565b34801561021657600080fd5b5061014c6102253660046108f4565b60006020819052908152604090205481565b34801561024357600080fd5b506100f7610700565b34801561025857600080fd5b5061012d610267366004610875565b6107b7565b34801561027857600080fd5b5061014c61028736600461090f565b600160209081526000928352604080842090915290825290205481565b33600090815260208190526040812080543492906102c3908490610971565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b606073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663d84447156040518163ffffffff1660e01b8152600401600060405180830381865afa158015610360573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103a691908101906109b8565b6040516020016103b69190610a83565b604051602081830303815290604052905090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906104329086815260200190565b60405180910390a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081205482111561047557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104eb575073ffffffffffffffffffffffffffffffffffffffff841660009081526001602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105735773ffffffffffffffffffffffffffffffffffffffff8416600090815260016020908152604080832033845290915290205482111561052d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602090815260408083203384529091528120805484929061056d908490610ac8565b90915550505b73ffffffffffffffffffffffffffffffffffffffff8416600090815260208190526040812080548492906105a8908490610ac8565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812080548492906105e2908490610971565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161064891815260200190565b60405180910390a35060019392505050565b3360009081526020819052604090205481111561067657600080fd5b3360009081526020819052604081208054839290610695908490610ac8565b9091555050604051339082156108fc029083906000818181858888f193505050501580156106c7573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b606073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663550fcdc96040518163ffffffff1660e01b8152600401600060405180830381865afa158015610761573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526107a791908101906109b8565b6040516020016103b69190610adf565b60006107c4338484610443565b9392505050565b60005b838110156107e65781810151838201526020016107ce565b838111156107f5576000848401525b50505050565b602081526000825180602084015261081a8160408501602087016107cb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461087057600080fd5b919050565b6000806040838503121561088857600080fd5b6108918361084c565b946020939093013593505050565b6000806000606084860312156108b457600080fd5b6108bd8461084c565b92506108cb6020850161084c565b9150604084013590509250925092565b6000602082840312156108ed57600080fd5b5035919050565b60006020828403121561090657600080fd5b6107c48261084c565b6000806040838503121561092257600080fd5b61092b8361084c565b91506109396020840161084c565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561098457610984610942565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156109ca57600080fd5b815167ffffffffffffffff808211156109e257600080fd5b818401915084601f8301126109f657600080fd5b815181811115610a0857610a08610989565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610a4e57610a4e610989565b81604052828152876020848701011115610a6757600080fd5b610a788360208301602088016107cb565b979650505050505050565b7f5772617070656420000000000000000000000000000000000000000000000000815260008251610abb8160088501602087016107cb565b9190910160080192915050565b600082821015610ada57610ada610942565b500390565b7f5700000000000000000000000000000000000000000000000000000000000000815260008251610b178160018501602087016107cb565b919091016001019291505056fea164736f6c634300080f000a
Deployed Bytecode
0x6080604052600436106100cb5760003560e01c806354fd4d5011610074578063a9059cbb1161004e578063a9059cbb1461024c578063d0e30db0146100da578063dd62ed3e1461026c576100da565b806354fd4d50146101c157806370a082311461020a57806395d89b4114610237576100da565b806323b872dd116100a557806323b872dd1461015a5780632e1a7d4d1461017a578063313ce5671461019a576100da565b806306fdde03146100e2578063095ea7b31461010d57806318160ddd1461013d576100da565b366100da576100d86102a4565b005b6100d86102a4565b3480156100ee57600080fd5b506100f76102ff565b60405161010491906107fb565b60405180910390f35b34801561011957600080fd5b5061012d610128366004610875565b6103ca565b6040519015158152602001610104565b34801561014957600080fd5b50475b604051908152602001610104565b34801561016657600080fd5b5061012d61017536600461089f565b610443565b34801561018657600080fd5b506100d86101953660046108db565b61065a565b3480156101a657600080fd5b506101af601281565b60405160ff9091168152602001610104565b3480156101cd57600080fd5b506100f76040518060400160405280600c81526020017f312e302e302d626574612e31000000000000000000000000000000000000000081525081565b34801561021657600080fd5b5061014c6102253660046108f4565b60006020819052908152604090205481565b34801561024357600080fd5b506100f7610700565b34801561025857600080fd5b5061012d610267366004610875565b6107b7565b34801561027857600080fd5b5061014c61028736600461090f565b600160209081526000928352604080842090915290825290205481565b33600090815260208190526040812080543492906102c3908490610971565b909155505060405134815233907fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c9060200160405180910390a2565b606073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663d84447156040518163ffffffff1660e01b8152600401600060405180830381865afa158015610360573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526103a691908101906109b8565b6040516020016103b69190610a83565b604051602081830303815290604052905090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906104329086815260200190565b60405180910390a350600192915050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604081205482111561047557600080fd5b73ffffffffffffffffffffffffffffffffffffffff841633148015906104eb575073ffffffffffffffffffffffffffffffffffffffff841660009081526001602090815260408083203384529091529020547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14155b156105735773ffffffffffffffffffffffffffffffffffffffff8416600090815260016020908152604080832033845290915290205482111561052d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff841660009081526001602090815260408083203384529091528120805484929061056d908490610ac8565b90915550505b73ffffffffffffffffffffffffffffffffffffffff8416600090815260208190526040812080548492906105a8908490610ac8565b909155505073ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040812080548492906105e2908490610971565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161064891815260200190565b60405180910390a35060019392505050565b3360009081526020819052604090205481111561067657600080fd5b3360009081526020819052604081208054839290610695908490610ac8565b9091555050604051339082156108fc029083906000818181858888f193505050501580156106c7573d6000803e3d6000fd5b5060405181815233907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a250565b606073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff1663550fcdc96040518163ffffffff1660e01b8152600401600060405180830381865afa158015610761573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526107a791908101906109b8565b6040516020016103b69190610adf565b60006107c4338484610443565b9392505050565b60005b838110156107e65781810151838201526020016107ce565b838111156107f5576000848401525b50505050565b602081526000825180602084015261081a8160408501602087016107cb565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461087057600080fd5b919050565b6000806040838503121561088857600080fd5b6108918361084c565b946020939093013593505050565b6000806000606084860312156108b457600080fd5b6108bd8461084c565b92506108cb6020850161084c565b9150604084013590509250925092565b6000602082840312156108ed57600080fd5b5035919050565b60006020828403121561090657600080fd5b6107c48261084c565b6000806040838503121561092257600080fd5b61092b8361084c565b91506109396020840161084c565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561098457610984610942565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156109ca57600080fd5b815167ffffffffffffffff808211156109e257600080fd5b818401915084601f8301126109f657600080fd5b815181811115610a0857610a08610989565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610a4e57610a4e610989565b81604052828152876020848701011115610a6757600080fd5b610a788360208301602088016107cb565b979650505050505050565b7f5772617070656420000000000000000000000000000000000000000000000000815260008251610abb8160088501602087016107cb565b9190910160080192915050565b600082821015610ada57610ada610942565b500390565b7f5700000000000000000000000000000000000000000000000000000000000000815260008251610b178160018501602087016107cb565b919091016001019291505056fea164736f6c634300080f000a
Deployed Bytecode Sourcemap
451:757:3:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1214:9:5;:7;:9::i;:::-;451:757:3;;1308:9:5;:7;:9::i;712:181:3:-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2190:182:5;;;;;;;;;;-1:-1:-1;2190:182:5;;;;;:::i;:::-;;:::i;:::-;;;1349:14:12;;1342:22;1324:41;;1312:2;1297:18;2190:182:5;1184:187:12;2058:100:5;;;;;;;;;;-1:-1:-1;2130:21:5;2058:100;;;1522:25:12;;;1510:2;1495:18;2058:100:5;1376:177:12;2562:452:5;;;;;;;;;;-1:-1:-1;2562:452:5;;;;;:::i;:::-;;:::i;1803:223::-;;;;;;;;;;-1:-1:-1;1803:223:5;;;;;:::i;:::-;;:::i;980:35::-;;;;;;;;;;;;1013:2;980:35;;;;;2248:4:12;2236:17;;;2218:36;;2206:2;2191:18;980:35:5;2076:184:12;526:47:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1022:44:5;;;;;;;;;;-1:-1:-1;1022:44:5;;;;;:::i;:::-;;;;;;;;;;;;;;;1024:182:3;;;;;;;;;;;;;:::i;2404:126:5:-;;;;;;;;;;-1:-1:-1;2404:126:5;;;;;:::i;:::-;;:::i;1072:64::-;;;;;;;;;;-1:-1:-1;1072:64:5;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;1633:138;1695:10;1685:9;:21;;;;;;;;;;:34;;1710:9;;1685;:34;;1710:9;;1685:34;:::i;:::-;;;;-1:-1:-1;;1734:30:5;;1754:9;1522:25:12;;1742:10:5;;1734:30;;1510:2:12;1495:18;1734:30:5;;;;;;;1633:138::o;712:181:3:-;760:19;2827:42:9;825:58:3;;;:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;799:87;;;;;;;;:::i;:::-;;;;;;;;;;;;;791:95;;712:181;:::o;2190:182:5:-;2277:10;2251:4;2267:21;;;:9;:21;;;;;;;;;:26;;;;;;;;;;:32;;;2314:30;2251:4;;2267:26;;2314:30;;;;2296:3;1522:25:12;;1510:2;1495:18;;1376:177;2314:30:5;;;;;;;;-1:-1:-1;2361:4:5;2190:182;;;;:::o;2562:452::-;2663:14;;;2639:4;2663:14;;;;;;;;;;;:21;-1:-1:-1;2663:21:5;2655:30;;;;;;2700:17;;;2707:10;2700:17;;;;:68;;-1:-1:-1;2721:14:5;;;;;;;:9;:14;;;;;;;;2736:10;2721:26;;;;;;;;2751:17;2721:47;;2700:68;2696:188;;;2792:14;;;;;;;:9;:14;;;;;;;;2807:10;2792:26;;;;;;;;:33;-1:-1:-1;2792:33:5;2784:42;;;;;;2840:14;;;;;;;:9;:14;;;;;;;;2855:10;2840:26;;;;;;;:33;;2870:3;;2840:14;:33;;2870:3;;2840:33;:::i;:::-;;;;-1:-1:-1;;2696:188:5;2894:14;;;:9;:14;;;;;;;;;;:21;;2912:3;;2894:9;:21;;2912:3;;2894:21;:::i;:::-;;;;-1:-1:-1;;2925:14:5;;;:9;:14;;;;;;;;;;:21;;2943:3;;2925:9;:21;;2943:3;;2925:21;:::i;:::-;;;;;;;;2976:3;2962:23;;2971:3;2962:23;;;2981:3;2962:23;;;;1522:25:12;;1510:2;1495:18;;1376:177;2962:23:5;;;;;;;;-1:-1:-1;3003:4:5;2562:452;;;;;:::o;1803:223::-;1877:10;1867:9;:21;;;;;;;;;;;:28;-1:-1:-1;1867:28:5;1859:37;;;;;;1916:10;1906:9;:21;;;;;;;;;;:28;;1931:3;;1906:9;:28;;1931:3;;1906:28;:::i;:::-;;;;-1:-1:-1;;1944:33:5;;1952:10;;1944:33;;;;;1973:3;;1944:33;;;;1973:3;1952:10;1944:33;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1992:27:5;;1522:25:12;;;2003:10:5;;1992:27;;1510:2:12;1495:18;1992:27:5;;;;;;;1803:223;:::o;1024:182:3:-;1074:21;2827:42:9;1136:60:3;;;:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1117:82;;;;;;;;:::i;2404:126:5:-;2466:4;2489:34;2502:10;2514:3;2519;2489:12;:34::i;:::-;2482:41;2404:126;-1:-1:-1;;;2404:126:5:o;14:258:12:-;86:1;96:113;110:6;107:1;104:13;96:113;;;186:11;;;180:18;167:11;;;160:39;132:2;125:10;96:113;;;227:6;224:1;221:13;218:48;;;262:1;253:6;248:3;244:16;237:27;218:48;;14:258;;;:::o;277:442::-;426:2;415:9;408:21;389:4;458:6;452:13;501:6;496:2;485:9;481:18;474:34;517:66;576:6;571:2;560:9;556:18;551:2;543:6;539:15;517:66;:::i;:::-;635:2;623:15;640:66;619:88;604:104;;;;710:2;600:113;;277:442;-1:-1:-1;;277:442:12:o;724:196::-;792:20;;852:42;841:54;;831:65;;821:93;;910:1;907;900:12;821:93;724:196;;;:::o;925:254::-;993:6;1001;1054:2;1042:9;1033:7;1029:23;1025:32;1022:52;;;1070:1;1067;1060:12;1022:52;1093:29;1112:9;1093:29;:::i;:::-;1083:39;1169:2;1154:18;;;;1141:32;;-1:-1:-1;;;925:254:12:o;1558:328::-;1635:6;1643;1651;1704:2;1692:9;1683:7;1679:23;1675:32;1672:52;;;1720:1;1717;1710:12;1672:52;1743:29;1762:9;1743:29;:::i;:::-;1733:39;;1791:38;1825:2;1814:9;1810:18;1791:38;:::i;:::-;1781:48;;1876:2;1865:9;1861:18;1848:32;1838:42;;1558:328;;;;;:::o;1891:180::-;1950:6;2003:2;1991:9;1982:7;1978:23;1974:32;1971:52;;;2019:1;2016;2009:12;1971:52;-1:-1:-1;2042:23:12;;1891:180;-1:-1:-1;1891:180:12:o;2265:186::-;2324:6;2377:2;2365:9;2356:7;2352:23;2348:32;2345:52;;;2393:1;2390;2383:12;2345:52;2416:29;2435:9;2416:29;:::i;2456:260::-;2524:6;2532;2585:2;2573:9;2564:7;2560:23;2556:32;2553:52;;;2601:1;2598;2591:12;2553:52;2624:29;2643:9;2624:29;:::i;:::-;2614:39;;2672:38;2706:2;2695:9;2691:18;2672:38;:::i;:::-;2662:48;;2456:260;;;;;:::o;2721:184::-;2773:77;2770:1;2763:88;2870:4;2867:1;2860:15;2894:4;2891:1;2884:15;2910:128;2950:3;2981:1;2977:6;2974:1;2971:13;2968:39;;;2987:18;;:::i;:::-;-1:-1:-1;3023:9:12;;2910:128::o;3043:184::-;3095:77;3092:1;3085:88;3192:4;3189:1;3182:15;3216:4;3213:1;3206:15;3232:943;3312:6;3365:2;3353:9;3344:7;3340:23;3336:32;3333:52;;;3381:1;3378;3371:12;3333:52;3414:9;3408:16;3443:18;3484:2;3476:6;3473:14;3470:34;;;3500:1;3497;3490:12;3470:34;3538:6;3527:9;3523:22;3513:32;;3583:7;3576:4;3572:2;3568:13;3564:27;3554:55;;3605:1;3602;3595:12;3554:55;3634:2;3628:9;3656:2;3652;3649:10;3646:36;;;3662:18;;:::i;:::-;3796:2;3790:9;3858:4;3850:13;;3701:66;3846:22;;;3870:2;3842:31;3838:40;3826:53;;;3894:18;;;3914:22;;;3891:46;3888:72;;;3940:18;;:::i;:::-;3980:10;3976:2;3969:22;4015:2;4007:6;4000:18;4055:7;4050:2;4045;4041;4037:11;4033:20;4030:33;4027:53;;;4076:1;4073;4066:12;4027:53;4089:55;4141:2;4136;4128:6;4124:15;4119:2;4115;4111:11;4089:55;:::i;:::-;4163:6;3232:943;-1:-1:-1;;;;;;;3232:943:12:o;4180:414::-;4431:10;4426:3;4419:23;4401:3;4471:6;4465:13;4487:61;4541:6;4537:1;4532:3;4528:11;4521:4;4513:6;4509:17;4487:61;:::i;:::-;4568:16;;;;4586:1;4564:24;;4180:414;-1:-1:-1;;4180:414:12:o;4599:125::-;4639:4;4667:1;4664;4661:8;4658:34;;;4672:18;;:::i;:::-;-1:-1:-1;4709:9:12;;4599:125::o;4729:407::-;4980:3;4975;4968:16;4950:3;5013:6;5007:13;5029:61;5083:6;5079:1;5074:3;5070:11;5063:4;5055:6;5051:17;5029:61;:::i;:::-;5110:16;;;;5128:1;5106:24;;4729:407;-1:-1:-1;;4729:407:12:o
Swarm Source
none
Loading...
Loading
OVERVIEW
WETH is "wrapped ETH".Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BASE | 83.75% | $2,020.6 | 230,675.0306 | $466,102,987.21 | |
BASE | <0.01% | $2,023.87 | 1.5015 | $3,038.8 | |
BASE | <0.01% | $0.999872 | 38.9553 | $38.95 | |
BASE | <0.01% | $0.001157 | 8,379.14 | $9.69 | |
BASE | <0.01% | $0.00702 | 201.7972 | $1.42 | |
BASE | <0.01% | $1 | 0.7487 | $0.7494 | |
BASE | <0.01% | $2,205.81 | 0.00020242 | $0.4465 | |
BASE | <0.01% | $0.428388 | 1 | $0.4283 | |
BASE | <0.01% | $0.007284 | 21 | $0.1529 | |
BASE | <0.01% | $0.000139 | 1,000 | $0.1387 | |
OP | 13.73% | $2,020.76 | 37,825.6667 | $76,436,493.99 | |
OP | <0.01% | $2,024.17 | 0.0998 | $202.11 | |
OP | <0.01% | $0.999859 | 65.9312 | $65.92 | |
OP | <0.01% | $0.879321 | 72.1404 | $63.43 | |
OP | <0.01% | $0.877791 | 27.6337 | $24.26 | |
OP | <0.01% | $0.904363 | 19.0258 | $17.21 | |
OP | <0.01% | $1 | 15.4765 | $15.48 | |
OP | <0.01% | $85,424 | 0.0000998 | $8.53 | |
SWELL | 1.21% | $2,020.45 | 3,339.053 | $6,746,389.07 | |
UNI | 0.81% | $2,020.72 | 2,228.9778 | $4,504,133.75 | |
WORLD | 0.25% | $2,020.6 | 686.7802 | $1,387,711.03 | |
WORLD | <0.01% | $0.87838 | 52.4869 | $46.1 | |
WORLD | <0.01% | $2,024.01 | 0.014 | $28.35 | |
WORLD | <0.01% | $85,414 | 0.000002 | $0.1708 | |
OPBNB | 0.22% | $626.04 | 1,943.8537 | $1,216,927.78 | |
OPBNB | <0.01% | $625.64 | 0.0036 | $2.25 | |
ETH | 0.02% | $2,021.77 | 49.7108 | $100,503.62 | |
ETH | <0.01% | $2,021.77 | 2.0291 | $4,102.38 | |
ETH | <0.01% | $0.999872 | 6.2973 | $6.3 | |
ARB | <0.01% | $2,020.91 | 1.8279 | $3,693.96 | |
ARB | <0.01% | $2,023.92 | 0.005 | $10.12 | |
BSC | <0.01% | $625.91 | 1.5206 | $951.75 | |
BSC | <0.01% | $2,020.49 | 0.0504 | $101.76 | |
BSC | <0.01% | $1 | 10 | $10 | |
BSC | <0.01% | $626.72 | 0.007505 | $4.7 | |
BSC | <0.01% | $1.06 | 0.2 | $0.2112 | |
ZKSYNC | <0.01% | $2,021.77 | 0.5052 | $1,021.35 | |
TAIKO | <0.01% | $2,021.77 | 0.2227 | $450.18 | |
LINEA | <0.01% | $2,021.77 | 0.1244 | $251.52 | |
SCROLL | <0.01% | $2,021.77 | 0.0871 | $176.18 | |
SONIC | <0.01% | $0.532305 | 236.4946 | $125.89 | |
AVAX | <0.01% | $19.19 | 4.2158 | $80.9 | |
FRAXTAL | <0.01% | $2,017.45 | 0.014 | $28.24 | |
POL | <0.01% | $0.217845 | 57.1062 | $12.44 | |
POL | <0.01% | $2,020.49 | 0.00266218 | $5.38 | |
POL | <0.01% | $1 | 1.03 | $1.03 | |
POL | <0.01% | $177.8 | 0.00328178 | $0.5835 | |
ZKEVM | <0.01% | $2,021.77 | 0.00879758 | $17.79 | |
FTM | <0.01% | $0.5327 | 0.03 | $0.015992 | |
CELO | <0.01% | $0.361264 | 0.0201 | $0.007257 | |
GNO | <0.01% | $1 | 0.0001 | $0.0001 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.