Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
L2ERC721Bridge
Compiler Version
v0.8.15+commit.e14f2714
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
// Contracts
import { ERC721Bridge } from "src/universal/ERC721Bridge.sol";
// Libraries
import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
// Interfaces
import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol";
import { IOptimismMintableERC721 } from "src/universal/interfaces/IOptimismMintableERC721.sol";
import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol";
/// @custom:proxied true
/// @custom:predeploy 0x4200000000000000000000000000000000000014
/// @title L2ERC721Bridge
/// @notice The L2 ERC721 bridge is a contract which works together with the L1 ERC721 bridge to
/// make it possible to transfer ERC721 tokens from Ethereum to Optimism. This contract
/// acts as a minter for new tokens when it hears about deposits into the L1 ERC721 bridge.
/// This contract also acts as a burner for tokens being withdrawn.
/// **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This
/// bridge ONLY supports ERC721s originally deployed on Ethereum. Users will need to
/// wait for the one-week challenge period to elapse before their Optimism-native NFT
/// can be refunded on L2.
contract L2ERC721Bridge is ERC721Bridge, ISemver {
/// @custom:semver 1.7.1-beta.2
string public constant version = "1.7.1-beta.2";
/// @notice Constructs the L2ERC721Bridge contract.
constructor() ERC721Bridge() {
initialize({ _l1ERC721Bridge: payable(address(0)) });
}
/// @notice Initializes the contract.
/// @param _l1ERC721Bridge Address of the ERC721 bridge contract on the other network.
function initialize(address payable _l1ERC721Bridge) public initializer {
__ERC721Bridge_init({
_messenger: ICrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER),
_otherBridge: ERC721Bridge(_l1ERC721Bridge)
});
}
/// @notice Completes an ERC721 bridge from the other domain and sends the ERC721 token to the
/// recipient on this domain.
/// @param _localToken Address of the ERC721 token on this domain.
/// @param _remoteToken Address of the ERC721 token on the other domain.
/// @param _from Address that triggered the bridge on the other domain.
/// @param _to Address to receive the token on this domain.
/// @param _tokenId ID of the token being deposited.
/// @param _extraData Optional data to forward to L1.
/// Data supplied here will not be used to execute any code on L1 and is
/// only emitted as extra data for the convenience of off-chain tooling.
function finalizeBridgeERC721(
address _localToken,
address _remoteToken,
address _from,
address _to,
uint256 _tokenId,
bytes calldata _extraData
)
external
onlyOtherBridge
{
require(_localToken != address(this), "L2ERC721Bridge: local token cannot be self");
// Note that supportsInterface makes a callback to the _localToken address which is user
// provided.
require(
ERC165Checker.supportsInterface(_localToken, type(IOptimismMintableERC721).interfaceId),
"L2ERC721Bridge: local token interface is not compliant"
);
require(
_remoteToken == IOptimismMintableERC721(_localToken).remoteToken(),
"L2ERC721Bridge: wrong remote token for Optimism Mintable ERC721 local token"
);
// When a deposit is finalized, we give the NFT with the same tokenId to the account
// on L2. Note that safeMint makes a callback to the _to address which is user provided.
IOptimismMintableERC721(_localToken).safeMint(_to, _tokenId);
// slither-disable-next-line reentrancy-events
emit ERC721BridgeFinalized(_localToken, _remoteToken, _from, _to, _tokenId, _extraData);
}
/// @inheritdoc ERC721Bridge
function _initiateBridgeERC721(
address _localToken,
address _remoteToken,
address _from,
address _to,
uint256 _tokenId,
uint32 _minGasLimit,
bytes calldata _extraData
)
internal
override
{
require(_remoteToken != address(0), "L2ERC721Bridge: remote token cannot be address(0)");
// Check that the withdrawal is being initiated by the NFT owner
require(
_from == IOptimismMintableERC721(_localToken).ownerOf(_tokenId),
"L2ERC721Bridge: Withdrawal is not being initiated by NFT owner"
);
// Construct calldata for l1ERC721Bridge.finalizeBridgeERC721(_to, _tokenId)
// slither-disable-next-line reentrancy-events
address remoteToken = IOptimismMintableERC721(_localToken).remoteToken();
require(remoteToken == _remoteToken, "L2ERC721Bridge: remote token does not match given value");
// When a withdrawal is initiated, we burn the withdrawer's NFT to prevent subsequent L2
// usage
// slither-disable-next-line reentrancy-events
IOptimismMintableERC721(_localToken).burn(_from, _tokenId);
bytes memory message = abi.encodeWithSelector(
IL1ERC721Bridge.finalizeBridgeERC721.selector, remoteToken, _localToken, _from, _to, _tokenId, _extraData
);
// Send message to L1 bridge
// slither-disable-next-line reentrancy-events
messenger.sendMessage({ _target: address(otherBridge), _message: message, _minGasLimit: _minGasLimit });
// slither-disable-next-line reentrancy-events
emit ERC721BridgeInitiated(_localToken, remoteToken, _from, _to, _tokenId, _extraData);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
/// @title ERC721Bridge
/// @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.
abstract contract ERC721Bridge is Initializable {
/// @custom:spacer ERC721Bridge's initializer slot spacing
/// @notice Spacer to avoid packing into the initializer slot
bytes30 private spacer_0_2_30;
/// @notice Messenger contract on this domain.
/// @custom:network-specific
ICrossDomainMessenger public messenger;
/// @notice Contract of the bridge on the other network.
/// @custom:network-specific
ERC721Bridge public otherBridge;
/// @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.
uint256[46] private __gap;
/// @notice Emitted when an ERC721 bridge to the other network is initiated.
/// @param localToken Address of the token on this domain.
/// @param remoteToken Address of the token on the remote domain.
/// @param from Address that initiated bridging action.
/// @param to Address to receive the token.
/// @param tokenId ID of the specific token deposited.
/// @param extraData Extra data for use on the client-side.
event ERC721BridgeInitiated(
address indexed localToken,
address indexed remoteToken,
address indexed from,
address to,
uint256 tokenId,
bytes extraData
);
/// @notice Emitted when an ERC721 bridge from the other network is finalized.
/// @param localToken Address of the token on this domain.
/// @param remoteToken Address of the token on the remote domain.
/// @param from Address that initiated bridging action.
/// @param to Address to receive the token.
/// @param tokenId ID of the specific token deposited.
/// @param extraData Extra data for use on the client-side.
event ERC721BridgeFinalized(
address indexed localToken,
address indexed remoteToken,
address indexed from,
address to,
uint256 tokenId,
bytes extraData
);
/// @notice Ensures that the caller is a cross-chain message from the other bridge.
modifier onlyOtherBridge() {
require(
msg.sender == address(messenger) && messenger.xDomainMessageSender() == address(otherBridge),
"ERC721Bridge: function can only be called from the other bridge"
);
_;
}
/// @notice Initializer.
/// @param _messenger Contract of the CrossDomainMessenger on this network.
/// @param _otherBridge Contract of the ERC721 bridge on the other network.
function __ERC721Bridge_init(
ICrossDomainMessenger _messenger,
ERC721Bridge _otherBridge
)
internal
onlyInitializing
{
messenger = _messenger;
otherBridge = _otherBridge;
}
/// @notice Legacy getter for messenger contract.
/// Public getter is legacy and will be removed in the future. Use `messenger` instead.
/// @return Messenger contract on this domain.
/// @custom:legacy
function MESSENGER() external view returns (ICrossDomainMessenger) {
return messenger;
}
/// @notice Legacy getter for other bridge address.
/// Public getter is legacy and will be removed in the future. Use `otherBridge` instead.
/// @return Contract of the bridge on the other network.
/// @custom:legacy
function OTHER_BRIDGE() external view returns (ERC721Bridge) {
return otherBridge;
}
/// @notice This function should return true if the contract is paused.
/// On L1 this function will check the SuperchainConfig for its paused status.
/// On L2 this function should be a no-op.
/// @return Whether or not the contract is paused.
function paused() public view virtual returns (bool) {
return false;
}
/// @notice Initiates a bridge of an NFT to the caller's account on the other chain. Note that
/// this function can only be called by EOAs. Smart contract wallets should use the
/// `bridgeERC721To` function after ensuring that the recipient address on the remote
/// chain exists. Also note that the current owner of the token on this chain must
/// approve this contract to operate the NFT before it can be bridged.
/// **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This
/// bridge only supports ERC721s originally deployed on Ethereum. Users will need to
/// wait for the one-week challenge period to elapse before their Optimism-native NFT
/// can be refunded on L2.
/// @param _localToken Address of the ERC721 on this domain.
/// @param _remoteToken Address of the ERC721 on the remote domain.
/// @param _tokenId Token ID to bridge.
/// @param _minGasLimit Minimum gas limit for the bridge message on the other domain.
/// @param _extraData Optional data to forward to the other chain. Data supplied here will not
/// be used to execute any code on the other chain and is only emitted as
/// extra data for the convenience of off-chain tooling.
function bridgeERC721(
address _localToken,
address _remoteToken,
uint256 _tokenId,
uint32 _minGasLimit,
bytes calldata _extraData
)
external
{
// Modifier requiring sender to be EOA. This prevents against a user error that would occur
// if the sender is a smart contract wallet that has a different address on the remote chain
// (or doesn't have an address on the remote chain at all). The user would fail to receive
// the NFT if they use this function because it sends the NFT to the same address as the
// caller. This check could be bypassed by a malicious contract via initcode, but it takes
// care of the user error we want to avoid.
require(!Address.isContract(msg.sender), "ERC721Bridge: account is not externally owned");
_initiateBridgeERC721(_localToken, _remoteToken, msg.sender, msg.sender, _tokenId, _minGasLimit, _extraData);
}
/// @notice Initiates a bridge of an NFT to some recipient's account on the other chain. Note
/// that the current owner of the token on this chain must approve this contract to
/// operate the NFT before it can be bridged.
/// **WARNING**: Do not bridge an ERC721 that was originally deployed on Optimism. This
/// bridge only supports ERC721s originally deployed on Ethereum. Users will need to
/// wait for the one-week challenge period to elapse before their Optimism-native NFT
/// can be refunded on L2.
/// @param _localToken Address of the ERC721 on this domain.
/// @param _remoteToken Address of the ERC721 on the remote domain.
/// @param _to Address to receive the token on the other domain.
/// @param _tokenId Token ID to bridge.
/// @param _minGasLimit Minimum gas limit for the bridge message on the other domain.
/// @param _extraData Optional data to forward to the other chain. Data supplied here will not
/// be used to execute any code on the other chain and is only emitted as
/// extra data for the convenience of off-chain tooling.
function bridgeERC721To(
address _localToken,
address _remoteToken,
address _to,
uint256 _tokenId,
uint32 _minGasLimit,
bytes calldata _extraData
)
external
{
require(_to != address(0), "ERC721Bridge: nft recipient cannot be address(0)");
_initiateBridgeERC721(_localToken, _remoteToken, msg.sender, _to, _tokenId, _minGasLimit, _extraData);
}
/// @notice Internal function for initiating a token bridge to the other domain.
/// @param _localToken Address of the ERC721 on this domain.
/// @param _remoteToken Address of the ERC721 on the remote domain.
/// @param _from Address of the sender on this domain.
/// @param _to Address to receive the token on the other domain.
/// @param _tokenId Token ID to bridge.
/// @param _minGasLimit Minimum gas limit for the bridge message on the other domain.
/// @param _extraData Optional data to forward to the other domain. Data supplied here will
/// not be used to execute any code on the other domain and is only emitted
/// as extra data for the convenience of off-chain tooling.
function _initiateBridgeERC721(
address _localToken,
address _remoteToken,
address _from,
address _to,
uint256 _tokenId,
uint32 _minGasLimit,
bytes calldata _extraData
)
internal
virtual;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.2) (utils/introspection/ERC165Checker.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/
library ERC165Checker {
// As per the EIP-165 spec, no interface should ever match 0xffffffff
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
/**
* @dev Returns true if `account` supports the {IERC165} interface,
*/
function supportsERC165(address account) internal view returns (bool) {
// Any contract that implements ERC165 must explicitly indicate support of
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
return
_supportsERC165Interface(account, type(IERC165).interfaceId) &&
!_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
// query support of both ERC165 as per the spec and support of _interfaceId
return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);
}
/**
* @dev Returns a boolean array where each value corresponds to the
* interfaces passed in and whether they're supported or not. This allows
* you to batch check interfaces for a contract where your expectation
* is that some interfaces may not be supported.
*
* See {IERC165-supportsInterface}.
*
* _Available since v3.4._
*/
function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)
internal
view
returns (bool[] memory)
{
// an array of booleans corresponding to interfaceIds and whether they're supported or not
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
// query support of ERC165 itself
if (supportsERC165(account)) {
// query support of each interface in interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
}
}
return interfaceIdsSupported;
}
/**
* @dev Returns true if `account` supports all the interfaces defined in
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
*
* Batch-querying can lead to gas savings by skipping repeated checks for
* {IERC165} support.
*
* See {IERC165-supportsInterface}.
*/
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
// query support of ERC165 itself
if (!supportsERC165(account)) {
return false;
}
// query support of each interface in _interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
if (!_supportsERC165Interface(account, interfaceIds[i])) {
return false;
}
}
// all interfaces supported
return true;
}
/**
* @notice Query if a contract implements an interface, does not check ERC165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
* Interface identification is specified in ERC-165.
*/
function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
// prepare call
bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);
// perform static call
bool success;
uint256 returnSize;
uint256 returnValue;
assembly {
success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
returnSize := returndatasize()
returnValue := mload(0x00)
}
return success && returnSize >= 0x20 && returnValue > 0;
}
}// 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;
/// @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.0;
import { IERC721Bridge } from "src/universal/interfaces/IERC721Bridge.sol";
import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
interface IL1ERC721Bridge is IERC721Bridge {
function bridgeERC721(
address _localToken,
address _remoteToken,
uint256 _tokenId,
uint32 _minGasLimit,
bytes memory _extraData
)
external;
function bridgeERC721To(
address _localToken,
address _remoteToken,
address _to,
uint256 _tokenId,
uint32 _minGasLimit,
bytes memory _extraData
)
external;
function deposits(address, address, uint256) external view returns (bool);
function finalizeBridgeERC721(
address _localToken,
address _remoteToken,
address _from,
address _to,
uint256 _tokenId,
bytes memory _extraData
)
external;
function initialize(ICrossDomainMessenger _messenger, ISuperchainConfig _superchainConfig) external;
function paused() external view returns (bool);
function superchainConfig() external view returns (ISuperchainConfig);
function version() external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC721Enumerable } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
/// @title IOptimismMintableERC721
/// @notice Interface for contracts that are compatible with the OptimismMintableERC721 standard.
/// Tokens that follow this standard can be easily transferred across the ERC721 bridge.
interface IOptimismMintableERC721 is IERC721Enumerable {
/// @notice Emitted when a token is minted.
/// @param account Address of the account the token was minted to.
/// @param tokenId Token ID of the minted token.
event Mint(address indexed account, uint256 tokenId);
/// @notice Emitted when a token is burned.
/// @param account Address of the account the token was burned from.
/// @param tokenId Token ID of the burned token.
event Burn(address indexed account, uint256 tokenId);
/// @notice Mints some token ID for a user, checking first that contract recipients
/// are aware of the ERC721 protocol to prevent tokens from being forever locked.
/// @param _to Address of the user to mint the token for.
/// @param _tokenId Token ID to mint.
function safeMint(address _to, uint256 _tokenId) external;
/// @notice Burns a token ID from a user.
/// @param _from Address of the user to burn the token from.
/// @param _tokenId Token ID to burn.
function burn(address _from, uint256 _tokenId) external;
/// @notice Chain ID of the chain where the remote token is deployed.
function REMOTE_CHAIN_ID() external view returns (uint256);
/// @notice Address of the token on the remote domain.
function REMOTE_TOKEN() external view returns (address);
/// @notice Address of the ERC721 bridge on this network.
function BRIDGE() external view returns (address);
/// @notice Chain ID of the chain where the remote token is deployed.
function remoteChainId() external view returns (uint256);
/// @notice Address of the token on the remote domain.
function remoteToken() external view returns (address);
/// @notice Address of the ERC721 bridge on this network.
function bridge() external view returns (address);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ICrossDomainMessenger {
event FailedRelayedMessage(bytes32 indexed msgHash);
event Initialized(uint8 version);
event RelayedMessage(bytes32 indexed msgHash);
event SentMessage(address indexed target, address sender, bytes message, uint256 messageNonce, uint256 gasLimit);
event SentMessageExtension1(address indexed sender, uint256 value);
function MESSAGE_VERSION() external view returns (uint16);
function MIN_GAS_CALLDATA_OVERHEAD() external view returns (uint64);
function MIN_GAS_DYNAMIC_OVERHEAD_DENOMINATOR() external view returns (uint64);
function MIN_GAS_DYNAMIC_OVERHEAD_NUMERATOR() external view returns (uint64);
function OTHER_MESSENGER() external view returns (ICrossDomainMessenger);
function RELAY_CALL_OVERHEAD() external view returns (uint64);
function RELAY_CONSTANT_OVERHEAD() external view returns (uint64);
function RELAY_GAS_CHECK_BUFFER() external view returns (uint64);
function RELAY_RESERVED_GAS() external view returns (uint64);
function baseGas(bytes memory _message, uint32 _minGasLimit) external pure returns (uint64);
function failedMessages(bytes32) external view returns (bool);
function messageNonce() external view returns (uint256);
function otherMessenger() external view returns (ICrossDomainMessenger);
function paused() external view returns (bool);
function relayMessage(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _minGasLimit,
bytes memory _message
)
external
payable;
function sendMessage(address _target, bytes memory _message, uint32 _minGasLimit) external payable;
function successfulMessages(bytes32) external view returns (bool);
function xDomainMessageSender() external view returns (address);
}// 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
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/Address.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original
* initialization step. This is essential to configure modules that are added through upgrades and that require
* initialization.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized < type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// 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;
import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol";
interface IERC721Bridge {
event ERC721BridgeFinalized(
address indexed localToken,
address indexed remoteToken,
address indexed from,
address to,
uint256 tokenId,
bytes extraData
);
event ERC721BridgeInitiated(
address indexed localToken,
address indexed remoteToken,
address indexed from,
address to,
uint256 tokenId,
bytes extraData
);
event Initialized(uint8 version);
function MESSENGER() external view returns (ICrossDomainMessenger);
function OTHER_BRIDGE() external view returns (IERC721Bridge);
function bridgeERC721(
address _localToken,
address _remoteToken,
uint256 _tokenId,
uint32 _minGasLimit,
bytes memory _extraData
)
external;
function bridgeERC721To(
address _localToken,
address _remoteToken,
address _to,
uint256 _tokenId,
uint32 _minGasLimit,
bytes memory _extraData
)
external;
function messenger() external view returns (ICrossDomainMessenger);
function otherBridge() external view returns (IERC721Bridge);
function paused() external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ISuperchainConfig {
enum UpdateType {
GUARDIAN
}
event ConfigUpdate(UpdateType indexed updateType, bytes data);
event Initialized(uint8 version);
event Paused(string identifier);
event Unpaused();
function GUARDIAN_SLOT() external view returns (bytes32);
function PAUSED_SLOT() external view returns (bytes32);
function guardian() external view returns (address guardian_);
function initialize(address _guardian, bool _paused) external;
function pause(string memory _identifier) external;
function paused() external view returns (bool paused_);
function unpause() external;
function version() external view returns (string memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}{
"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[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"localToken","type":"address"},{"indexed":true,"internalType":"address","name":"remoteToken","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ERC721BridgeFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"localToken","type":"address"},{"indexed":true,"internalType":"address","name":"remoteToken","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"ERC721BridgeInitiated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"inputs":[],"name":"MESSENGER","outputs":[{"internalType":"contract ICrossDomainMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OTHER_BRIDGE","outputs":[{"internalType":"contract ERC721Bridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_localToken","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_localToken","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint32","name":"_minGasLimit","type":"uint32"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"bridgeERC721To","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_localToken","type":"address"},{"internalType":"address","name":"_remoteToken","type":"address"},{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_extraData","type":"bytes"}],"name":"finalizeBridgeERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_l1ERC721Bridge","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"messenger","outputs":[{"internalType":"contract ICrossDomainMessenger","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"otherBridge","outputs":[{"internalType":"contract ERC721Bridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50600436106100be5760003560e01c80637f46ddb211610076578063aa5574521161005b578063aa557452146101c9578063c4d66de8146101dc578063c89701a2146101ef57600080fd5b80637f46ddb21461018d578063927ede2d146101ab57600080fd5b806354fd4d50116100a757806354fd4d50146101225780635c975abb1461016b578063761f44931461017a57600080fd5b80633687011a146100c35780633cb747bf146100d8575b600080fd5b6100d66100d136600461128a565b61020f565b005b6001546100f89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61015e6040518060400160405280600c81526020017f312e372e312d626574612e32000000000000000000000000000000000000000081525081565b6040516101199190611378565b60405160008152602001610119565b6100d661018836600461138b565b6102bb565b60025473ffffffffffffffffffffffffffffffffffffffff166100f8565b60015473ffffffffffffffffffffffffffffffffffffffff166100f8565b6100d66101d7366004611423565b6107d9565b6100d66101ea36600461149a565b610895565b6002546100f89073ffffffffffffffffffffffffffffffffffffffff1681565b333b156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102b38686333388888888610a5a565b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156103905750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa158015610354573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037891906114b7565b73ffffffffffffffffffffffffffffffffffffffff16145b61041c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161029a565b3073ffffffffffffffffffffffffffffffffffffffff8816036104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161029a565b6104eb877f74259ebf00000000000000000000000000000000000000000000000000000000610fc2565b610577576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e20696e746560448201527f7266616365206973206e6f7420636f6d706c69616e7400000000000000000000606482015260840161029a565b8673ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e691906114b7565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146106c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324552433732314272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433732312060648201527f6c6f63616c20746f6b656e000000000000000000000000000000000000000000608482015260a40161029a565b6040517fa144819400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063a144819490604401600060405180830381600087803b15801561073657600080fd5b505af115801561074a573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107c8949392919061151d565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff851661087c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161029a565b61088c8787338888888888610a5a565b50505050505050565b600054610100900460ff16158080156108b55750600054600160ff909116105b806108cf5750303b1580156108cf575060005460ff166001145b61095b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161029a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156109b957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6109d773420000000000000000000000000000000000000783610fe5565b8015610a3a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161029a565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e90602401602060405180830381865afa158015610b68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8c91906114b7565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610c46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324552433732314272696467653a205769746864726177616c206973206e6f60448201527f74206265696e6720696e69746961746564206279204e4654206f776e65720000606482015260840161029a565b60008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb791906114b7565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c7565000000000000000000606482015260840161029a565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790528a1690639dc29fac90604401600060405180830381600087803b158015610de457600080fd5b505af1158015610df8573d6000803e3d6000fd5b50505050600063761f449360e01b828b8a8a8a8989604051602401610e23979695949392919061155d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925260015460025492517f3dbb202b00000000000000000000000000000000000000000000000000000000815291935073ffffffffffffffffffffffffffffffffffffffff90811692633dbb202b92610f0292919091169085908a906004016115ba565b600060405180830381600087803b158015610f1c57600080fd5b505af1158015610f30573d6000803e3d6000fd5b505050508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610fae949392919061151d565b60405180910390a450505050505050505050565b6000610fcd836110cf565b8015610fde5750610fde8383611134565b9392505050565b600054610100900460ff1661107c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161029a565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b60006110fb827f01ffc9a700000000000000000000000000000000000000000000000000000000611134565b801561112e575061112c827fffffffff00000000000000000000000000000000000000000000000000000000611134565b155b92915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156111ec575060208210155b80156111f85750600081115b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461122557600080fd5b50565b803563ffffffff8116811461123c57600080fd5b919050565b60008083601f84011261125357600080fd5b50813567ffffffffffffffff81111561126b57600080fd5b60208301915083602082850101111561128357600080fd5b9250929050565b60008060008060008060a087890312156112a357600080fd5b86356112ae81611203565b955060208701356112be81611203565b9450604087013593506112d360608801611228565b9250608087013567ffffffffffffffff8111156112ef57600080fd5b6112fb89828a01611241565b979a9699509497509295939492505050565b6000815180845260005b8181101561133357602081850181015186830182015201611317565b81811115611345576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610fde602083018461130d565b600080600080600080600060c0888a0312156113a657600080fd5b87356113b181611203565b965060208801356113c181611203565b955060408801356113d181611203565b945060608801356113e181611203565b93506080880135925060a088013567ffffffffffffffff81111561140457600080fd5b6114108a828b01611241565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561143e57600080fd5b873561144981611203565b9650602088013561145981611203565b9550604088013561146981611203565b94506060880135935061147e60808901611228565b925060a088013567ffffffffffffffff81111561140457600080fd5b6000602082840312156114ac57600080fd5b8135610fde81611203565b6000602082840312156114c957600080fd5b8151610fde81611203565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006115536060830184866114d4565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a08301526115ad60c0830184866114d4565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006115e9606083018561130d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100be5760003560e01c80637f46ddb211610076578063aa5574521161005b578063aa557452146101c9578063c4d66de8146101dc578063c89701a2146101ef57600080fd5b80637f46ddb21461018d578063927ede2d146101ab57600080fd5b806354fd4d50116100a757806354fd4d50146101225780635c975abb1461016b578063761f44931461017a57600080fd5b80633687011a146100c35780633cb747bf146100d8575b600080fd5b6100d66100d136600461128a565b61020f565b005b6001546100f89073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61015e6040518060400160405280600c81526020017f312e372e312d626574612e32000000000000000000000000000000000000000081525081565b6040516101199190611378565b60405160008152602001610119565b6100d661018836600461138b565b6102bb565b60025473ffffffffffffffffffffffffffffffffffffffff166100f8565b60015473ffffffffffffffffffffffffffffffffffffffff166100f8565b6100d66101d7366004611423565b6107d9565b6100d66101ea36600461149a565b610895565b6002546100f89073ffffffffffffffffffffffffffffffffffffffff1681565b333b156102a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f4552433732314272696467653a206163636f756e74206973206e6f742065787460448201527f65726e616c6c79206f776e65640000000000000000000000000000000000000060648201526084015b60405180910390fd5b6102b38686333388888888610a5a565b505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331480156103905750600254600154604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9384169390921691636e296e45916004808201926020929091908290030181865afa158015610354573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037891906114b7565b73ffffffffffffffffffffffffffffffffffffffff16145b61041c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603f60248201527f4552433732314272696467653a2066756e6374696f6e2063616e206f6e6c792060448201527f62652063616c6c65642066726f6d20746865206f746865722062726964676500606482015260840161029a565b3073ffffffffffffffffffffffffffffffffffffffff8816036104c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e2063616e6e60448201527f6f742062652073656c6600000000000000000000000000000000000000000000606482015260840161029a565b6104eb877f74259ebf00000000000000000000000000000000000000000000000000000000610fc2565b610577576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c324552433732314272696467653a206c6f63616c20746f6b656e20696e746560448201527f7266616365206973206e6f7420636f6d706c69616e7400000000000000000000606482015260840161029a565b8673ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e691906114b7565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146106c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604b60248201527f4c324552433732314272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433732312060648201527f6c6f63616c20746f6b656e000000000000000000000000000000000000000000608482015260a40161029a565b6040517fa144819400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301526024820185905288169063a144819490604401600060405180830381600087803b15801561073657600080fd5b505af115801561074a573d6000803e3d6000fd5b505050508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f1f39bf6707b5d608453e0ae4c067b562bcc4c85c0f562ef5d2c774d2e7f131ac878787876040516107c8949392919061151d565b60405180910390a450505050505050565b73ffffffffffffffffffffffffffffffffffffffff851661087c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f4552433732314272696467653a206e667420726563697069656e742063616e6e60448201527f6f74206265206164647265737328302900000000000000000000000000000000606482015260840161029a565b61088c8787338888888888610a5a565b50505050505050565b600054610100900460ff16158080156108b55750600054600160ff909116105b806108cf5750303b1580156108cf575060005460ff166001145b61095b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840161029a565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156109b957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b6109d773420000000000000000000000000000000000000783610fe5565b8015610a3a57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b73ffffffffffffffffffffffffffffffffffffffff8716610afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e2063616e60448201527f6e6f742062652061646472657373283029000000000000000000000000000000606482015260840161029a565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff891690636352211e90602401602060405180830381865afa158015610b68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8c91906114b7565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610c46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f4c324552433732314272696467653a205769746864726177616c206973206e6f60448201527f74206265696e6720696e69746961746564206279204e4654206f776e65720000606482015260840161029a565b60008873ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb791906114b7565b90508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610d74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c324552433732314272696467653a2072656d6f746520746f6b656e20646f6560448201527f73206e6f74206d6174636820676976656e2076616c7565000000000000000000606482015260840161029a565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152602482018790528a1690639dc29fac90604401600060405180830381600087803b158015610de457600080fd5b505af1158015610df8573d6000803e3d6000fd5b50505050600063761f449360e01b828b8a8a8a8989604051602401610e23979695949392919061155d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925260015460025492517f3dbb202b00000000000000000000000000000000000000000000000000000000815291935073ffffffffffffffffffffffffffffffffffffffff90811692633dbb202b92610f0292919091169085908a906004016115ba565b600060405180830381600087803b158015610f1c57600080fd5b505af1158015610f30573d6000803e3d6000fd5b505050508773ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167fb7460e2a880f256ebef3406116ff3eee0cee51ebccdc2a40698f87ebb2e9c1a58a8a8989604051610fae949392919061151d565b60405180910390a450505050505050505050565b6000610fcd836110cf565b8015610fde5750610fde8383611134565b9392505050565b600054610100900460ff1661107c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840161029a565b6001805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560028054929093169116179055565b60006110fb827f01ffc9a700000000000000000000000000000000000000000000000000000000611134565b801561112e575061112c827fffffffff00000000000000000000000000000000000000000000000000000000611134565b155b92915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d915060005190508280156111ec575060208210155b80156111f85750600081115b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461122557600080fd5b50565b803563ffffffff8116811461123c57600080fd5b919050565b60008083601f84011261125357600080fd5b50813567ffffffffffffffff81111561126b57600080fd5b60208301915083602082850101111561128357600080fd5b9250929050565b60008060008060008060a087890312156112a357600080fd5b86356112ae81611203565b955060208701356112be81611203565b9450604087013593506112d360608801611228565b9250608087013567ffffffffffffffff8111156112ef57600080fd5b6112fb89828a01611241565b979a9699509497509295939492505050565b6000815180845260005b8181101561133357602081850181015186830182015201611317565b81811115611345576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610fde602083018461130d565b600080600080600080600060c0888a0312156113a657600080fd5b87356113b181611203565b965060208801356113c181611203565b955060408801356113d181611203565b945060608801356113e181611203565b93506080880135925060a088013567ffffffffffffffff81111561140457600080fd5b6114108a828b01611241565b989b979a50959850939692959293505050565b600080600080600080600060c0888a03121561143e57600080fd5b873561144981611203565b9650602088013561145981611203565b9550604088013561146981611203565b94506060880135935061147e60808901611228565b925060a088013567ffffffffffffffff81111561140457600080fd5b6000602082840312156114ac57600080fd5b8135610fde81611203565b6000602082840312156114c957600080fd5b8151610fde81611203565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff851681528360208201526060604082015260006115536060830184866114d4565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808a1683528089166020840152808816604084015280871660608401525084608083015260c060a08301526115ad60c0830184866114d4565b9998505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006115e9606083018561130d565b905063ffffffff8316604083015294935050505056fea164736f6c634300080f000a
Deployed Bytecode Sourcemap
1502:4521:9:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5567:971:12;;;;;;:::i;:::-;;:::i;:::-;;711:38;;;;;;;;;;;;1731:42:17;1719:55;;;1701:74;;1689:2;1674:18;711:38:12;;;;;;;;1593:47:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;4118:82:12:-;;;4165:4;2687:41:17;;2675:2;2660:18;4118:82:12;2547:187:17;2969:1275:9;;;;;;:::i;:::-;;:::i;3739:96:12:-;3817:11;;;;3739:96;;3391:100;3475:9;;;;3391:100;;7764:428;;;;;;:::i;:::-;;:::i;1940:262:9:-;;;;;;:::i;:::-;;:::i;850:31:12:-;;;;;;;;;5567:971;6351:10;1465:19:3;:23;6323:89:12;;;;;;;5470:2:17;6323:89:12;;;5452:21:17;5509:2;5489:18;;;5482:30;5548:34;5528:18;;;5521:62;5619:15;5599:18;;;5592:43;5652:19;;6323:89:12;;;;;;;;;6423:108;6445:11;6458:12;6472:10;6484;6496:8;6506:12;6520:10;;6423:21;:108::i;:::-;5567:971;;;;;;:::o;2969:1275:9:-;2550:9:12;;;;2528:10;:32;:92;;;;-1:-1:-1;2608:11:12;;;2564:9;:32;;;;;;;;2608:11;;;;;2564:9;;;;:30;;:32;;;;;;;;;;;;;;;:9;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:56;;;2528:92;2507:202;;;;;;;6140:2:17;2507:202:12;;;6122:21:17;6179:2;6159:18;;;6152:30;6218:34;6198:18;;;6191:62;6289:33;6269:18;;;6262:61;6340:19;;2507:202:12;5938:427:17;2507:202:12;3255:4:9::1;3232:28;::::0;::::1;::::0;3224:83:::1;;;::::0;::::1;::::0;;6572:2:17;3224:83:9::1;::::0;::::1;6554:21:17::0;6611:2;6591:18;;;6584:30;6650:34;6630:18;;;6623:62;6721:12;6701:18;;;6694:40;6751:19;;3224:83:9::1;6370:406:17::0;3224:83:9::1;3457:87;3489:11;3502:41;3457:31;:87::i;:::-;3436:188;;;::::0;::::1;::::0;;6983:2:17;3436:188:9::1;::::0;::::1;6965:21:17::0;7022:2;7002:18;;;6995:30;7061:34;7041:18;;;7034:62;7132:24;7112:18;;;7105:52;7174:19;;3436:188:9::1;6781:418:17::0;3436:188:9::1;3696:11;3672:48;;;:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3656:66;;:12;:66;;;3635:188;;;::::0;::::1;::::0;;7406:2:17;3635:188:9::1;::::0;::::1;7388:21:17::0;7445:2;7425:18;;;7418:30;7484:34;7464:18;;;7457:62;7555:34;7535:18;;;7528:62;7627:13;7606:19;;;7599:42;7658:19;;3635:188:9::1;7204:479:17::0;3635:188:9::1;4024:60;::::0;;;;:45:::1;7880:55:17::0;;;4024:60:9::1;::::0;::::1;7862:74:17::0;7952:18;;;7945:34;;;4024:45:9;::::1;::::0;::::1;::::0;7835:18:17;;4024:60:9::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;4204:5;4155:82;;4190:12;4155:82;;4177:11;4155:82;;;4211:3;4216:8;4226:10;;4155:82;;;;;;;;;:::i;:::-;;;;;;;;2969:1275:::0;;;;;;;:::o;7764:428:12:-;8003:17;;;7995:78;;;;;;;8962:2:17;7995:78:12;;;8944:21:17;9001:2;8981:18;;;8974:30;9040:34;9020:18;;;9013:62;9111:18;9091;;;9084:46;9147:19;;7995:78:12;8760:412:17;7995:78:12;8084:101;8106:11;8119:12;8133:10;8145:3;8150:8;8160:12;8174:10;;8084:21;:101::i;:::-;7764:428;;;;;;;:::o;1940:262:9:-;3100:19:0;3123:13;;;;;;3122:14;;3168:34;;;;-1:-1:-1;3186:12:0;;3201:1;3186:12;;;;:16;3168:34;3167:97;;;-1:-1:-1;3236:4:0;1465:19:3;:23;;;3208:55:0;;-1:-1:-1;3246:12:0;;;;;:17;3208:55;3146:190;;;;;;;9379:2:17;3146:190:0;;;9361:21:17;9418:2;9398:18;;;9391:30;9457:34;9437:18;;;9430:62;9528:16;9508:18;;;9501:44;9562:19;;3146:190:0;9177:410:17;3146:190:0;3346:12;:16;;;;3361:1;3346:16;;;3372:65;;;;3406:13;:20;;;;;;;;3372:65;2022:173:9::1;1491:42:11;2168:15:9;2022:19;:173::i;:::-;3461:14:0::0;3457:99;;;3507:5;3491:21;;;;;;3531:14;;-1:-1:-1;9744:36:17;;3531:14:0;;9732:2:17;9717:18;3531:14:0;;;;;;;3457:99;3090:472;1940:262:9;:::o;1175:320:3:-;1465:19;;;:23;;;1175:320::o;4283:1738:9:-;4569:26;;;4561:88;;;;;;;9993:2:17;4561:88:9;;;9975:21:17;10032:2;10012:18;;;10005:30;10071:34;10051:18;;;10044:62;10142:19;10122:18;;;10115:47;10179:19;;4561:88:9;9791:413:17;4561:88:9;4763:54;;;;;;;;10355:25:17;;;4763:44:9;;;;;;10328:18:17;;4763:54:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4754:63;;:5;:63;;;4733:172;;;;;;;10593:2:17;4733:172:9;;;10575:21:17;10632:2;10612:18;;;10605:30;10671:34;10651:18;;;10644:62;10742:32;10722:18;;;10715:60;10792:19;;4733:172:9;10391:426:17;4733:172:9;5056:19;5102:11;5078:48;;;:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5056:72;;5161:12;5146:27;;:11;:27;;;5138:95;;;;;;;11024:2:17;5138:95:9;;;11006:21:17;11063:2;11043:18;;;11036:30;11102:34;11082:18;;;11075:62;11173:25;11153:18;;;11146:53;11216:19;;5138:95:9;10822:419:17;5138:95:9;5413:58;;;;;:41;7880:55:17;;;5413:58:9;;;7862:74:17;7952:18;;;7945:34;;;5413:41:9;;;;;7835:18:17;;5413:58:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5482:20;5541:45;;;5588:11;5601;5614:5;5621:3;5626:8;5636:10;;5505:151;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5759:9;;5800:11;;5759:103;;;;;5505:151;;-1:-1:-1;5759:9:9;;;;;:21;;:103;;5800:11;;;;;5505:151;;5847:12;;5759:103;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5981:5;5933:81;;5968:11;5933:81;;5955:11;5933:81;;;5988:3;5993:8;6003:10;;5933:81;;;;;;;;;:::i;:::-;;;;;;;;4551:1470;;4283:1738;;;;;;;;:::o;1333:274:4:-;1420:4;1527:23;1542:7;1527:14;:23::i;:::-;:73;;;;;1554:46;1579:7;1588:11;1554:24;:46::i;:::-;1520:80;1333:274;-1:-1:-1;;;1333:274:4:o;2924:233:12:-;4888:13:0;;;;;;;4880:69;;;;;;;12582:2:17;4880:69:0;;;12564:21:17;12621:2;12601:18;;;12594:30;12660:34;12640:18;;;12633:62;12731:13;12711:18;;;12704:41;12762:19;;4880:69:0;12380:407:17;4880:69:0;3092:9:12::1;:22:::0;;::::1;::::0;;::::1;::::0;;;::::1;;::::0;;;3124:11:::1;:26:::0;;;;;::::1;::::0;::::1;;::::0;;2924:233::o;704:411:4:-;768:4;975:60;1000:7;1009:25;975:24;:60::i;:::-;:133;;;;-1:-1:-1;1052:56:4;1077:7;1086:21;1052:24;:56::i;:::-;1051:57;975:133;956:152;704:411;-1:-1:-1;;704:411:4:o;4223:638::-;4385:71;;;12966:66:17;12954:79;;4385:71:4;;;;12936:98:17;;;;4385:71:4;;;;;;;;;;12909:18:17;;;;4385:71:4;;;;;;;;;;;4408:34;4385:71;;;4664:20;;4316:4;;4385:71;4316:4;;;;;;4385:71;4316:4;;4664:20;4629:7;4622:5;4611:86;4600:97;;4724:16;4710:30;;4774:4;4768:11;4753:26;;4806:7;:29;;;;;4831:4;4817:10;:18;;4806:29;:48;;;;;4853:1;4839:11;:15;4806:48;4799:55;4223:638;-1:-1:-1;;;;;;;4223:638:4:o;14:154:17:-;100:42;93:5;89:54;82:5;79:65;69:93;;158:1;155;148:12;69:93;14:154;:::o;173:163::-;240:20;;300:10;289:22;;279:33;;269:61;;326:1;323;316:12;269:61;173:163;;;:::o;341:347::-;392:8;402:6;456:3;449:4;441:6;437:17;433:27;423:55;;474:1;471;464:12;423:55;-1:-1:-1;497:20:17;;540:18;529:30;;526:50;;;572:1;569;562:12;526:50;609:4;601:6;597:17;585:29;;661:3;654:4;645:6;637;633:19;629:30;626:39;623:59;;;678:1;675;668:12;623:59;341:347;;;;;:::o;693:827::-;798:6;806;814;822;830;838;891:3;879:9;870:7;866:23;862:33;859:53;;;908:1;905;898:12;859:53;947:9;934:23;966:31;991:5;966:31;:::i;:::-;1016:5;-1:-1:-1;1073:2:17;1058:18;;1045:32;1086:33;1045:32;1086:33;:::i;:::-;1138:7;-1:-1:-1;1192:2:17;1177:18;;1164:32;;-1:-1:-1;1215:37:17;1248:2;1233:18;;1215:37;:::i;:::-;1205:47;;1303:3;1292:9;1288:19;1275:33;1331:18;1323:6;1320:30;1317:50;;;1363:1;1360;1353:12;1317:50;1402:58;1452:7;1443:6;1432:9;1428:22;1402:58;:::i;:::-;693:827;;;;-1:-1:-1;693:827:17;;-1:-1:-1;693:827:17;;1479:8;;693:827;-1:-1:-1;;;693:827:17:o;1786:531::-;1828:3;1866:5;1860:12;1893:6;1888:3;1881:19;1918:1;1928:162;1942:6;1939:1;1936:13;1928:162;;;2004:4;2060:13;;;2056:22;;2050:29;2032:11;;;2028:20;;2021:59;1957:12;1928:162;;;2108:6;2105:1;2102:13;2099:87;;;2174:1;2167:4;2158:6;2153:3;2149:16;2145:27;2138:38;2099:87;-1:-1:-1;2231:2:17;2219:15;2236:66;2215:88;2206:98;;;;2306:4;2202:109;;1786:531;-1:-1:-1;;1786:531:17:o;2322:220::-;2471:2;2460:9;2453:21;2434:4;2491:45;2532:2;2521:9;2517:18;2509:6;2491:45;:::i;2739:1038::-;2854:6;2862;2870;2878;2886;2894;2902;2955:3;2943:9;2934:7;2930:23;2926:33;2923:53;;;2972:1;2969;2962:12;2923:53;3011:9;2998:23;3030:31;3055:5;3030:31;:::i;:::-;3080:5;-1:-1:-1;3137:2:17;3122:18;;3109:32;3150:33;3109:32;3150:33;:::i;:::-;3202:7;-1:-1:-1;3261:2:17;3246:18;;3233:32;3274:33;3233:32;3274:33;:::i;:::-;3326:7;-1:-1:-1;3385:2:17;3370:18;;3357:32;3398:33;3357:32;3398:33;:::i;:::-;3450:7;-1:-1:-1;3504:3:17;3489:19;;3476:33;;-1:-1:-1;3560:3:17;3545:19;;3532:33;3588:18;3577:30;;3574:50;;;3620:1;3617;3610:12;3574:50;3659:58;3709:7;3700:6;3689:9;3685:22;3659:58;:::i;:::-;2739:1038;;;;-1:-1:-1;2739:1038:17;;-1:-1:-1;2739:1038:17;;;;3633:84;;-1:-1:-1;;;2739:1038:17:o;4034:969::-;4148:6;4156;4164;4172;4180;4188;4196;4249:3;4237:9;4228:7;4224:23;4220:33;4217:53;;;4266:1;4263;4256:12;4217:53;4305:9;4292:23;4324:31;4349:5;4324:31;:::i;:::-;4374:5;-1:-1:-1;4431:2:17;4416:18;;4403:32;4444:33;4403:32;4444:33;:::i;:::-;4496:7;-1:-1:-1;4555:2:17;4540:18;;4527:32;4568:33;4527:32;4568:33;:::i;:::-;4620:7;-1:-1:-1;4674:2:17;4659:18;;4646:32;;-1:-1:-1;4697:38:17;4730:3;4715:19;;4697:38;:::i;:::-;4687:48;;4786:3;4775:9;4771:19;4758:33;4814:18;4806:6;4803:30;4800:50;;;4846:1;4843;4836:12;5008:255;5075:6;5128:2;5116:9;5107:7;5103:23;5099:32;5096:52;;;5144:1;5141;5134:12;5096:52;5183:9;5170:23;5202:31;5227:5;5202:31;:::i;5682:251::-;5752:6;5805:2;5793:9;5784:7;5780:23;5776:32;5773:52;;;5821:1;5818;5811:12;5773:52;5853:9;5847:16;5872:31;5897:5;5872:31;:::i;7990:325::-;8078:6;8073:3;8066:19;8130:6;8123:5;8116:4;8111:3;8107:14;8094:43;;8182:1;8175:4;8166:6;8161:3;8157:16;8153:27;8146:38;8048:3;8304:4;8234:66;8229:2;8221:6;8217:15;8213:88;8208:3;8204:98;8200:109;8193:116;;7990:325;;;;:::o;8320:435::-;8545:42;8537:6;8533:55;8522:9;8515:74;8625:6;8620:2;8609:9;8605:18;8598:34;8668:2;8663;8652:9;8648:18;8641:30;8496:4;8688:61;8745:2;8734:9;8730:18;8722:6;8714;8688:61;:::i;:::-;8680:69;8320:435;-1:-1:-1;;;;;;8320:435:17:o;11246:700::-;11506:4;11535:42;11616:2;11608:6;11604:15;11593:9;11586:34;11668:2;11660:6;11656:15;11651:2;11640:9;11636:18;11629:43;11720:2;11712:6;11708:15;11703:2;11692:9;11688:18;11681:43;11772:2;11764:6;11760:15;11755:2;11744:9;11740:18;11733:43;;11813:6;11807:3;11796:9;11792:19;11785:35;11857:3;11851;11840:9;11836:19;11829:32;11878:62;11935:3;11924:9;11920:19;11912:6;11904;11878:62;:::i;:::-;11870:70;11246:700;-1:-1:-1;;;;;;;;;11246:700:17:o;11951:424::-;12164:42;12156:6;12152:55;12141:9;12134:74;12244:2;12239;12228:9;12224:18;12217:30;12115:4;12264:45;12305:2;12294:9;12290:18;12282:6;12264:45;:::i;:::-;12256:53;;12357:10;12349:6;12345:23;12340:2;12329:9;12325:18;12318:51;11951:424;;;;;;:::o
Swarm Source
none
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.