Overview
ETH Balance
ETH Value
$145.29 (@ $1,780.48/ETH)More Info
Private Name Tags
ContractCreator
TokenTracker
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0xd3aeef9c115ccf8d69d8e34005efce25c6bb3ed19dbe0508b44a804e24a65176 | - | (pending) | 2 hrs ago | IN | 0.0003263926 ETH | (Pending) | |||
Transfer Remote | 14377395 | 21 days ago | IN | 0.00017335 ETH | 0.00000973 | ||||
Batch Mint With ... | 14377375 | 21 days ago | IN | 0.00025 ETH | 0.00000738 | ||||
Transfer Remote | 14343632 | 22 days ago | IN | 0.00037337 ETH | 0.00001233 | ||||
Batch Mint With ... | 14343629 | 22 days ago | IN | 0.00025 ETH | 0.0000089 | ||||
Batch Mint With ... | 14343614 | 22 days ago | IN | 0.00025 ETH | 0.00000739 | ||||
Transfer Remote | 14339491 | 22 days ago | IN | 0.00017335 ETH | 0.00001949 | ||||
Mint | 14339485 | 22 days ago | IN | 0.00025 ETH | 0.00001325 | ||||
Transfer Remote | 14339249 | 22 days ago | IN | 0.00037337 ETH | 0.00001752 | ||||
Mint | 14339243 | 22 days ago | IN | 0.00025 ETH | 0.00001193 | ||||
Transfer Remote | 14325876 | 23 days ago | IN | 0.00018428 ETH | 0.00000979 | ||||
Batch Mint With ... | 14325863 | 23 days ago | IN | 0.00025 ETH | 0.00000718 | ||||
Transfer Remote | 14199430 | 30 days ago | IN | 0.00018428 ETH | 0.00001044 | ||||
Mint | 14199421 | 30 days ago | IN | 0.00025 ETH | 0.00000689 | ||||
Mint | 14185312 | 31 days ago | IN | 0.00025 ETH | 0.00001677 | ||||
Transfer Remote | 14176884 | 31 days ago | IN | 0.00018428 ETH | 0.00001222 | ||||
Mint | 14176882 | 31 days ago | IN | 0.00025 ETH | 0.0000083 | ||||
Transfer Remote | 14176838 | 31 days ago | IN | 0.00018428 ETH | 0.00001205 | ||||
Mint | 14176833 | 31 days ago | IN | 0.00025 ETH | 0.00000829 | ||||
Transfer Remote | 14176724 | 31 days ago | IN | 0.00018428 ETH | 0.00001491 | ||||
Mint | 14176712 | 31 days ago | IN | 0.00025 ETH | 0.00001804 | ||||
Mint | 14175892 | 31 days ago | IN | 0.00025 ETH | 0.00000828 | ||||
Transfer Remote | 14107483 | 35 days ago | IN | 0.00018428 ETH | 0.0000124 | ||||
Mint | 14107472 | 35 days ago | IN | 0.00025 ETH | 0.00000659 | ||||
Transfer Remote | 14077963 | 37 days ago | IN | 0.00018428 ETH | 0.0000102 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
14377395 | 21 days ago | 0.00013335 ETH | ||||
14343632 | 22 days ago | 0.00033337 ETH | ||||
14339491 | 22 days ago | 0.00013335 ETH | ||||
14339249 | 22 days ago | 0.00033337 ETH | ||||
14325876 | 23 days ago | 0.00014428 ETH | ||||
14199430 | 30 days ago | 0.00014428 ETH | ||||
14176884 | 31 days ago | 0.00014428 ETH | ||||
14176838 | 31 days ago | 0.00014428 ETH | ||||
14176724 | 31 days ago | 0.00014428 ETH | ||||
14107483 | 35 days ago | 0.00014428 ETH | ||||
14077963 | 37 days ago | 0.00014428 ETH | ||||
14062749 | 37 days ago | 0.00014428 ETH | ||||
14047906 | 38 days ago | 0.00014428 ETH | ||||
13994140 | 41 days ago | 0.00046355 ETH | ||||
13984062 | 42 days ago | 0.00010441 ETH | ||||
13872942 | 47 days ago | 0.00010441 ETH | ||||
13839163 | 49 days ago | 0.00010441 ETH | ||||
13807231 | 50 days ago | 0.00010441 ETH | ||||
13806972 | 50 days ago | 0.00010441 ETH | ||||
13768868 | 52 days ago | 0.00010441 ETH | ||||
13690909 | 55 days ago | 0.00010441 ETH | ||||
13591998 | 60 days ago | 0.00010851 ETH | ||||
13525573 | 63 days ago | 0.00010851 ETH | ||||
13456634 | 66 days ago | 0.00010524 ETH | ||||
13334215 | 71 days ago | 0.00026311 ETH |
Loading...
Loading
Contract Name:
GetMintNFT721
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity =0.8.19; import '@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol'; import '@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol'; import '@openzeppelin/contracts/security/ReentrancyGuard.sol'; import '@openzeppelin/contracts/security/Pausable.sol'; import '@hyperlane-xyz/core/contracts/token/libs/TokenRouter.sol'; import '@hyperlane-xyz/core/contracts/token/libs/TokenMessage.sol'; /** * @author GetMint * @title GetMintNFT721 */ contract GetMintNFT721 is TokenRouter, ERC721Enumerable, Pausable, ReentrancyGuard { event NFTMinted(address indexed minter, uint256 indexed itemId, uint256 feeEarnings, address indexed referrer, uint256 referrerEarnings); event NFTSent(address indexed from, uint32 indexed dstChainId, address indexed receiver, uint256 tokenId, uint256 feeEarned); event NFTReceived(bytes32 indexed srcAddress, uint32 indexed srcChainId, address indexed receiver, uint256 tokenId); event FeeEarningsClaimed(address indexed collector, uint256 claimedAmount); event ReferrerEarningsClaimed(address indexed referrer, uint256 claimedAmount); uint256 public immutable minTokenId; uint256 public immutable maxTokenId; uint256 public tokenCounter; string public _tokenBaseURI; string public _tokenURIExtension; address public feeCollector; uint256 public bridgeFee; uint256 public mintFee; uint256 public feeToCollect; uint256 public claimedFee; uint16 public constant DENOMINATOR = 10000; // 100% uint16 public commonRefBips; mapping(address => uint16) public personalRefBips; mapping(address => uint256) public refTxsCount; mapping(address => uint256) public refAmountToClaim; mapping(address => uint256) public refAmountClaimed; constructor( address _mailbox, address _feeCollector, uint256 _mintFee, uint256 _bridgeFee, uint256 _totalSupply, uint256 _idMultiplier ) ERC721('GetMint', 'GM') TokenRouter(_mailbox) { require(_feeCollector != address(0), 'Fee collector must be non-zero'); feeCollector = _feeCollector; mintFee = _mintFee; bridgeFee = _bridgeFee; minTokenId = _totalSupply * _idMultiplier + 1; maxTokenId = _totalSupply * (_idMultiplier + 1); tokenCounter = _totalSupply * _idMultiplier + 1; } function pause() external onlyOwner whenNotPaused { _pause(); } function unpause() external onlyOwner whenPaused { _unpause(); } function setMintFee(uint256 _mintFee) external onlyOwner { mintFee = _mintFee; } function setBridgeFee(uint256 _bridgeFee) external onlyOwner { bridgeFee = _bridgeFee; } function setFeeCollector(address _feeCollector) external onlyOwner { require(_feeCollector != address(0), 'GetMintNFT721: Fee collector must be non-zero address'); feeCollector = _feeCollector; } function claimFees() external nonReentrant { require(_msgSender() == feeCollector, 'GetMintNFT721: Only fee collector allowed'); uint256 currentEarnings = feeToCollect; require(currentEarnings != 0, 'GetMintNFT721: Nothing to claim'); feeToCollect = 0; claimedFee += currentEarnings; (bool success, ) = payable(feeCollector).call{value: currentEarnings}(''); require(success, 'GetMintNFT721: Failed to send Ether'); emit FeeEarningsClaimed(_msgSender(), currentEarnings); } function mint() external payable nonReentrant whenNotPaused { require(msg.value == mintFee, 'GetMintNFT721: Insufficient mint fee'); uint256 nextId = tokenCounter; require(nextId <= maxTokenId, 'GetMintNFT721: Mint exceeds limit'); ++tokenCounter; feeToCollect += mintFee; _safeMint(_msgSender(), nextId); emit NFTMinted(_msgSender(), nextId, mintFee, address(0), 0); } function batchMint(uint256 count) external payable nonReentrant whenNotPaused { require(msg.value == mintFee * count, 'GetMintNFT721: Insufficient mint fee'); for (uint256 i = 0; i < count; i++) { uint256 nextId = tokenCounter; require(nextId <= maxTokenId, 'GetMintNFT721: Mint exceeds limit'); ++tokenCounter; feeToCollect += mintFee; _safeMint(_msgSender(), nextId); emit NFTMinted(_msgSender(), nextId, mintFee, address(0), 0); } } function mintWithReferrer(address referrer) external payable nonReentrant whenNotPaused { require(_msgSender() != referrer && referrer != address(0), 'GetMintNFT721: Invalid referrer address'); require(msg.value == mintFee, 'GetMintNFT721: Insufficient mint fee'); uint256 nextId = tokenCounter; require(nextId <= maxTokenId, 'GetMintNFT721: Mint exceeds limit'); uint256 fee = mintFee; uint256 refShares = calculateRefShares(referrer, fee); ++tokenCounter; feeToCollect += fee - refShares; refAmountToClaim[referrer] += refShares; ++refTxsCount[referrer]; _safeMint(_msgSender(), nextId); emit NFTMinted(_msgSender(), nextId, mintFee, referrer, refShares); } function batchMintWithReferrer(uint256 count, address referrer) external payable nonReentrant whenNotPaused { require(_msgSender() != referrer && referrer != address(0), 'GetMintNFT721: Invalid referrer address'); require(msg.value == mintFee * count, 'GetMintNFT721: Insufficient mint fee'); for (uint256 i = 0; i < count; i++) { uint256 nextId = tokenCounter; require(nextId <= maxTokenId, 'GetMintNFT721: Mint exceeds limit'); uint256 fee = mintFee; uint256 refShares = calculateRefShares(referrer, fee); ++tokenCounter; feeToCollect += fee - refShares; refAmountToClaim[referrer] += refShares; ++refTxsCount[referrer]; _safeMint(_msgSender(), nextId); emit NFTMinted(_msgSender(), nextId, mintFee, referrer, refShares); } } function transferRemote( uint32 _dstChain, bytes32 _receiver, uint256 _tokenId ) external payable override(TokenRouter) nonReentrant whenNotPaused returns (bytes32 messageId) { require(_receiver != bytes32(0), 'GetMintNFT721: Invalid receiver'); require(_isApprovedOrOwner(_msgSender(), _tokenId), 'GetMintNFT721: send caller is not owner nor approved'); uint256 fee = getHyperlaneMessageFee(_dstChain); require(msg.value >= fee + bridgeFee, 'GetMintNFT721: Incorrect message value'); feeToCollect += bridgeFee; messageId = _transferRemote(_dstChain, _receiver, _tokenId, msg.value - bridgeFee); emit NFTSent(msg.sender, _dstChain, address(uint160(uint256(_receiver))), _tokenId, bridgeFee); } function getHyperlaneMessageFee(uint32 _dstChain) public view returns (uint256) { uint256 fee = _quoteDispatch(_dstChain, ""); return fee; } /////////////// ///// REF ///// /////////////// function setCommonRefBips(uint16 _bips) external onlyOwner { require(_bips <= DENOMINATOR, 'ReferralSystem: Referral bips are too high'); commonRefBips = _bips; } function setPersonalRefBips(address referrer, uint16 bips) external onlyOwner { require(bips <= DENOMINATOR, 'ReferralSystem: Referral bips are too high'); personalRefBips[referrer] = bips; } function setPersonalRefBipsBatch(address[] calldata referrers, uint16 bips) external onlyOwner { require(bips <= DENOMINATOR, 'ReferralSystem: Referral bips are too high'); for (uint256 i = 0; i < referrers.length; i++) { personalRefBips[referrers[i]] = bips; } } function claimRefEarnings() external nonReentrant { uint256 amountToClaim = refAmountToClaim[_msgSender()]; require(amountToClaim > 0, 'Nothing to claim'); address referrer = _msgSender(); refAmountToClaim[referrer] = 0; refAmountClaimed[referrer] += amountToClaim; (bool success, ) = payable(referrer).call{value: amountToClaim}(''); require(success, 'ReferralSystem: Failed to send Ether'); emit ReferrerEarningsClaimed(referrer, amountToClaim); } function calculateRefShares(address referrer, uint256 amount) public view virtual returns (uint256) { uint256 referrerBips = personalRefBips[referrer]; uint256 referrerShareBips = referrerBips == 0 ? commonRefBips : referrerBips; if (referrerShareBips == 0) { return 0; } uint256 referrerEarnings = (amount * referrerShareBips) / DENOMINATOR; return referrerEarnings; } ////////////////// //// override //// ////////////////// function balanceOf(address _account) public view virtual override(TokenRouter, ERC721, IERC721) returns (uint256) { return ERC721.balanceOf(_account); } function _transferFromSender(uint256 _tokenId) internal virtual override returns (bytes memory) { require(ownerOf(_tokenId) == msg.sender, '!owner'); _burn(_tokenId); return bytes(''); // no metadata } function _transferTo( address _recipient, uint256 _tokenId, bytes calldata // no metadata ) internal virtual override { _safeMint(_recipient, _tokenId); } function _contextSuffixLength() internal view override(Context, ContextUpgradeable) returns (uint256) { return 0; } function _msgData() internal view override(Context, ContextUpgradeable) returns (bytes calldata) { return msg.data; } function _msgSender() internal view override(Context, ContextUpgradeable) returns (address) { return msg.sender; } ////////////////////////////// ////////// URI /////////////// ///////////////////////////// function setTokenBaseURI( string calldata _newTokenBaseURI, string calldata _fileExtension ) external onlyOwner { _tokenBaseURI = _newTokenBaseURI; _tokenURIExtension = _fileExtension; } function tokenURI( uint256 tokenId ) public view override returns (string memory) { return string( abi.encodePacked( _tokenBaseURI, Strings.toString(tokenId), _tokenURIExtension ) ); } ////////////////////////////// ////// escape mechanism ////// ////////////////////////////// function resqueFunds() external { require(_msgSender() == feeCollector || _msgSender() == owner(), 'Resque: Only fee collector or owner allowed'); (bool success, ) = payable(msg.sender).call{value: address(this).balance}(''); require(success, 'Resque: Failed to send Ether'); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; import {Router} from "./Router.sol"; import {StandardHookMetadata} from "../hooks/libs/StandardHookMetadata.sol"; abstract contract GasRouter is Router { // ============ Mutable Storage ============ mapping(uint32 => uint256) public destinationGas; struct GasRouterConfig { uint32 domain; uint256 gas; } constructor(address _mailbox) Router(_mailbox) {} /** * @notice Sets the gas amount dispatched for each configured domain. * @param gasConfigs The array of GasRouterConfig structs */ function setDestinationGas( GasRouterConfig[] calldata gasConfigs ) external onlyOwner { for (uint256 i = 0; i < gasConfigs.length; i += 1) { _setDestinationGas(gasConfigs[i].domain, gasConfigs[i].gas); } } /** * @notice Sets the gas amount dispatched for each configured domain. * @param domain The destination domain ID * @param gas The gas limit */ function setDestinationGas(uint32 domain, uint256 gas) external onlyOwner { _setDestinationGas(domain, gas); } /** * @notice Returns the gas payment required to dispatch a message to the given domain's router. * @param _destinationDomain The domain of the router. * @return _gasPayment Payment computed by the registered InterchainGasPaymaster. */ function quoteGasPayment( uint32 _destinationDomain ) external view returns (uint256 _gasPayment) { return _quoteDispatch(_destinationDomain, ""); } function _metadata( uint32 _destination ) internal view virtual override returns (bytes memory) { return StandardHookMetadata.overrideGasLimit(destinationGas[_destination]); } function _setDestinationGas(uint32 domain, uint256 gas) internal { destinationGas[domain] = gas; } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; // ============ Internal Imports ============ import {IMailbox} from "../interfaces/IMailbox.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; import {Message} from "../libs/Message.sol"; // ============ External Imports ============ import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; abstract contract MailboxClient is OwnableUpgradeable { using Message for bytes; IMailbox public immutable mailbox; uint32 public immutable localDomain; IPostDispatchHook public hook; IInterchainSecurityModule public interchainSecurityModule; uint256[48] private __GAP; // gap for upgrade safety // ============ Modifiers ============ modifier onlyContract(address _contract) { require( Address.isContract(_contract), "MailboxClient: invalid mailbox" ); _; } modifier onlyContractOrNull(address _contract) { require( Address.isContract(_contract) || _contract == address(0), "MailboxClient: invalid contract setting" ); _; } /** * @notice Only accept messages from an Hyperlane Mailbox contract */ modifier onlyMailbox() { require( msg.sender == address(mailbox), "MailboxClient: sender not mailbox" ); _; } constructor(address _mailbox) onlyContract(_mailbox) { mailbox = IMailbox(_mailbox); localDomain = mailbox.localDomain(); _transferOwnership(msg.sender); } /** * @notice Sets the address of the application's custom hook. * @param _hook The address of the hook contract. */ function setHook(address _hook) public onlyContractOrNull(_hook) onlyOwner { hook = IPostDispatchHook(_hook); } /** * @notice Sets the address of the application's custom interchain security module. * @param _module The address of the interchain security module contract. */ function setInterchainSecurityModule( address _module ) public onlyContractOrNull(_module) onlyOwner { interchainSecurityModule = IInterchainSecurityModule(_module); } // ======== Initializer ========= function _MailboxClient_initialize( address _hook, address _interchainSecurityModule, address _owner ) internal onlyInitializing { __Ownable_init(); setHook(_hook); setInterchainSecurityModule(_interchainSecurityModule); _transferOwnership(_owner); } function _isLatestDispatched(bytes32 id) internal view returns (bool) { return mailbox.latestDispatchedId() == id; } function _metadata( uint32 /*_destinationDomain*/ ) internal view virtual returns (bytes memory) { return ""; } function _dispatch( uint32 _destinationDomain, bytes32 _recipient, bytes memory _messageBody ) internal virtual returns (bytes32) { return _dispatch(_destinationDomain, _recipient, msg.value, _messageBody); } function _dispatch( uint32 _destinationDomain, bytes32 _recipient, uint256 _value, bytes memory _messageBody ) internal virtual returns (bytes32) { return mailbox.dispatch{value: _value}( _destinationDomain, _recipient, _messageBody, _metadata(_destinationDomain), hook ); } function _quoteDispatch( uint32 _destinationDomain, bytes32 _recipient, bytes memory _messageBody ) internal view virtual returns (uint256) { return mailbox.quoteDispatch( _destinationDomain, _recipient, _messageBody, _metadata(_destinationDomain), hook ); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; // ============ Internal Imports ============ import {IMessageRecipient} from "../interfaces/IMessageRecipient.sol"; import {IPostDispatchHook} from "../interfaces/hooks/IPostDispatchHook.sol"; import {IInterchainSecurityModule} from "../interfaces/IInterchainSecurityModule.sol"; import {MailboxClient} from "./MailboxClient.sol"; import {EnumerableMapExtended} from "../libs/EnumerableMapExtended.sol"; // ============ External Imports ============ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; abstract contract Router is MailboxClient, IMessageRecipient { using EnumerableMapExtended for EnumerableMapExtended.UintToBytes32Map; using Strings for uint32; // ============ Mutable Storage ============ EnumerableMapExtended.UintToBytes32Map internal _routers; uint256[48] private __GAP; // gap for upgrade safety constructor(address _mailbox) MailboxClient(_mailbox) {} // ============ External functions ============ function domains() external view returns (uint32[] memory) { return _routers.uint32Keys(); } /** * @notice Returns the address of the Router contract for the given domain * @param _domain The remote domain ID. * @dev Returns 0 address if no router is enrolled for the given domain * @return router The address of the Router contract for the given domain */ function routers(uint32 _domain) public view virtual returns (bytes32) { (, bytes32 _router) = _routers.tryGet(_domain); return _router; } /** * @notice Unregister the domain * @param _domain The domain of the remote Application Router */ function unenrollRemoteRouter(uint32 _domain) external virtual onlyOwner { _unenrollRemoteRouter(_domain); } /** * @notice Register the address of a Router contract for the same Application on a remote chain * @param _domain The domain of the remote Application Router * @param _router The address of the remote Application Router */ function enrollRemoteRouter( uint32 _domain, bytes32 _router ) external virtual onlyOwner { _enrollRemoteRouter(_domain, _router); } /** * @notice Batch version of `enrollRemoteRouter` * @param _domains The domains of the remote Application Routers * @param _addresses The addresses of the remote Application Routers */ function enrollRemoteRouters( uint32[] calldata _domains, bytes32[] calldata _addresses ) external virtual onlyOwner { require(_domains.length == _addresses.length, "!length"); uint256 length = _domains.length; for (uint256 i = 0; i < length; i += 1) { _enrollRemoteRouter(_domains[i], _addresses[i]); } } /** * @notice Batch version of `unenrollRemoteRouter` * @param _domains The domains of the remote Application Routers */ function unenrollRemoteRouters( uint32[] calldata _domains ) external virtual onlyOwner { uint256 length = _domains.length; for (uint256 i = 0; i < length; i += 1) { _unenrollRemoteRouter(_domains[i]); } } /** * @notice Handles an incoming message * @param _origin The origin domain * @param _sender The sender address * @param _message The message */ function handle( uint32 _origin, bytes32 _sender, bytes calldata _message ) external payable virtual override onlyMailbox { bytes32 _router = _mustHaveRemoteRouter(_origin); require(_router == _sender, "Enrolled router does not match sender"); _handle(_origin, _sender, _message); } // ============ Virtual functions ============ function _handle( uint32 _origin, bytes32 _sender, bytes calldata _message ) internal virtual; // ============ Internal functions ============ /** * @notice Set the router for a given domain * @param _domain The domain * @param _address The new router */ function _enrollRemoteRouter( uint32 _domain, bytes32 _address ) internal virtual { _routers.set(_domain, _address); } /** * @notice Remove the router for a given domain * @param _domain The domain */ function _unenrollRemoteRouter(uint32 _domain) internal virtual { require(_routers.remove(_domain), _domainNotFoundError(_domain)); } /** * @notice Return true if the given domain / router is the address of a remote Application Router * @param _domain The domain of the potential remote Application Router * @param _address The address of the potential remote Application Router */ function _isRemoteRouter( uint32 _domain, bytes32 _address ) internal view returns (bool) { return routers(_domain) == _address; } /** * @notice Assert that the given domain has a Application Router registered and return its address * @param _domain The domain of the chain for which to get the Application Router * @return _router The address of the remote Application Router on _domain */ function _mustHaveRemoteRouter( uint32 _domain ) internal view returns (bytes32) { (bool contained, bytes32 _router) = _routers.tryGet(_domain); require(contained, _domainNotFoundError(_domain)); return _router; } function _domainNotFoundError( uint32 _domain ) internal pure returns (string memory) { return string.concat( "No router enrolled for domain: ", _domain.toString() ); } function _dispatch( uint32 _destinationDomain, bytes memory _messageBody ) internal virtual returns (bytes32) { return _dispatch(_destinationDomain, msg.value, _messageBody); } function _dispatch( uint32 _destinationDomain, uint256 _value, bytes memory _messageBody ) internal virtual returns (bytes32) { bytes32 _router = _mustHaveRemoteRouter(_destinationDomain); return super._dispatch(_destinationDomain, _router, _value, _messageBody); } function _quoteDispatch( uint32 _destinationDomain, bytes memory _messageBody ) internal view virtual returns (uint256) { bytes32 _router = _mustHaveRemoteRouter(_destinationDomain); return super._quoteDispatch(_destinationDomain, _router, _messageBody); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ /** * Format of metadata: * * [0:2] variant * [2:34] msg.value * [34:66] Gas limit for message (IGP) * [66:86] Refund address for message (IGP) * [86:] Custom metadata */ library StandardHookMetadata { struct Metadata { uint16 variant; uint256 msgValue; uint256 gasLimit; address refundAddress; } uint8 private constant VARIANT_OFFSET = 0; uint8 private constant MSG_VALUE_OFFSET = 2; uint8 private constant GAS_LIMIT_OFFSET = 34; uint8 private constant REFUND_ADDRESS_OFFSET = 66; uint256 private constant MIN_METADATA_LENGTH = 86; uint16 public constant VARIANT = 1; /** * @notice Returns the variant of the metadata. * @param _metadata ABI encoded standard hook metadata. * @return variant of the metadata as uint8. */ function variant(bytes calldata _metadata) internal pure returns (uint16) { if (_metadata.length < VARIANT_OFFSET + 2) return 0; return uint16(bytes2(_metadata[VARIANT_OFFSET:VARIANT_OFFSET + 2])); } /** * @notice Returns the specified value for the message. * @param _metadata ABI encoded standard hook metadata. * @param _default Default fallback value. * @return Value for the message as uint256. */ function msgValue( bytes calldata _metadata, uint256 _default ) internal pure returns (uint256) { if (_metadata.length < MSG_VALUE_OFFSET + 32) return _default; return uint256(bytes32(_metadata[MSG_VALUE_OFFSET:MSG_VALUE_OFFSET + 32])); } /** * @notice Returns the specified gas limit for the message. * @param _metadata ABI encoded standard hook metadata. * @param _default Default fallback gas limit. * @return Gas limit for the message as uint256. */ function gasLimit( bytes calldata _metadata, uint256 _default ) internal pure returns (uint256) { if (_metadata.length < GAS_LIMIT_OFFSET + 32) return _default; return uint256(bytes32(_metadata[GAS_LIMIT_OFFSET:GAS_LIMIT_OFFSET + 32])); } /** * @notice Returns the specified refund address for the message. * @param _metadata ABI encoded standard hook metadata. * @param _default Default fallback refund address. * @return Refund address for the message as address. */ function refundAddress( bytes calldata _metadata, address _default ) internal pure returns (address) { if (_metadata.length < REFUND_ADDRESS_OFFSET + 20) return _default; return address( bytes20( _metadata[REFUND_ADDRESS_OFFSET:REFUND_ADDRESS_OFFSET + 20] ) ); } /** * @notice Returns any custom metadata. * @param _metadata ABI encoded standard hook metadata. * @return Custom metadata. */ function getCustomMetadata( bytes calldata _metadata ) internal pure returns (bytes calldata) { if (_metadata.length < MIN_METADATA_LENGTH) return _metadata[0:0]; return _metadata[MIN_METADATA_LENGTH:]; } /** * @notice Formats the specified gas limit and refund address into standard hook metadata. * @param _msgValue msg.value for the message. * @param _gasLimit Gas limit for the message. * @param _refundAddress Refund address for the message. * @param _customMetadata Additional metadata to include in the standard hook metadata. * @return ABI encoded standard hook metadata. */ function formatMetadata( uint256 _msgValue, uint256 _gasLimit, address _refundAddress, bytes memory _customMetadata ) internal pure returns (bytes memory) { return abi.encodePacked( VARIANT, _msgValue, _gasLimit, _refundAddress, _customMetadata ); } /** * @notice Formats the specified gas limit and refund address into standard hook metadata. * @param _msgValue msg.value for the message. * @return ABI encoded standard hook metadata. */ function overrideMsgValue( uint256 _msgValue ) internal view returns (bytes memory) { return formatMetadata(_msgValue, uint256(0), msg.sender, ""); } /** * @notice Formats the specified gas limit and refund address into standard hook metadata. * @param _gasLimit Gas limit for the message. * @return ABI encoded standard hook metadata. */ function overrideGasLimit( uint256 _gasLimit ) internal view returns (bytes memory) { return formatMetadata(uint256(0), _gasLimit, msg.sender, ""); } /** * @notice Formats the specified refund address into standard hook metadata. * @param _refundAddress Refund address for the message. * @return ABI encoded standard hook metadata. */ function overrideRefundAddress( address _refundAddress ) internal pure returns (bytes memory) { return formatMetadata(uint256(0), uint256(0), _refundAddress, ""); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; /*@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@ HYPERLANE @@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@@ @@@@@@@@*/ interface IPostDispatchHook { enum Types { UNUSED, ROUTING, AGGREGATION, MERKLE_TREE, INTERCHAIN_GAS_PAYMASTER, FALLBACK_ROUTING, ID_AUTH_ISM, PAUSABLE, PROTOCOL_FEE, LAYER_ZERO_V1 } /** * @notice Returns an enum that represents the type of hook */ function hookType() external view returns (uint8); /** * @notice Returns whether the hook supports metadata * @param metadata metadata * @return Whether the hook supports metadata */ function supportsMetadata( bytes calldata metadata ) external view returns (bool); /** * @notice Post action after a message is dispatched via the Mailbox * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call */ function postDispatch( bytes calldata metadata, bytes calldata message ) external payable; /** * @notice Compute the payment required by the postDispatch call * @param metadata The metadata required for the hook * @param message The message passed from the Mailbox.dispatch() call * @return Quoted payment for the postDispatch call */ function quoteDispatch( bytes calldata metadata, bytes calldata message ) external view returns (uint256); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; interface IInterchainSecurityModule { enum Types { UNUSED, ROUTING, AGGREGATION, LEGACY_MULTISIG, MERKLE_ROOT_MULTISIG, MESSAGE_ID_MULTISIG, NULL, // used with relayer carrying no metadata CCIP_READ } /** * @notice Returns an enum that represents the type of security model * encoded by this ISM. * @dev Relayers infer how to fetch and format metadata. */ function moduleType() external view returns (uint8); /** * @notice Defines a security model responsible for verifying interchain * messages based on the provided metadata. * @param _metadata Off-chain metadata provided by a relayer, specific to * the security model encoded by the module (e.g. validator signatures) * @param _message Hyperlane encoded interchain message * @return True if the message was verified */ function verify( bytes calldata _metadata, bytes calldata _message ) external returns (bool); } interface ISpecifiesInterchainSecurityModule { function interchainSecurityModule() external view returns (IInterchainSecurityModule); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {IInterchainSecurityModule} from "./IInterchainSecurityModule.sol"; import {IPostDispatchHook} from "./hooks/IPostDispatchHook.sol"; interface IMailbox { // ============ Events ============ /** * @notice Emitted when a new message is dispatched via Hyperlane * @param sender The address that dispatched the message * @param destination The destination domain of the message * @param recipient The message recipient address on `destination` * @param message Raw bytes of message */ event Dispatch( address indexed sender, uint32 indexed destination, bytes32 indexed recipient, bytes message ); /** * @notice Emitted when a new message is dispatched via Hyperlane * @param messageId The unique message identifier */ event DispatchId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is processed * @param messageId The unique message identifier */ event ProcessId(bytes32 indexed messageId); /** * @notice Emitted when a Hyperlane message is delivered * @param origin The origin domain of the message * @param sender The message sender address on `origin` * @param recipient The address that handled the message */ event Process( uint32 indexed origin, bytes32 indexed sender, address indexed recipient ); function localDomain() external view returns (uint32); function delivered(bytes32 messageId) external view returns (bool); function defaultIsm() external view returns (IInterchainSecurityModule); function defaultHook() external view returns (IPostDispatchHook); function requiredHook() external view returns (IPostDispatchHook); function latestDispatchedId() external view returns (bytes32); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata defaultHookMetadata ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata defaultHookMetadata ) external view returns (uint256 fee); function dispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata body, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external payable returns (bytes32 messageId); function quoteDispatch( uint32 destinationDomain, bytes32 recipientAddress, bytes calldata messageBody, bytes calldata customHookMetadata, IPostDispatchHook customHook ) external view returns (uint256 fee); function process( bytes calldata metadata, bytes calldata message ) external payable; function recipientIsm( address recipient ) external view returns (IInterchainSecurityModule module); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; interface IMessageRecipient { function handle( uint32 _origin, bytes32 _sender, bytes calldata _message ) external payable; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; // ============ External Imports ============ import "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; // extends EnumerableMap with uint256 => bytes32 type // modelled after https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.0/contracts/utils/structs/EnumerableMap.sol library EnumerableMapExtended { using EnumerableMap for EnumerableMap.Bytes32ToBytes32Map; using EnumerableSet for EnumerableSet.Bytes32Set; struct UintToBytes32Map { EnumerableMap.Bytes32ToBytes32Map _inner; } // ============ Library Functions ============ function keys( UintToBytes32Map storage map ) internal view returns (uint256[] memory _keys) { uint256 _length = map._inner.length(); _keys = new uint256[](_length); for (uint256 i = 0; i < _length; i++) { _keys[i] = uint256(map._inner._keys.at(i)); } } function uint32Keys( UintToBytes32Map storage map ) internal view returns (uint32[] memory _keys) { uint256[] memory uint256keys = keys(map); _keys = new uint32[](uint256keys.length); for (uint256 i = 0; i < uint256keys.length; i++) { _keys[i] = uint32(uint256keys[i]); } } function set( UintToBytes32Map storage map, uint256 key, bytes32 value ) internal { map._inner.set(bytes32(key), value); } function get( UintToBytes32Map storage map, uint256 key ) internal view returns (bytes32) { return map._inner.get(bytes32(key)); } function tryGet( UintToBytes32Map storage map, uint256 key ) internal view returns (bool, bytes32) { return map._inner.tryGet(bytes32(key)); } function remove( UintToBytes32Map storage map, uint256 key ) internal returns (bool) { return map._inner.remove(bytes32(key)); } function contains( UintToBytes32Map storage map, uint256 key ) internal view returns (bool) { return map._inner.contains(bytes32(key)); } function length( UintToBytes32Map storage map ) internal view returns (uint256) { return map._inner.length(); } function at( UintToBytes32Map storage map, uint256 index ) internal view returns (uint256, bytes32) { (bytes32 key, bytes32 value) = map._inner.at(index); return (uint256(key), value); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; import {TypeCasts} from "./TypeCasts.sol"; /** * @title Hyperlane Message Library * @notice Library for formatted messages used by Mailbox **/ library Message { using TypeCasts for bytes32; uint256 private constant VERSION_OFFSET = 0; uint256 private constant NONCE_OFFSET = 1; uint256 private constant ORIGIN_OFFSET = 5; uint256 private constant SENDER_OFFSET = 9; uint256 private constant DESTINATION_OFFSET = 41; uint256 private constant RECIPIENT_OFFSET = 45; uint256 private constant BODY_OFFSET = 77; /** * @notice Returns formatted (packed) Hyperlane message with provided fields * @dev This function should only be used in memory message construction. * @param _version The version of the origin and destination Mailboxes * @param _nonce A nonce to uniquely identify the message on its origin chain * @param _originDomain Domain of origin chain * @param _sender Address of sender as bytes32 * @param _destinationDomain Domain of destination chain * @param _recipient Address of recipient on destination chain as bytes32 * @param _messageBody Raw bytes of message body * @return Formatted message */ function formatMessage( uint8 _version, uint32 _nonce, uint32 _originDomain, bytes32 _sender, uint32 _destinationDomain, bytes32 _recipient, bytes calldata _messageBody ) internal pure returns (bytes memory) { return abi.encodePacked( _version, _nonce, _originDomain, _sender, _destinationDomain, _recipient, _messageBody ); } /** * @notice Returns the message ID. * @param _message ABI encoded Hyperlane message. * @return ID of `_message` */ function id(bytes memory _message) internal pure returns (bytes32) { return keccak256(_message); } /** * @notice Returns the message version. * @param _message ABI encoded Hyperlane message. * @return Version of `_message` */ function version(bytes calldata _message) internal pure returns (uint8) { return uint8(bytes1(_message[VERSION_OFFSET:NONCE_OFFSET])); } /** * @notice Returns the message nonce. * @param _message ABI encoded Hyperlane message. * @return Nonce of `_message` */ function nonce(bytes calldata _message) internal pure returns (uint32) { return uint32(bytes4(_message[NONCE_OFFSET:ORIGIN_OFFSET])); } /** * @notice Returns the message origin domain. * @param _message ABI encoded Hyperlane message. * @return Origin domain of `_message` */ function origin(bytes calldata _message) internal pure returns (uint32) { return uint32(bytes4(_message[ORIGIN_OFFSET:SENDER_OFFSET])); } /** * @notice Returns the message sender as bytes32. * @param _message ABI encoded Hyperlane message. * @return Sender of `_message` as bytes32 */ function sender(bytes calldata _message) internal pure returns (bytes32) { return bytes32(_message[SENDER_OFFSET:DESTINATION_OFFSET]); } /** * @notice Returns the message sender as address. * @param _message ABI encoded Hyperlane message. * @return Sender of `_message` as address */ function senderAddress( bytes calldata _message ) internal pure returns (address) { return sender(_message).bytes32ToAddress(); } /** * @notice Returns the message destination domain. * @param _message ABI encoded Hyperlane message. * @return Destination domain of `_message` */ function destination( bytes calldata _message ) internal pure returns (uint32) { return uint32(bytes4(_message[DESTINATION_OFFSET:RECIPIENT_OFFSET])); } /** * @notice Returns the message recipient as bytes32. * @param _message ABI encoded Hyperlane message. * @return Recipient of `_message` as bytes32 */ function recipient( bytes calldata _message ) internal pure returns (bytes32) { return bytes32(_message[RECIPIENT_OFFSET:BODY_OFFSET]); } /** * @notice Returns the message recipient as address. * @param _message ABI encoded Hyperlane message. * @return Recipient of `_message` as address */ function recipientAddress( bytes calldata _message ) internal pure returns (address) { return recipient(_message).bytes32ToAddress(); } /** * @notice Returns the message body. * @param _message ABI encoded Hyperlane message. * @return Body of `_message` */ function body( bytes calldata _message ) internal pure returns (bytes calldata) { return bytes(_message[BODY_OFFSET:]); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.6.11; library TypeCasts { // alignment preserving cast function addressToBytes32(address _addr) internal pure returns (bytes32) { return bytes32(uint256(uint160(_addr))); } // alignment preserving cast function bytes32ToAddress(bytes32 _buf) internal pure returns (address) { return address(uint160(uint256(_buf))); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.0; library TokenMessage { function format( bytes32 _recipient, uint256 _amount, bytes memory _metadata ) internal pure returns (bytes memory) { return abi.encodePacked(_recipient, _amount, _metadata); } function recipient(bytes calldata message) internal pure returns (bytes32) { return bytes32(message[0:32]); } function amount(bytes calldata message) internal pure returns (uint256) { return uint256(bytes32(message[32:64])); } // alias for ERC721 function tokenId(bytes calldata message) internal pure returns (uint256) { return amount(message); } function metadata( bytes calldata message ) internal pure returns (bytes calldata) { return message[64:]; } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity >=0.8.0; import {GasRouter} from "../../client/GasRouter.sol"; import {MailboxClient} from "../../client/MailboxClient.sol"; import {TypeCasts} from "../../libs/TypeCasts.sol"; import {TokenMessage} from "./TokenMessage.sol"; /** * @title Hyperlane Token Router that extends Router with abstract token (ERC20/ERC721) remote transfer functionality. * @author Abacus Works */ abstract contract TokenRouter is GasRouter { using TypeCasts for bytes32; using TypeCasts for address; using TokenMessage for bytes; /** * @dev Emitted on `transferRemote` when a transfer message is dispatched. * @param destination The identifier of the destination chain. * @param recipient The address of the recipient on the destination chain. * @param amount The amount of tokens burnt on the origin chain. */ event SentTransferRemote( uint32 indexed destination, bytes32 indexed recipient, uint256 amount ); /** * @dev Emitted on `_handle` when a transfer message is processed. * @param origin The identifier of the origin chain. * @param recipient The address of the recipient on the destination chain. * @param amount The amount of tokens minted on the destination chain. */ event ReceivedTransferRemote( uint32 indexed origin, bytes32 indexed recipient, uint256 amount ); constructor(address _mailbox) GasRouter(_mailbox) {} /** * @notice Transfers `_amountOrId` token to `_recipient` on `_destination` domain. * @dev Delegates transfer logic to `_transferFromSender` implementation. * @dev Emits `SentTransferRemote` event on the origin chain. * @param _destination The identifier of the destination chain. * @param _recipient The address of the recipient on the destination chain. * @param _amountOrId The amount or identifier of tokens to be sent to the remote recipient. * @return messageId The identifier of the dispatched message. */ function transferRemote( uint32 _destination, bytes32 _recipient, uint256 _amountOrId ) external payable virtual returns (bytes32 messageId) { return _transferRemote(_destination, _recipient, _amountOrId, msg.value); } /** * @notice Transfers `_amountOrId` token to `_recipient` on `_destination` domain. * @dev Delegates transfer logic to `_transferFromSender` implementation. * @dev Emits `SentTransferRemote` event on the origin chain. * @param _destination The identifier of the destination chain. * @param _recipient The address of the recipient on the destination chain. * @param _amountOrId The amount or identifier of tokens to be sent to the remote recipient. * @param _gasPayment The amount of native token to pay for interchain gas. * @return messageId The identifier of the dispatched message. */ function _transferRemote( uint32 _destination, bytes32 _recipient, uint256 _amountOrId, uint256 _gasPayment ) internal returns (bytes32 messageId) { bytes memory metadata = _transferFromSender(_amountOrId); messageId = _dispatch( _destination, _gasPayment, TokenMessage.format(_recipient, _amountOrId, metadata) ); emit SentTransferRemote(_destination, _recipient, _amountOrId); } /** * @dev Should transfer `_amountOrId` of tokens from `msg.sender` to this token router. * @dev Called by `transferRemote` before message dispatch. * @dev Optionally returns `metadata` associated with the transfer to be passed in message. */ function _transferFromSender( uint256 _amountOrId ) internal virtual returns (bytes memory metadata); /** * @notice Returns the balance of `account` on this token router. * @param account The address to query the balance of. * @return The balance of `account`. */ function balanceOf(address account) external virtual returns (uint256); /** * @dev Mints tokens to recipient when router receives transfer message. * @dev Emits `ReceivedTransferRemote` event on the destination chain. * @param _origin The identifier of the origin chain. * @param _message The encoded remote transfer message containing the recipient address and amount. */ function _handle( uint32 _origin, bytes32, bytes calldata _message ) internal virtual override { bytes32 recipient = _message.recipient(); uint256 amount = _message.amount(); bytes calldata metadata = _message.metadata(); _transferTo(recipient.bytes32ToAddress(), amount, metadata); emit ReceivedTransferRemote(_origin, recipient, amount); } /** * @dev Should transfer `_amountOrId` of tokens from this token router to `_recipient`. * @dev Called by `handle` after message decoding. * @dev Optionally handles `metadata` associated with transfer passed in message. */ function _transferTo( address _recipient, uint256 _amountOrId, bytes calldata metadata ) internal virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.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] * ```solidity * 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. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.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. * * 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. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * 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. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ 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. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @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. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal virtual {} /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such * that `ownerOf(tokenId)` is `a`. */ // solhint-disable-next-line func-name-mixedcase function __unsafe_increaseBalance(address account, uint256 amount) internal { _balances[account] += amount; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev See {ERC721-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual override { super._beforeTokenTransfer(from, to, firstTokenId, batchSize); if (batchSize > 1) { // Will only trigger during construction. Batch transferring (minting) is not available afterwards. revert("ERC721Enumerable: consecutive transfers not supported"); } uint256 tokenId = firstTokenId; if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// 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 v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// 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 // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableMap.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. pragma solidity ^0.8.0; import "./EnumerableSet.sol"; /** * @dev Library for managing an enumerable variant of Solidity's * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] * type. * * Maps have the following properties: * * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableMap for EnumerableMap.UintToAddressMap; * * // Declare a set state variable * EnumerableMap.UintToAddressMap private myMap; * } * ``` * * The following map types are supported: * * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableMap. * ==== */ library EnumerableMap { using EnumerableSet for EnumerableSet.Bytes32Set; // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Map type with // bytes32 keys and values. // The Map implementation uses private functions, and user-facing // implementations (such as Uint256ToAddressMap) are just wrappers around // the underlying Map. // This means that we can only create new EnumerableMaps for types that fit // in bytes32. struct Bytes32ToBytes32Map { // Storage of keys EnumerableSet.Bytes32Set _keys; mapping(bytes32 => bytes32) _values; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) { map._values[key] = value; return map._keys.add(key); } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { delete map._values[key]; return map._keys.remove(key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { return map._keys.contains(key); } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { return map._keys.length(); } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { bytes32 key = map._keys.at(index); return (key, map._values[key]); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { bytes32 value = map._values[key]; if (value == bytes32(0)) { return (contains(map, key), bytes32(0)); } else { return (true, value); } } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { bytes32 value = map._values[key]; require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key"); return value; } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( Bytes32ToBytes32Map storage map, bytes32 key, string memory errorMessage ) internal view returns (bytes32) { bytes32 value = map._values[key]; require(value != 0 || contains(map, key), errorMessage); return value; } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) { return map._keys.values(); } // UintToUintMap struct UintToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get(UintToUintMap storage map, uint256 key, string memory errorMessage) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key), errorMessage)); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToUintMap storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintToAddressMap struct UintToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( UintToAddressMap storage map, uint256 key, string memory errorMessage ) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage)))); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressToUintMap struct AddressToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToUintMap storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToUintMap storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToUintMap storage map, address key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))))); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( AddressToUintMap storage map, address key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage)); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(AddressToUintMap storage map) internal view returns (address[] memory) { bytes32[] memory store = keys(map._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // Bytes32ToUintMap struct Bytes32ToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) { return set(map._inner, key, bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { return remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { return contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(Bytes32ToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (key, uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, key); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { return uint256(get(map._inner, key)); } /** * @dev Same as {get}, with a custom error message when `key` is not in the map. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryGet}. */ function get( Bytes32ToUintMap storage map, bytes32 key, string memory errorMessage ) internal view returns (uint256) { return uint256(get(map._inner, key, errorMessage)); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) { bytes32[] memory store = keys(map._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_mailbox","type":"address"},{"internalType":"address","name":"_feeCollector","type":"address"},{"internalType":"uint256","name":"_mintFee","type":"uint256"},{"internalType":"uint256","name":"_bridgeFee","type":"uint256"},{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"uint256","name":"_idMultiplier","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collector","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimedAmount","type":"uint256"}],"name":"FeeEarningsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":true,"internalType":"uint256","name":"itemId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeEarnings","type":"uint256"},{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"referrerEarnings","type":"uint256"}],"name":"NFTMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"srcAddress","type":"bytes32"},{"indexed":true,"internalType":"uint32","name":"srcChainId","type":"uint32"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NFTReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint32","name":"dstChainId","type":"uint32"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeEarned","type":"uint256"}],"name":"NFTSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"origin","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"recipient","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReceivedTransferRemote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"claimedAmount","type":"uint256"}],"name":"ReferrerEarningsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"destination","type":"uint32"},{"indexed":true,"internalType":"bytes32","name":"recipient","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SentTransferRemote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_tokenBaseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_tokenURIExtension","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"batchMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"batchMintWithReferrer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"bridgeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateRefShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRefEarnings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimedFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"commonRefBips","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"destinationGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domains","outputs":[{"internalType":"uint32[]","name":"","type":"uint32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"bytes32","name":"_router","type":"bytes32"}],"name":"enrollRemoteRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"_domains","type":"uint32[]"},{"internalType":"bytes32[]","name":"_addresses","type":"bytes32[]"}],"name":"enrollRemoteRouters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeToCollect","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstChain","type":"uint32"}],"name":"getHyperlaneMessageFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_origin","type":"uint32"},{"internalType":"bytes32","name":"_sender","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"handle","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"hook","outputs":[{"internalType":"contract IPostDispatchHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interchainSecurityModule","outputs":[{"internalType":"contract IInterchainSecurityModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"localDomain","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mailbox","outputs":[{"internalType":"contract IMailbox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"mintWithReferrer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"personalRefBips","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_destinationDomain","type":"uint32"}],"name":"quoteGasPayment","outputs":[{"internalType":"uint256","name":"_gasPayment","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"refAmountClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"refAmountToClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"refTxsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resqueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"}],"name":"routers","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bridgeFee","type":"uint256"}],"name":"setBridgeFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_bips","type":"uint16"}],"name":"setCommonRefBips","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"setDestinationGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"domain","type":"uint32"},{"internalType":"uint256","name":"gas","type":"uint256"}],"internalType":"struct GasRouter.GasRouterConfig[]","name":"gasConfigs","type":"tuple[]"}],"name":"setDestinationGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeCollector","type":"address"}],"name":"setFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_hook","type":"address"}],"name":"setHook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_module","type":"address"}],"name":"setInterchainSecurityModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintFee","type":"uint256"}],"name":"setMintFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"},{"internalType":"uint16","name":"bips","type":"uint16"}],"name":"setPersonalRefBips","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"referrers","type":"address[]"},{"internalType":"uint16","name":"bips","type":"uint16"}],"name":"setPersonalRefBipsBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newTokenBaseURI","type":"string"},{"internalType":"string","name":"_fileExtension","type":"string"}],"name":"setTokenBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_dstChain","type":"uint32"},{"internalType":"bytes32","name":"_receiver","type":"bytes32"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferRemote","outputs":[{"internalType":"bytes32","name":"messageId","type":"bytes32"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"}],"name":"unenrollRemoteRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32[]","name":"_domains","type":"uint32[]"}],"name":"unenrollRemoteRouters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101006040523480156200001257600080fd5b5060405162004f5338038062004f538339810160408190526200003591620002f0565b6040518060400160405280600781526020016611d95d135a5b9d60ca1b81525060405180604001604052806002815260200161474d60f01b815250878080808062000086816200027260201b60201c565b620000d85760405162461bcd60e51b815260206004820152601e60248201527f4d61696c626f78436c69656e743a20696e76616c6964206d61696c626f78000060448201526064015b60405180910390fd5b6001600160a01b03821660808190526040805163234d8e3d60e21b81529051638d3638f4916004808201926020929091908290030181865afa15801562000123573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200014991906200034d565b63ffffffff1660a0526200015d3362000281565b50505050508160cb908162000173919062000421565b5060cc62000182828262000421565b505060d5805460ff1916905550600160d6556001600160a01b038516620001ec5760405162461bcd60e51b815260206004820152601e60248201527f46656520636f6c6c6563746f72206d757374206265206e6f6e2d7a65726f00006044820152606401620000cf565b60da80546001600160a01b0319166001600160a01b03871617905560dc84905560db8390556200021d818362000503565b6200022a90600162000523565b60c0526200023a81600162000523565b62000246908362000503565b60e05262000255818362000503565b6200026290600162000523565b60d7555062000539945050505050565b6001600160a01b03163b151590565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b80516001600160a01b0381168114620002eb57600080fd5b919050565b60008060008060008060c087890312156200030a57600080fd5b6200031587620002d3565b95506200032560208801620002d3565b945060408701519350606087015192506080870151915060a087015190509295509295509295565b6000602082840312156200036057600080fd5b815163ffffffff811681146200037557600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c90821680620003a757607f821691505b602082108103620003c857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200041c57600081815260208120601f850160051c81016020861015620003f75750805b601f850160051c820191505b81811015620004185782815560010162000403565b5050505b505050565b81516001600160401b038111156200043d576200043d6200037c565b62000455816200044e845462000392565b84620003ce565b602080601f8311600181146200048d5760008415620004745750858301515b600019600386901b1c1916600185901b17855562000418565b600085815260208120601f198616915b82811015620004be578886015182559484019460019091019084016200049d565b5085821015620004dd5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176200051d576200051d620004ed565b92915050565b808201808211156200051d576200051d620004ed565b60805160a05160c05160e0516149af620005a460003960008181610969015281816110f7015281816117c301528181611da40152611f2001526000610b20015260006108d9015260008181610bac0152818161164601528181613296015261393501526149af6000f3fe60806040526004361061041b5760003560e01c806381b4e8b41161021e578063c415b95c11610123578063de523cf3116100ab578063eddd0d9c1161007a578063eddd0d9c14610c88578063efae508a14610ca8578063f2ed8c5314610cc8578063f2fde38b14610ce8578063f39c504c14610d0857600080fd5b8063de523cf314610bce578063e3d078dc14610bee578063e9198bf914610c1f578063e985e9c514610c3f57600080fd5b8063ce6e23b2116100f2578063ce6e23b214610b0e578063d082e38114610b42578063d11ba61414610b58578063d294f09314610b85578063d5438eae14610b9a57600080fd5b8063c415b95c14610a93578063c87b56dd14610ab3578063cb253c4614610ad3578063cbc1418a14610aee57600080fd5b80639236197a116101a6578063a22cb46511610175578063a22cb465146109f3578063a42dce8014610a13578063b1bd643614610a33578063b49c53a714610a53578063b88d4fde14610a7357600080fd5b80639236197a1461098b57806395d89b41146109ab578063998cdf83146109c0578063a14d4699146109e057600080fd5b80638cfd1a65116101ed5780638cfd1a65146108b25780638d3638f4146108c75780638da5cb5b14610910578063918f86741461092e57806391ba317a1461095757600080fd5b806381b4e8b41461086157806382b12dd7146108745780638456cb591461088a5780638467be0d1461089f57600080fd5b806342aeaaf9116103245780636141cc09116102ac578063715018a61161027b578063715018a6146107c957806371a15b38146107de578063775313a1146107fe578063777133dd1461082b5780637f5a7c7b1461084157600080fd5b80636141cc091461075e5780636352211e14610774578063641ddc2e1461079457806370a08231146107a957600080fd5b80634e886281116102f35780634e886281146106e05780634f6ccce71461070057806356d5d475146107205780635c975abb146107335780635f74172c1461074b57600080fd5b806342aeaaf914610651578063440df4f41461067e57806349d462ef146106a05780634b7784c1146106c057600080fd5b806323b872dd116103a757806337bb76dc1161037657806337bb76dc146105c75780633ca4fb76146105e75780633dfd3873146105fc5780633f4ba83a1461061c57806342842e0e1461063157600080fd5b806323b872dd146105475780632643bf5f146105675780632ead72f6146105875780632f745c59146105a757600080fd5b80630b2b1955116103ee5780630b2b1955146104d15780630e72cc06146104e65780631249c58b1461050657806313966db51461050e57806318160ddd1461053257600080fd5b806301ffc9a71461042057806306fdde0314610455578063081812fc14610477578063095ea7b3146104af575b600080fd5b34801561042c57600080fd5b5061044061043b366004613c31565b610d35565b60405190151581526020015b60405180910390f35b34801561046157600080fd5b5061046a610d60565b60405161044c9190613c9e565b34801561048357600080fd5b50610497610492366004613cb1565b610df2565b6040516001600160a01b03909116815260200161044c565b3480156104bb57600080fd5b506104cf6104ca366004613ce6565b610e19565b005b3480156104dd57600080fd5b506104cf610f33565b3480156104f257600080fd5b506104cf610501366004613d10565b61105a565b6104cf6110c1565b34801561051a57600080fd5b5061052460dc5481565b60405190815260200161044c565b34801561053e57600080fd5b5060d354610524565b34801561055357600080fd5b506104cf610562366004613d2b565b6111ac565b34801561057357600080fd5b506104cf610582366004613d79565b6111dd565b34801561059357600080fd5b506105246105a2366004613da8565b611223565b3480156105b357600080fd5b506105246105c2366004613ce6565b611242565b3480156105d357600080fd5b506104cf6105e2366004613dc3565b6112d8565b3480156105f357600080fd5b5061046a611335565b34801561060857600080fd5b506104cf610617366004613d10565b6113c3565b34801561062857600080fd5b506104cf61142a565b34801561063d57600080fd5b506104cf61064c366004613d2b565b611442565b34801561065d57600080fd5b5061052461066c366004613d10565b60e16020526000908152604090205481565b34801561068a57600080fd5b5061069361145d565b60405161044c9190613df6565b3480156106ac57600080fd5b506104cf6106bb366004613e40565b61146e565b3480156106cc57600080fd5b506104cf6106db366004613ea0565b611494565b3480156106ec57600080fd5b506105246106fb366004613ce6565b61153e565b34801561070c57600080fd5b5061052461071b366004613cb1565b6115a8565b6104cf61072e366004613f34565b61163b565b34801561073f57600080fd5b5060d55460ff16610440565b6104cf610759366004613f8d565b61173a565b34801561076a57600080fd5b5061052460de5481565b34801561078057600080fd5b5061049761078f366004613cb1565b611901565b3480156107a057600080fd5b506104cf611961565b3480156107b557600080fd5b506105246107c4366004613d10565b611ae7565b3480156107d557600080fd5b506104cf611af2565b3480156107ea57600080fd5b506104cf6107f9366004613fb0565b611b04565b34801561080a57600080fd5b50610524610819366004613da8565b60ca6020526000908152604090205481565b34801561083757600080fd5b5061052460dd5481565b34801561084d57600080fd5b50606554610497906001600160a01b031681565b61052461086f366004613ff1565b611b59565b34801561088057600080fd5b5061052460db5481565b34801561089657600080fd5b506104cf611d40565b6104cf6108ad366004613cb1565b611d58565b3480156108be57600080fd5b5061046a611e68565b3480156108d357600080fd5b506108fb7f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161044c565b34801561091c57600080fd5b506033546001600160a01b0316610497565b34801561093a57600080fd5b5061094461271081565b60405161ffff909116815260200161044c565b34801561096357600080fd5b506105247f000000000000000000000000000000000000000000000000000000000000000081565b34801561099757600080fd5b506105246109a6366004613da8565b611e75565b3480156109b757600080fd5b5061046a611e91565b3480156109cc57600080fd5b506104cf6109db366004613cb1565b611ea0565b6104cf6109ee366004613d10565b611ead565b3480156109ff57600080fd5b506104cf610a0e366004614024565b612048565b348015610a1f57600080fd5b506104cf610a2e366004613d10565b612053565b348015610a3f57600080fd5b506104cf610a4e366004614060565b6120f1565b348015610a5f57600080fd5b506104cf610a6e366004613e40565b612176565b348015610a7f57600080fd5b506104cf610a8e3660046140ea565b612188565b348015610a9f57600080fd5b5060da54610497906001600160a01b031681565b348015610abf57600080fd5b5061046a610ace366004613cb1565b6121b9565b348015610adf57600080fd5b5060df546109449061ffff1681565b348015610afa57600080fd5b506104cf610b093660046141c5565b6121f0565b348015610b1a57600080fd5b506105247f000000000000000000000000000000000000000000000000000000000000000081565b348015610b4e57600080fd5b5061052460d75481565b348015610b6457600080fd5b50610524610b73366004613d10565b60e26020526000908152604090205481565b348015610b9157600080fd5b506104cf612213565b348015610ba657600080fd5b506104977f000000000000000000000000000000000000000000000000000000000000000081565b348015610bda57600080fd5b50606654610497906001600160a01b031681565b348015610bfa57600080fd5b50610944610c09366004613d10565b60e06020526000908152604090205461ffff1681565b348015610c2b57600080fd5b506104cf610c3a366004614224565b6123f3565b348015610c4b57600080fd5b50610440610c5a366004614283565b6001600160a01b03918216600090815260d06020908152604080832093909416825291909152205460ff1690565b348015610c9457600080fd5b506104cf610ca3366004613cb1565b6124a2565b348015610cb457600080fd5b506104cf610cc3366004613da8565b6124af565b348015610cd457600080fd5b50610524610ce3366004613da8565b6124c0565b348015610cf457600080fd5b506104cf610d03366004613d10565b6124db565b348015610d1457600080fd5b50610524610d23366004613d10565b60e36020526000908152604090205481565b60006001600160e01b0319821663780e9d6360e01b1480610d5a5750610d5a82612551565b92915050565b606060cb8054610d6f906142ad565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9b906142ad565b8015610de85780601f10610dbd57610100808354040283529160200191610de8565b820191906000526020600020905b815481529060010190602001808311610dcb57829003601f168201915b5050505050905090565b6000610dfd826125a1565b50600090815260cf60205260409020546001600160a01b031690565b6000610e2482611901565b9050806001600160a01b0316836001600160a01b031603610e965760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610eb25750610eb28133610c5a565b610f245760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610e8d565b610f2e8383612600565b505050565b60da546001600160a01b0316336001600160a01b03161480610f5f57506033546001600160a01b031633145b610fbf5760405162461bcd60e51b815260206004820152602b60248201527f5265737175653a204f6e6c792066656520636f6c6c6563746f72206f72206f7760448201526a1b995c88185b1b1bddd95960aa1b6064820152608401610e8d565b604051600090339047908381818185875af1925050503d8060008114611001576040519150601f19603f3d011682016040523d82523d6000602084013e611006565b606091505b50509050806110575760405162461bcd60e51b815260206004820152601d60248201527f5265737175653a20204661696c656420746f2073656e642045746865720000006044820152606401610e8d565b50565b806001600160a01b0381163b15158061107a57506001600160a01b038116155b6110965760405162461bcd60e51b8152600401610e8d906142e7565b61109e61266e565b50606680546001600160a01b0319166001600160a01b0392909216919091179055565b6110c96126c8565b6110d1612721565b60dc5434146110f25760405162461bcd60e51b8152600401610e8d9061432e565b60d7547f00000000000000000000000000000000000000000000000000000000000000008111156111355760405162461bcd60e51b8152600401610e8d90614372565b60d760008154611144906143c9565b9091555060dc5460dd805460009061115d9084906143e2565b9091555061116e9050335b82612767565b60dc5460408051918252600060208301819052918391339160008051602061495a833981519152910160405180910390a4506111aa600160d655565b565b6111b63382612781565b6111d25760405162461bcd60e51b8152600401610e8d906143f5565b610f2e8383836127ff565b6111e561266e565b61271061ffff8216111561120b5760405162461bcd60e51b8152600401610e8d90614442565b60df805461ffff191661ffff92909216919091179055565b60008061123a609763ffffffff8086169061297016565b949350505050565b600061124d83612989565b82106112af5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610e8d565b506001600160a01b0391909116600090815260d160209081526040808320938352929052205490565b6112e061266e565b61271061ffff821611156113065760405162461bcd60e51b8152600401610e8d90614442565b6001600160a01b0391909116600090815260e060205260409020805461ffff191661ffff909216919091179055565b60d88054611342906142ad565b80601f016020809104026020016040519081016040528092919081815260200182805461136e906142ad565b80156113bb5780601f10611390576101008083540402835291602001916113bb565b820191906000526020600020905b81548152906001019060200180831161139e57829003601f168201915b505050505081565b806001600160a01b0381163b1515806113e357506001600160a01b038116155b6113ff5760405162461bcd60e51b8152600401610e8d906142e7565b61140761266e565b50606580546001600160a01b0319166001600160a01b0392909216919091179055565b61143261266e565b61143a612a0f565b6111aa612a58565b610f2e83838360405180602001604052806000815250612188565b60606114696097612aaa565b905090565b61147661266e565b63ffffffff91909116600090815260ca6020526040902055565b5050565b61149c61266e565b61271061ffff821611156114c25760405162461bcd60e51b8152600401610e8d90614442565b60005b82811015611538578160e060008686858181106114e4576114e461448c565b90506020020160208101906114f99190613d10565b6001600160a01b031681526020810191909152604001600020805461ffff191661ffff9290921691909117905580611530816143c9565b9150506114c5565b50505050565b6001600160a01b038216600090815260e0602052604081205461ffff168181156115685781611570565b60df5461ffff165b90508060000361158557600092505050610d5a565b600061271061159483876144a2565b61159e91906144b9565b9695505050505050565b60006115b360d35490565b82106116165760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610e8d565b60d382815481106116295761162961448c565b90600052602060002001549050919050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146116bd5760405162461bcd60e51b815260206004820152602160248201527f4d61696c626f78436c69656e743a2073656e646572206e6f74206d61696c626f6044820152600f60fb1b6064820152608401610e8d565b60006116c885612b64565b90508381146117275760405162461bcd60e51b815260206004820152602560248201527f456e726f6c6c656420726f7574657220646f6573206e6f74206d61746368207360448201526432b73232b960d91b6064820152608401610e8d565b61173385858585612bb0565b5050505050565b6117426126c8565b61174a612721565b336001600160a01b0382161480159061176b57506001600160a01b03811615155b6117875760405162461bcd60e51b8152600401610e8d906144db565b8160dc5461179591906144a2565b34146117b35760405162461bcd60e51b8152600401610e8d9061432e565b60005b828110156118f65760d7547f00000000000000000000000000000000000000000000000000000000000000008111156118015760405162461bcd60e51b8152600401610e8d90614372565b60dc546000611810858361153e565b905060d760008154611821906143c9565b9091555061182f8183614522565b60dd600082825461184091906143e2565b90915550506001600160a01b038516600090815260e260205260408120805483929061186d9084906143e2565b90915550506001600160a01b038516600090815260e1602052604081208054909190611898906143c9565b909155506118a7335b84612767565b60dc5460408051918252602082018390526001600160a01b038716918591339160008051602061495a833981519152910160405180910390a450505080806118ee906143c9565b9150506117b6565b50611490600160d655565b600081815260cd60205260408120546001600160a01b031680610d5a5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b6119696126c8565b33600090815260e26020526040902054806119b95760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b6044820152606401610e8d565b33600081815260e26020908152604080832083905560e3909152812080548492906119e59084906143e2565b90915550506040516000906001600160a01b0383169084908381818185875af1925050503d8060008114611a35576040519150601f19603f3d011682016040523d82523d6000602084013e611a3a565b606091505b5050905080611a975760405162461bcd60e51b8152602060048201526024808201527f526566657272616c53797374656d3a204661696c656420746f2073656e6420456044820152633a3432b960e11b6064820152608401610e8d565b816001600160a01b03167fa6183a81b1ce4e0d90156f6ec9b6f2d13c204d11884302b40b47bb456fb5915684604051611ad291815260200190565b60405180910390a25050506111aa600160d655565b6000610d5a82612989565b611afa61266e565b6111aa6000612c3a565b611b0c61266e565b8060005b8181101561153857611b47848483818110611b2d57611b2d61448c565b9050602002016020810190611b429190613da8565b612c8c565b611b526001826143e2565b9050611b10565b6000611b636126c8565b611b6b612721565b82611bb85760405162461bcd60e51b815260206004820152601f60248201527f4765744d696e744e46543732313a20496e76616c6964207265636569766572006044820152606401610e8d565b611bc3335b83612781565b611c2c5760405162461bcd60e51b815260206004820152603460248201527f4765744d696e744e46543732313a2073656e642063616c6c6572206973206e6f6044820152731d081bdddb995c881b9bdc88185c1c1c9bdd995960621b6064820152608401610e8d565b6000611c3785611e75565b905060db5481611c4791906143e2565b341015611ca55760405162461bcd60e51b815260206004820152602660248201527f4765744d696e744e46543732313a20496e636f7272656374206d6573736167656044820152652076616c756560d01b6064820152608401610e8d565b60db5460dd6000828254611cb991906143e2565b92505081905550611cd985858560db5434611cd49190614522565b612cc7565b60db546040805186815260208101929092529193506001600160a01b0386169163ffffffff88169133917f8c76f9a0946e85f2e4c199f247a3436d1766156d4ce90144bf16dfb353878ade910160405180910390a450611d39600160d655565b9392505050565b611d4861266e565b611d50612721565b6111aa612d36565b611d606126c8565b611d68612721565b8060dc54611d7691906144a2565b3414611d945760405162461bcd60e51b8152600401610e8d9061432e565b60005b81811015611e5d5760d7547f0000000000000000000000000000000000000000000000000000000000000000811115611de25760405162461bcd60e51b8152600401610e8d90614372565b60d760008154611df1906143c9565b9091555060dc5460dd8054600090611e0a9084906143e2565b90915550611e19905033611168565b60dc5460408051918252600060208301819052918391339160008051602061495a833981519152910160405180910390a45080611e55816143c9565b915050611d97565b50611057600160d655565b60d98054611342906142ad565b600080611d398360405180602001604052806000815250612d73565b606060cc8054610d6f906142ad565b611ea861266e565b60db55565b611eb56126c8565b611ebd612721565b336001600160a01b03821614801590611ede57506001600160a01b03811615155b611efa5760405162461bcd60e51b8152600401610e8d906144db565b60dc543414611f1b5760405162461bcd60e51b8152600401610e8d9061432e565b60d7547f0000000000000000000000000000000000000000000000000000000000000000811115611f5e5760405162461bcd60e51b8152600401610e8d90614372565b60dc546000611f6d848361153e565b905060d760008154611f7e906143c9565b90915550611f8c8183614522565b60dd6000828254611f9d91906143e2565b90915550506001600160a01b038416600090815260e2602052604081208054839290611fca9084906143e2565b90915550506001600160a01b038416600090815260e1602052604081208054909190611ff5906143c9565b90915550612002336118a1565b60dc5460408051918252602082018390526001600160a01b038616918591339160008051602061495a833981519152910160405180910390a4505050611057600160d655565b611490338383612d8c565b61205b61266e565b6001600160a01b0381166120cf5760405162461bcd60e51b815260206004820152603560248201527f4765744d696e744e46543732313a2046656520636f6c6c6563746f72206d757360448201527474206265206e6f6e2d7a65726f206164647265737360581b6064820152608401610e8d565b60da80546001600160a01b0319166001600160a01b0392909216919091179055565b6120f961266e565b60005b81811015610f2e576121648383838181106121195761211961448c565b61212f9260206040909202019081019150613da8565b8484848181106121415761214161448c565b9050604002016020013563ffffffff909116600090815260ca6020526040902055565b61216f6001826143e2565b90506120fc565b61217e61266e565b6114908282612e5a565b61219133611bbd565b6121ad5760405162461bcd60e51b8152600401610e8d906143f5565b61153884848484612e70565b606060d86121c683612ea3565b60d96040516020016121da939291906145a8565b6040516020818303038152906040529050919050565b6121f861266e565b60d8612205848683614621565b5060d9611733828483614621565b61221b6126c8565b60da546001600160a01b0316336001600160a01b0316146122905760405162461bcd60e51b815260206004820152602960248201527f4765744d696e744e46543732313a204f6e6c792066656520636f6c6c6563746f6044820152681c88185b1b1bddd95960ba1b6064820152608401610e8d565b60dd5460008190036122e45760405162461bcd60e51b815260206004820152601f60248201527f4765744d696e744e46543732313a204e6f7468696e6720746f20636c61696d006044820152606401610e8d565b600060dd819055508060de60008282546122fe91906143e2565b909155505060da546040516000916001600160a01b03169083908381818185875af1925050503d8060008114612350576040519150601f19603f3d011682016040523d82523d6000602084013e612355565b606091505b50509050806123b25760405162461bcd60e51b815260206004820152602360248201527f4765744d696e744e46543732313a204661696c656420746f2073656e642045746044820152623432b960e91b6064820152608401610e8d565b60405182815233907f582c87414358df39212a275853c71633d2dc65d15ae92cc5718e7438766bea769060200160405180910390a250506111aa600160d655565b6123fb61266e565b8281146124345760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610e8d565b8260005b8181101561249a576124888686838181106124555761245561448c565b905060200201602081019061246a9190613da8565b85858481811061247c5761247c61448c565b90506020020135612e5a565b6124936001826143e2565b9050612438565b505050505050565b6124aa61266e565b60dc55565b6124b761266e565b61105781612c8c565b6000610d5a8260405180602001604052806000815250612d73565b6124e361266e565b6001600160a01b0381166125485760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e8d565b61105781612c3a565b60006001600160e01b031982166380ac58cd60e01b148061258257506001600160e01b03198216635b5e139f60e01b145b80610d5a57506301ffc9a760e01b6001600160e01b0319831614610d5a565b600081815260cd60205260409020546001600160a01b03166110575760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b600081815260cf6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061263582611901565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6033546001600160a01b031633146111aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e8d565b600260d6540361271a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e8d565b600260d655565b60d55460ff16156111aa5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e8d565b611490828260405180602001604052806000815250612f35565b60008061278d83611901565b9050806001600160a01b0316846001600160a01b031614806127d457506001600160a01b03808216600090815260d0602090815260408083209388168352929052205460ff165b8061123a5750836001600160a01b03166127ed84610df2565b6001600160a01b031614949350505050565b826001600160a01b031661281282611901565b6001600160a01b0316146128385760405162461bcd60e51b8152600401610e8d906146e0565b6001600160a01b03821661289a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e8d565b6128a78383836001612f68565b826001600160a01b03166128ba82611901565b6001600160a01b0316146128e05760405162461bcd60e51b8152600401610e8d906146e0565b600081815260cf6020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260ce855283862080546000190190559087168086528386208054600101905586865260cd90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60008061297d8484613095565b915091505b9250929050565b60006001600160a01b0382166129f35760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e8d565b506001600160a01b0316600090815260ce602052604090205490565b60d55460ff166111aa5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e8d565b612a60612a0f565b60d5805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60606000612ab7836130cf565b905080516001600160401b03811115612ad257612ad26140d4565b604051908082528060200260200182016040528015612afb578160200160208202803683370190505b50915060005b8151811015612b5d57818181518110612b1c57612b1c61448c565b6020026020010151838281518110612b3657612b3661448c565b63ffffffff9092166020928302919091019091015280612b55816143c9565b915050612b01565b5050919050565b60008080612b7c609763ffffffff8087169061297016565b9150915081612b8a85613169565b90612ba85760405162461bcd60e51b8152600401610e8d9190613c9e565b509392505050565b6000612bbc838361318a565b90506000612bca84846131a2565b9050366000612bd986866131b2565b91509150612bef612be78590565b8484846131c2565b838863ffffffff167fba20947a325f450d232530e5f5fce293e7963499d5309a07cee84a269f2f15a685604051612c2891815260200190565b60405180910390a35050505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612ca0609763ffffffff808416906131cc16565b612ca982613169565b906114905760405162461bcd60e51b8152600401610e8d9190613c9e565b600080612cd3846131d8565b9050612cea8684612ce5888886613240565b61326f565b9150848663ffffffff167fd229aacb94204188fe8042965fa6b269c62dc5818b21238779ab64bdd17efeec86604051612d2591815260200190565b60405180910390a350949350505050565b612d3e612721565b60d5805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612a8d3390565b600080612d7f84612b64565b905061123a848285613292565b816001600160a01b0316836001600160a01b031603612ded5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e8d565b6001600160a01b03838116600081815260d06020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611490609763ffffffff80851690849061334116565b612e7b8484846127ff565b612e878484848461334c565b6115385760405162461bcd60e51b8152600401610e8d90614725565b60606000612eb08361344d565b60010190506000816001600160401b03811115612ecf57612ecf6140d4565b6040519080825280601f01601f191660200182016040528015612ef9576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612f0357509392505050565b612f3f8383613525565b612f4c600084848461334c565b610f2e5760405162461bcd60e51b8152600401610e8d90614725565b6001811115612fd75760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b6064820152608401610e8d565b816001600160a01b0385166130335761302e8160d38054600083815260d460205260408120829055600182018355919091527f915c3eb987b20e1af620c1403197bf687fb7f18513b3a73fde6e78c7072c41a60155565b613056565b836001600160a01b0316856001600160a01b0316146130565761305685826136be565b6001600160a01b0384166130725761306d8161375b565b611733565b846001600160a01b0316846001600160a01b03161461173357611733848261380a565b60008181526002830160205260408120548190806130c4576130b7858561384e565b9250600091506129829050565b600192509050612982565b606060006130dc8361385a565b9050806001600160401b038111156130f6576130f66140d4565b60405190808252806020026020018201604052801561311f578160200160208202803683370190505b50915060005b81811015612b5d576131378482613865565b60001c83828151811061314c5761314c61448c565b602090810291909101015280613161816143c9565b915050613125565b606061317a8263ffffffff16612ea3565b6040516020016121da9190614777565b600061319960208284866147bc565b611d39916147e6565b60006131996040602084866147bc565b36600061297d83604081876147bc565b6115388484612767565b6000611d398383613871565b6060336131e483611901565b6001600160a01b0316146132235760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610e8d565b61322c8261388e565b505060408051602081019091526000815290565b606083838360405160200161325793929190614804565b60405160208183030381529060405290509392505050565b60008061327b85612b64565b905061328985828686613931565b95945050505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166381d2ea958585856132cf896139e3565b6065546040516001600160e01b031960e088901b16815261330095949392916001600160a01b031690600401614831565b602060405180830381865afa15801561331d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123a9190614883565b611538838383613a05565b60006001600160a01b0384163b1561344257604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061339090339089908890889060040161489c565b6020604051808303816000875af19250505080156133cb575060408051601f3d908101601f191682019092526133c8918101906148cf565b60015b613428573d8080156133f9576040519150601f19603f3d011682016040523d82523d6000602084013e6133fe565b606091505b5080516000036134205760405162461bcd60e51b8152600401610e8d90614725565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061123a565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061348c5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106134b8576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106134d657662386f26fc10000830492506010015b6305f5e10083106134ee576305f5e100830492506008015b612710831061350257612710830492506004015b60648310613514576064830492506002015b600a8310610d5a5760010192915050565b6001600160a01b03821661357b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e8d565b600081815260cd60205260409020546001600160a01b0316156135e05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6135ee600083836001612f68565b600081815260cd60205260409020546001600160a01b0316156136535760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6001600160a01b038216600081815260ce602090815260408083208054600101905584835260cd90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600060016136cb84612989565b6136d59190614522565b600083815260d26020526040902054909150808214613728576001600160a01b038416600090815260d160209081526040808320858452825280832054848452818420819055835260d290915290208190555b50600091825260d2602090815260408084208490556001600160a01b03909416835260d181528383209183525290812055565b60d35460009061376d90600190614522565b600083815260d4602052604081205460d380549394509092849081106137955761379561448c565b906000526020600020015490508060d383815481106137b6576137b661448c565b600091825260208083209091019290925582815260d4909152604080822084905585825281205560d38054806137ee576137ee6148ec565b6001900381819060005260206000200160009055905550505050565b600061381583612989565b6001600160a01b03909316600090815260d160209081526040808320868452825280832085905593825260d29052919091209190915550565b6000611d398383613a22565b6000610d5a82613a3a565b6000611d398383613a44565b60008181526002830160205260408120819055611d398383613a6e565b600061389982611901565b90506138a9816000846001612f68565b6138b282611901565b600083815260cf6020908152604080832080546001600160a01b03199081169091556001600160a01b03851680855260ce8452828520805460001901905587855260cd909352818420805490911690555192935084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166310b83dc08487878661396f8b6139e3565b6065546040516001600160e01b031960e089901b1681526139a095949392916001600160a01b031690600401614831565b60206040518083038185885af11580156139be573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906132899190614883565b63ffffffff8116600090815260ca6020526040902054606090610d5a90613a7a565b6000828152600284016020526040812082905561123a8484613a98565b60008181526001830160205260408120541515611d39565b6000610d5a825490565b6000826000018281548110613a5b57613a5b61448c565b9060005260206000200154905092915050565b6000611d398383613aa4565b6060610d5a6000833360405180602001604052806000815250613b97565b6000611d398383613bcc565b60008181526001830160205260408120548015613b8d576000613ac8600183614522565b8554909150600090613adc90600190614522565b9050818114613b41576000866000018281548110613afc57613afc61448c565b9060005260206000200154905080876000018481548110613b1f57613b1f61448c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613b5257613b526148ec565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d5a565b6000915050610d5a565b6060600185858585604051602001613bb3959493929190614902565b6040516020818303038152906040529050949350505050565b6000818152600183016020526040812054613c1357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d5a565b506000610d5a565b6001600160e01b03198116811461105757600080fd5b600060208284031215613c4357600080fd5b8135611d3981613c1b565b60005b83811015613c69578181015183820152602001613c51565b50506000910152565b60008151808452613c8a816020860160208601613c4e565b601f01601f19169290920160200192915050565b602081526000611d396020830184613c72565b600060208284031215613cc357600080fd5b5035919050565b80356001600160a01b0381168114613ce157600080fd5b919050565b60008060408385031215613cf957600080fd5b613d0283613cca565b946020939093013593505050565b600060208284031215613d2257600080fd5b611d3982613cca565b600080600060608486031215613d4057600080fd5b613d4984613cca565b9250613d5760208501613cca565b9150604084013590509250925092565b803561ffff81168114613ce157600080fd5b600060208284031215613d8b57600080fd5b611d3982613d67565b803563ffffffff81168114613ce157600080fd5b600060208284031215613dba57600080fd5b611d3982613d94565b60008060408385031215613dd657600080fd5b613ddf83613cca565b9150613ded60208401613d67565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613e3457835163ffffffff1683529284019291840191600101613e12565b50909695505050505050565b60008060408385031215613e5357600080fd5b613d0283613d94565b60008083601f840112613e6e57600080fd5b5081356001600160401b03811115613e8557600080fd5b6020830191508360208260051b850101111561298257600080fd5b600080600060408486031215613eb557600080fd5b83356001600160401b03811115613ecb57600080fd5b613ed786828701613e5c565b9094509250613eea905060208501613d67565b90509250925092565b60008083601f840112613f0557600080fd5b5081356001600160401b03811115613f1c57600080fd5b60208301915083602082850101111561298257600080fd5b60008060008060608587031215613f4a57600080fd5b613f5385613d94565b93506020850135925060408501356001600160401b03811115613f7557600080fd5b613f8187828801613ef3565b95989497509550505050565b60008060408385031215613fa057600080fd5b82359150613ded60208401613cca565b60008060208385031215613fc357600080fd5b82356001600160401b03811115613fd957600080fd5b613fe585828601613e5c565b90969095509350505050565b60008060006060848603121561400657600080fd5b61400f84613d94565b95602085013595506040909401359392505050565b6000806040838503121561403757600080fd5b61404083613cca565b91506020830135801515811461405557600080fd5b809150509250929050565b6000806020838503121561407357600080fd5b82356001600160401b038082111561408a57600080fd5b818501915085601f83011261409e57600080fd5b8135818111156140ad57600080fd5b8660208260061b85010111156140c257600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561410057600080fd5b61410985613cca565b935061411760208601613cca565b92506040850135915060608501356001600160401b038082111561413a57600080fd5b818701915087601f83011261414e57600080fd5b813581811115614160576141606140d4565b604051601f8201601f19908116603f01168101908382118183101715614188576141886140d4565b816040528281528a60208487010111156141a157600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600080600080604085870312156141db57600080fd5b84356001600160401b03808211156141f257600080fd5b6141fe88838901613ef3565b9096509450602087013591508082111561421757600080fd5b50613f8187828801613ef3565b6000806000806040858703121561423a57600080fd5b84356001600160401b038082111561425157600080fd5b61425d88838901613e5c565b9096509450602087013591508082111561427657600080fd5b50613f8187828801613e5c565b6000806040838503121561429657600080fd5b61429f83613cca565b9150613ded60208401613cca565b600181811c908216806142c157607f821691505b6020821081036142e157634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526027908201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060408201526673657474696e6760c81b606082015260800190565b60208082526024908201527f4765744d696e744e46543732313a20496e73756666696369656e74206d696e746040820152632066656560e01b606082015260800190565b60208082526021908201527f4765744d696e744e46543732313a204d696e742065786365656473206c696d696040820152601d60fa1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000600182016143db576143db6143b3565b5060010190565b80820180821115610d5a57610d5a6143b3565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6020808252602a908201527f526566657272616c53797374656d3a20526566657272616c20626970732061726040820152690ca40e8dede40d0d2ced60b31b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417610d5a57610d5a6143b3565b6000826144d657634e487b7160e01b600052601260045260246000fd5b500490565b60208082526027908201527f4765744d696e744e46543732313a20496e76616c6964207265666572726572206040820152666164647265737360c81b606082015260800190565b81810381811115610d5a57610d5a6143b3565b60008154614542816142ad565b6001828116801561455a576001811461456f5761459e565b60ff198416875282151583028701945061459e565b8560005260208060002060005b858110156145955781548a82015290840190820161457c565b50505082870194505b5050505092915050565b60006145b48286614535565b84516145c4818360208901613c4e565b6145d081830186614535565b979650505050505050565b601f821115610f2e57600081815260208120601f850160051c810160208610156146025750805b601f850160051c820191505b8181101561249a5782815560010161460e565b6001600160401b03831115614638576146386140d4565b61464c8361464683546142ad565b836145db565b6000601f84116001811461468057600085156146685750838201355b600019600387901b1c1916600186901b178355611733565b600083815260209020601f19861690835b828110156146b15786850135825560209485019460019092019101614691565b50868210156146ce5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b7f4e6f20726f7574657220656e726f6c6c656420666f7220646f6d61696e3a20008152600082516147af81601f850160208701613c4e565b91909101601f0192915050565b600080858511156147cc57600080fd5b838611156147d957600080fd5b5050820193919092039150565b80356020831015610d5a57600019602084900360031b1b1692915050565b83815282602082015260008251614822816040850160208701613c4e565b91909101604001949350505050565b63ffffffff8616815284602082015260a06040820152600061485660a0830186613c72565b82810360608401526148688186613c72565b91505060018060a01b03831660808301529695505050505050565b60006020828403121561489557600080fd5b5051919050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061159e90830184613c72565b6000602082840312156148e157600080fd5b8151611d3981613c1b565b634e487b7160e01b600052603160045260246000fd5b61ffff60f01b8660f01b1681528460028201528360228201526bffffffffffffffffffffffff198360601b16604282015260008251614948816056850160208701613c4e565b91909101605601969550505050505056fedc9e7f115f499a243fe74d676de78b20c5c147ba36ff1e3bfc8d9f1821d30385a26469706673582212200dbea87b85038fba469b19bb6460a59d9720a74a88129da45ae72738643a942d64736f6c634300081300330000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000001914bd28f627031bd6fa0d82bc717548208d0000000000000000000000000000000000000000000000000000000b5e620f4800000000000000000000000000000000000000000000000000000001b48eb57e0000000000000000000000000000000000000000000000000000000000005f5e1000000000000000000000000000000000000000000000000000000000000000006
Deployed Bytecode
0x60806040526004361061041b5760003560e01c806381b4e8b41161021e578063c415b95c11610123578063de523cf3116100ab578063eddd0d9c1161007a578063eddd0d9c14610c88578063efae508a14610ca8578063f2ed8c5314610cc8578063f2fde38b14610ce8578063f39c504c14610d0857600080fd5b8063de523cf314610bce578063e3d078dc14610bee578063e9198bf914610c1f578063e985e9c514610c3f57600080fd5b8063ce6e23b2116100f2578063ce6e23b214610b0e578063d082e38114610b42578063d11ba61414610b58578063d294f09314610b85578063d5438eae14610b9a57600080fd5b8063c415b95c14610a93578063c87b56dd14610ab3578063cb253c4614610ad3578063cbc1418a14610aee57600080fd5b80639236197a116101a6578063a22cb46511610175578063a22cb465146109f3578063a42dce8014610a13578063b1bd643614610a33578063b49c53a714610a53578063b88d4fde14610a7357600080fd5b80639236197a1461098b57806395d89b41146109ab578063998cdf83146109c0578063a14d4699146109e057600080fd5b80638cfd1a65116101ed5780638cfd1a65146108b25780638d3638f4146108c75780638da5cb5b14610910578063918f86741461092e57806391ba317a1461095757600080fd5b806381b4e8b41461086157806382b12dd7146108745780638456cb591461088a5780638467be0d1461089f57600080fd5b806342aeaaf9116103245780636141cc09116102ac578063715018a61161027b578063715018a6146107c957806371a15b38146107de578063775313a1146107fe578063777133dd1461082b5780637f5a7c7b1461084157600080fd5b80636141cc091461075e5780636352211e14610774578063641ddc2e1461079457806370a08231146107a957600080fd5b80634e886281116102f35780634e886281146106e05780634f6ccce71461070057806356d5d475146107205780635c975abb146107335780635f74172c1461074b57600080fd5b806342aeaaf914610651578063440df4f41461067e57806349d462ef146106a05780634b7784c1146106c057600080fd5b806323b872dd116103a757806337bb76dc1161037657806337bb76dc146105c75780633ca4fb76146105e75780633dfd3873146105fc5780633f4ba83a1461061c57806342842e0e1461063157600080fd5b806323b872dd146105475780632643bf5f146105675780632ead72f6146105875780632f745c59146105a757600080fd5b80630b2b1955116103ee5780630b2b1955146104d15780630e72cc06146104e65780631249c58b1461050657806313966db51461050e57806318160ddd1461053257600080fd5b806301ffc9a71461042057806306fdde0314610455578063081812fc14610477578063095ea7b3146104af575b600080fd5b34801561042c57600080fd5b5061044061043b366004613c31565b610d35565b60405190151581526020015b60405180910390f35b34801561046157600080fd5b5061046a610d60565b60405161044c9190613c9e565b34801561048357600080fd5b50610497610492366004613cb1565b610df2565b6040516001600160a01b03909116815260200161044c565b3480156104bb57600080fd5b506104cf6104ca366004613ce6565b610e19565b005b3480156104dd57600080fd5b506104cf610f33565b3480156104f257600080fd5b506104cf610501366004613d10565b61105a565b6104cf6110c1565b34801561051a57600080fd5b5061052460dc5481565b60405190815260200161044c565b34801561053e57600080fd5b5060d354610524565b34801561055357600080fd5b506104cf610562366004613d2b565b6111ac565b34801561057357600080fd5b506104cf610582366004613d79565b6111dd565b34801561059357600080fd5b506105246105a2366004613da8565b611223565b3480156105b357600080fd5b506105246105c2366004613ce6565b611242565b3480156105d357600080fd5b506104cf6105e2366004613dc3565b6112d8565b3480156105f357600080fd5b5061046a611335565b34801561060857600080fd5b506104cf610617366004613d10565b6113c3565b34801561062857600080fd5b506104cf61142a565b34801561063d57600080fd5b506104cf61064c366004613d2b565b611442565b34801561065d57600080fd5b5061052461066c366004613d10565b60e16020526000908152604090205481565b34801561068a57600080fd5b5061069361145d565b60405161044c9190613df6565b3480156106ac57600080fd5b506104cf6106bb366004613e40565b61146e565b3480156106cc57600080fd5b506104cf6106db366004613ea0565b611494565b3480156106ec57600080fd5b506105246106fb366004613ce6565b61153e565b34801561070c57600080fd5b5061052461071b366004613cb1565b6115a8565b6104cf61072e366004613f34565b61163b565b34801561073f57600080fd5b5060d55460ff16610440565b6104cf610759366004613f8d565b61173a565b34801561076a57600080fd5b5061052460de5481565b34801561078057600080fd5b5061049761078f366004613cb1565b611901565b3480156107a057600080fd5b506104cf611961565b3480156107b557600080fd5b506105246107c4366004613d10565b611ae7565b3480156107d557600080fd5b506104cf611af2565b3480156107ea57600080fd5b506104cf6107f9366004613fb0565b611b04565b34801561080a57600080fd5b50610524610819366004613da8565b60ca6020526000908152604090205481565b34801561083757600080fd5b5061052460dd5481565b34801561084d57600080fd5b50606554610497906001600160a01b031681565b61052461086f366004613ff1565b611b59565b34801561088057600080fd5b5061052460db5481565b34801561089657600080fd5b506104cf611d40565b6104cf6108ad366004613cb1565b611d58565b3480156108be57600080fd5b5061046a611e68565b3480156108d357600080fd5b506108fb7f000000000000000000000000000000000000000000000000000000000008275081565b60405163ffffffff909116815260200161044c565b34801561091c57600080fd5b506033546001600160a01b0316610497565b34801561093a57600080fd5b5061094461271081565b60405161ffff909116815260200161044c565b34801561096357600080fd5b506105247f0000000000000000000000000000000000000000000000000000000029b9270081565b34801561099757600080fd5b506105246109a6366004613da8565b611e75565b3480156109b757600080fd5b5061046a611e91565b3480156109cc57600080fd5b506104cf6109db366004613cb1565b611ea0565b6104cf6109ee366004613d10565b611ead565b3480156109ff57600080fd5b506104cf610a0e366004614024565b612048565b348015610a1f57600080fd5b506104cf610a2e366004613d10565b612053565b348015610a3f57600080fd5b506104cf610a4e366004614060565b6120f1565b348015610a5f57600080fd5b506104cf610a6e366004613e40565b612176565b348015610a7f57600080fd5b506104cf610a8e3660046140ea565b612188565b348015610a9f57600080fd5b5060da54610497906001600160a01b031681565b348015610abf57600080fd5b5061046a610ace366004613cb1565b6121b9565b348015610adf57600080fd5b5060df546109449061ffff1681565b348015610afa57600080fd5b506104cf610b093660046141c5565b6121f0565b348015610b1a57600080fd5b506105247f0000000000000000000000000000000000000000000000000000000023c3460181565b348015610b4e57600080fd5b5061052460d75481565b348015610b6457600080fd5b50610524610b73366004613d10565b60e26020526000908152604090205481565b348015610b9157600080fd5b506104cf612213565b348015610ba657600080fd5b506104977f0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a781565b348015610bda57600080fd5b50606654610497906001600160a01b031681565b348015610bfa57600080fd5b50610944610c09366004613d10565b60e06020526000908152604090205461ffff1681565b348015610c2b57600080fd5b506104cf610c3a366004614224565b6123f3565b348015610c4b57600080fd5b50610440610c5a366004614283565b6001600160a01b03918216600090815260d06020908152604080832093909416825291909152205460ff1690565b348015610c9457600080fd5b506104cf610ca3366004613cb1565b6124a2565b348015610cb457600080fd5b506104cf610cc3366004613da8565b6124af565b348015610cd457600080fd5b50610524610ce3366004613da8565b6124c0565b348015610cf457600080fd5b506104cf610d03366004613d10565b6124db565b348015610d1457600080fd5b50610524610d23366004613d10565b60e36020526000908152604090205481565b60006001600160e01b0319821663780e9d6360e01b1480610d5a5750610d5a82612551565b92915050565b606060cb8054610d6f906142ad565b80601f0160208091040260200160405190810160405280929190818152602001828054610d9b906142ad565b8015610de85780601f10610dbd57610100808354040283529160200191610de8565b820191906000526020600020905b815481529060010190602001808311610dcb57829003601f168201915b5050505050905090565b6000610dfd826125a1565b50600090815260cf60205260409020546001600160a01b031690565b6000610e2482611901565b9050806001600160a01b0316836001600160a01b031603610e965760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610eb25750610eb28133610c5a565b610f245760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610e8d565b610f2e8383612600565b505050565b60da546001600160a01b0316336001600160a01b03161480610f5f57506033546001600160a01b031633145b610fbf5760405162461bcd60e51b815260206004820152602b60248201527f5265737175653a204f6e6c792066656520636f6c6c6563746f72206f72206f7760448201526a1b995c88185b1b1bddd95960aa1b6064820152608401610e8d565b604051600090339047908381818185875af1925050503d8060008114611001576040519150601f19603f3d011682016040523d82523d6000602084013e611006565b606091505b50509050806110575760405162461bcd60e51b815260206004820152601d60248201527f5265737175653a20204661696c656420746f2073656e642045746865720000006044820152606401610e8d565b50565b806001600160a01b0381163b15158061107a57506001600160a01b038116155b6110965760405162461bcd60e51b8152600401610e8d906142e7565b61109e61266e565b50606680546001600160a01b0319166001600160a01b0392909216919091179055565b6110c96126c8565b6110d1612721565b60dc5434146110f25760405162461bcd60e51b8152600401610e8d9061432e565b60d7547f0000000000000000000000000000000000000000000000000000000029b927008111156111355760405162461bcd60e51b8152600401610e8d90614372565b60d760008154611144906143c9565b9091555060dc5460dd805460009061115d9084906143e2565b9091555061116e9050335b82612767565b60dc5460408051918252600060208301819052918391339160008051602061495a833981519152910160405180910390a4506111aa600160d655565b565b6111b63382612781565b6111d25760405162461bcd60e51b8152600401610e8d906143f5565b610f2e8383836127ff565b6111e561266e565b61271061ffff8216111561120b5760405162461bcd60e51b8152600401610e8d90614442565b60df805461ffff191661ffff92909216919091179055565b60008061123a609763ffffffff8086169061297016565b949350505050565b600061124d83612989565b82106112af5760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610e8d565b506001600160a01b0391909116600090815260d160209081526040808320938352929052205490565b6112e061266e565b61271061ffff821611156113065760405162461bcd60e51b8152600401610e8d90614442565b6001600160a01b0391909116600090815260e060205260409020805461ffff191661ffff909216919091179055565b60d88054611342906142ad565b80601f016020809104026020016040519081016040528092919081815260200182805461136e906142ad565b80156113bb5780601f10611390576101008083540402835291602001916113bb565b820191906000526020600020905b81548152906001019060200180831161139e57829003601f168201915b505050505081565b806001600160a01b0381163b1515806113e357506001600160a01b038116155b6113ff5760405162461bcd60e51b8152600401610e8d906142e7565b61140761266e565b50606580546001600160a01b0319166001600160a01b0392909216919091179055565b61143261266e565b61143a612a0f565b6111aa612a58565b610f2e83838360405180602001604052806000815250612188565b60606114696097612aaa565b905090565b61147661266e565b63ffffffff91909116600090815260ca6020526040902055565b5050565b61149c61266e565b61271061ffff821611156114c25760405162461bcd60e51b8152600401610e8d90614442565b60005b82811015611538578160e060008686858181106114e4576114e461448c565b90506020020160208101906114f99190613d10565b6001600160a01b031681526020810191909152604001600020805461ffff191661ffff9290921691909117905580611530816143c9565b9150506114c5565b50505050565b6001600160a01b038216600090815260e0602052604081205461ffff168181156115685781611570565b60df5461ffff165b90508060000361158557600092505050610d5a565b600061271061159483876144a2565b61159e91906144b9565b9695505050505050565b60006115b360d35490565b82106116165760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610e8d565b60d382815481106116295761162961448c565b90600052602060002001549050919050565b336001600160a01b037f0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a716146116bd5760405162461bcd60e51b815260206004820152602160248201527f4d61696c626f78436c69656e743a2073656e646572206e6f74206d61696c626f6044820152600f60fb1b6064820152608401610e8d565b60006116c885612b64565b90508381146117275760405162461bcd60e51b815260206004820152602560248201527f456e726f6c6c656420726f7574657220646f6573206e6f74206d61746368207360448201526432b73232b960d91b6064820152608401610e8d565b61173385858585612bb0565b5050505050565b6117426126c8565b61174a612721565b336001600160a01b0382161480159061176b57506001600160a01b03811615155b6117875760405162461bcd60e51b8152600401610e8d906144db565b8160dc5461179591906144a2565b34146117b35760405162461bcd60e51b8152600401610e8d9061432e565b60005b828110156118f65760d7547f0000000000000000000000000000000000000000000000000000000029b927008111156118015760405162461bcd60e51b8152600401610e8d90614372565b60dc546000611810858361153e565b905060d760008154611821906143c9565b9091555061182f8183614522565b60dd600082825461184091906143e2565b90915550506001600160a01b038516600090815260e260205260408120805483929061186d9084906143e2565b90915550506001600160a01b038516600090815260e1602052604081208054909190611898906143c9565b909155506118a7335b84612767565b60dc5460408051918252602082018390526001600160a01b038716918591339160008051602061495a833981519152910160405180910390a450505080806118ee906143c9565b9150506117b6565b50611490600160d655565b600081815260cd60205260408120546001600160a01b031680610d5a5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b6119696126c8565b33600090815260e26020526040902054806119b95760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b6044820152606401610e8d565b33600081815260e26020908152604080832083905560e3909152812080548492906119e59084906143e2565b90915550506040516000906001600160a01b0383169084908381818185875af1925050503d8060008114611a35576040519150601f19603f3d011682016040523d82523d6000602084013e611a3a565b606091505b5050905080611a975760405162461bcd60e51b8152602060048201526024808201527f526566657272616c53797374656d3a204661696c656420746f2073656e6420456044820152633a3432b960e11b6064820152608401610e8d565b816001600160a01b03167fa6183a81b1ce4e0d90156f6ec9b6f2d13c204d11884302b40b47bb456fb5915684604051611ad291815260200190565b60405180910390a25050506111aa600160d655565b6000610d5a82612989565b611afa61266e565b6111aa6000612c3a565b611b0c61266e565b8060005b8181101561153857611b47848483818110611b2d57611b2d61448c565b9050602002016020810190611b429190613da8565b612c8c565b611b526001826143e2565b9050611b10565b6000611b636126c8565b611b6b612721565b82611bb85760405162461bcd60e51b815260206004820152601f60248201527f4765744d696e744e46543732313a20496e76616c6964207265636569766572006044820152606401610e8d565b611bc3335b83612781565b611c2c5760405162461bcd60e51b815260206004820152603460248201527f4765744d696e744e46543732313a2073656e642063616c6c6572206973206e6f6044820152731d081bdddb995c881b9bdc88185c1c1c9bdd995960621b6064820152608401610e8d565b6000611c3785611e75565b905060db5481611c4791906143e2565b341015611ca55760405162461bcd60e51b815260206004820152602660248201527f4765744d696e744e46543732313a20496e636f7272656374206d6573736167656044820152652076616c756560d01b6064820152608401610e8d565b60db5460dd6000828254611cb991906143e2565b92505081905550611cd985858560db5434611cd49190614522565b612cc7565b60db546040805186815260208101929092529193506001600160a01b0386169163ffffffff88169133917f8c76f9a0946e85f2e4c199f247a3436d1766156d4ce90144bf16dfb353878ade910160405180910390a450611d39600160d655565b9392505050565b611d4861266e565b611d50612721565b6111aa612d36565b611d606126c8565b611d68612721565b8060dc54611d7691906144a2565b3414611d945760405162461bcd60e51b8152600401610e8d9061432e565b60005b81811015611e5d5760d7547f0000000000000000000000000000000000000000000000000000000029b92700811115611de25760405162461bcd60e51b8152600401610e8d90614372565b60d760008154611df1906143c9565b9091555060dc5460dd8054600090611e0a9084906143e2565b90915550611e19905033611168565b60dc5460408051918252600060208301819052918391339160008051602061495a833981519152910160405180910390a45080611e55816143c9565b915050611d97565b50611057600160d655565b60d98054611342906142ad565b600080611d398360405180602001604052806000815250612d73565b606060cc8054610d6f906142ad565b611ea861266e565b60db55565b611eb56126c8565b611ebd612721565b336001600160a01b03821614801590611ede57506001600160a01b03811615155b611efa5760405162461bcd60e51b8152600401610e8d906144db565b60dc543414611f1b5760405162461bcd60e51b8152600401610e8d9061432e565b60d7547f0000000000000000000000000000000000000000000000000000000029b92700811115611f5e5760405162461bcd60e51b8152600401610e8d90614372565b60dc546000611f6d848361153e565b905060d760008154611f7e906143c9565b90915550611f8c8183614522565b60dd6000828254611f9d91906143e2565b90915550506001600160a01b038416600090815260e2602052604081208054839290611fca9084906143e2565b90915550506001600160a01b038416600090815260e1602052604081208054909190611ff5906143c9565b90915550612002336118a1565b60dc5460408051918252602082018390526001600160a01b038616918591339160008051602061495a833981519152910160405180910390a4505050611057600160d655565b611490338383612d8c565b61205b61266e565b6001600160a01b0381166120cf5760405162461bcd60e51b815260206004820152603560248201527f4765744d696e744e46543732313a2046656520636f6c6c6563746f72206d757360448201527474206265206e6f6e2d7a65726f206164647265737360581b6064820152608401610e8d565b60da80546001600160a01b0319166001600160a01b0392909216919091179055565b6120f961266e565b60005b81811015610f2e576121648383838181106121195761211961448c565b61212f9260206040909202019081019150613da8565b8484848181106121415761214161448c565b9050604002016020013563ffffffff909116600090815260ca6020526040902055565b61216f6001826143e2565b90506120fc565b61217e61266e565b6114908282612e5a565b61219133611bbd565b6121ad5760405162461bcd60e51b8152600401610e8d906143f5565b61153884848484612e70565b606060d86121c683612ea3565b60d96040516020016121da939291906145a8565b6040516020818303038152906040529050919050565b6121f861266e565b60d8612205848683614621565b5060d9611733828483614621565b61221b6126c8565b60da546001600160a01b0316336001600160a01b0316146122905760405162461bcd60e51b815260206004820152602960248201527f4765744d696e744e46543732313a204f6e6c792066656520636f6c6c6563746f6044820152681c88185b1b1bddd95960ba1b6064820152608401610e8d565b60dd5460008190036122e45760405162461bcd60e51b815260206004820152601f60248201527f4765744d696e744e46543732313a204e6f7468696e6720746f20636c61696d006044820152606401610e8d565b600060dd819055508060de60008282546122fe91906143e2565b909155505060da546040516000916001600160a01b03169083908381818185875af1925050503d8060008114612350576040519150601f19603f3d011682016040523d82523d6000602084013e612355565b606091505b50509050806123b25760405162461bcd60e51b815260206004820152602360248201527f4765744d696e744e46543732313a204661696c656420746f2073656e642045746044820152623432b960e91b6064820152608401610e8d565b60405182815233907f582c87414358df39212a275853c71633d2dc65d15ae92cc5718e7438766bea769060200160405180910390a250506111aa600160d655565b6123fb61266e565b8281146124345760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610e8d565b8260005b8181101561249a576124888686838181106124555761245561448c565b905060200201602081019061246a9190613da8565b85858481811061247c5761247c61448c565b90506020020135612e5a565b6124936001826143e2565b9050612438565b505050505050565b6124aa61266e565b60dc55565b6124b761266e565b61105781612c8c565b6000610d5a8260405180602001604052806000815250612d73565b6124e361266e565b6001600160a01b0381166125485760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e8d565b61105781612c3a565b60006001600160e01b031982166380ac58cd60e01b148061258257506001600160e01b03198216635b5e139f60e01b145b80610d5a57506301ffc9a760e01b6001600160e01b0319831614610d5a565b600081815260cd60205260409020546001600160a01b03166110575760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610e8d565b600081815260cf6020526040902080546001600160a01b0319166001600160a01b038416908117909155819061263582611901565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6033546001600160a01b031633146111aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e8d565b600260d6540361271a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610e8d565b600260d655565b60d55460ff16156111aa5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610e8d565b611490828260405180602001604052806000815250612f35565b60008061278d83611901565b9050806001600160a01b0316846001600160a01b031614806127d457506001600160a01b03808216600090815260d0602090815260408083209388168352929052205460ff165b8061123a5750836001600160a01b03166127ed84610df2565b6001600160a01b031614949350505050565b826001600160a01b031661281282611901565b6001600160a01b0316146128385760405162461bcd60e51b8152600401610e8d906146e0565b6001600160a01b03821661289a5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610e8d565b6128a78383836001612f68565b826001600160a01b03166128ba82611901565b6001600160a01b0316146128e05760405162461bcd60e51b8152600401610e8d906146e0565b600081815260cf6020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260ce855283862080546000190190559087168086528386208054600101905586865260cd90945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b60008061297d8484613095565b915091505b9250929050565b60006001600160a01b0382166129f35760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610e8d565b506001600160a01b0316600090815260ce602052604090205490565b60d55460ff166111aa5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610e8d565b612a60612a0f565b60d5805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b60606000612ab7836130cf565b905080516001600160401b03811115612ad257612ad26140d4565b604051908082528060200260200182016040528015612afb578160200160208202803683370190505b50915060005b8151811015612b5d57818181518110612b1c57612b1c61448c565b6020026020010151838281518110612b3657612b3661448c565b63ffffffff9092166020928302919091019091015280612b55816143c9565b915050612b01565b5050919050565b60008080612b7c609763ffffffff8087169061297016565b9150915081612b8a85613169565b90612ba85760405162461bcd60e51b8152600401610e8d9190613c9e565b509392505050565b6000612bbc838361318a565b90506000612bca84846131a2565b9050366000612bd986866131b2565b91509150612bef612be78590565b8484846131c2565b838863ffffffff167fba20947a325f450d232530e5f5fce293e7963499d5309a07cee84a269f2f15a685604051612c2891815260200190565b60405180910390a35050505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b612ca0609763ffffffff808416906131cc16565b612ca982613169565b906114905760405162461bcd60e51b8152600401610e8d9190613c9e565b600080612cd3846131d8565b9050612cea8684612ce5888886613240565b61326f565b9150848663ffffffff167fd229aacb94204188fe8042965fa6b269c62dc5818b21238779ab64bdd17efeec86604051612d2591815260200190565b60405180910390a350949350505050565b612d3e612721565b60d5805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612a8d3390565b600080612d7f84612b64565b905061123a848285613292565b816001600160a01b0316836001600160a01b031603612ded5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610e8d565b6001600160a01b03838116600081815260d06020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611490609763ffffffff80851690849061334116565b612e7b8484846127ff565b612e878484848461334c565b6115385760405162461bcd60e51b8152600401610e8d90614725565b60606000612eb08361344d565b60010190506000816001600160401b03811115612ecf57612ecf6140d4565b6040519080825280601f01601f191660200182016040528015612ef9576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a8504945084612f0357509392505050565b612f3f8383613525565b612f4c600084848461334c565b610f2e5760405162461bcd60e51b8152600401610e8d90614725565b6001811115612fd75760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b6064820152608401610e8d565b816001600160a01b0385166130335761302e8160d38054600083815260d460205260408120829055600182018355919091527f915c3eb987b20e1af620c1403197bf687fb7f18513b3a73fde6e78c7072c41a60155565b613056565b836001600160a01b0316856001600160a01b0316146130565761305685826136be565b6001600160a01b0384166130725761306d8161375b565b611733565b846001600160a01b0316846001600160a01b03161461173357611733848261380a565b60008181526002830160205260408120548190806130c4576130b7858561384e565b9250600091506129829050565b600192509050612982565b606060006130dc8361385a565b9050806001600160401b038111156130f6576130f66140d4565b60405190808252806020026020018201604052801561311f578160200160208202803683370190505b50915060005b81811015612b5d576131378482613865565b60001c83828151811061314c5761314c61448c565b602090810291909101015280613161816143c9565b915050613125565b606061317a8263ffffffff16612ea3565b6040516020016121da9190614777565b600061319960208284866147bc565b611d39916147e6565b60006131996040602084866147bc565b36600061297d83604081876147bc565b6115388484612767565b6000611d398383613871565b6060336131e483611901565b6001600160a01b0316146132235760405162461bcd60e51b815260206004820152600660248201526510b7bbb732b960d11b6044820152606401610e8d565b61322c8261388e565b505060408051602081019091526000815290565b606083838360405160200161325793929190614804565b60405160208183030381529060405290509392505050565b60008061327b85612b64565b905061328985828686613931565b95945050505050565b60007f0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a76001600160a01b03166381d2ea958585856132cf896139e3565b6065546040516001600160e01b031960e088901b16815261330095949392916001600160a01b031690600401614831565b602060405180830381865afa15801561331d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061123a9190614883565b611538838383613a05565b60006001600160a01b0384163b1561344257604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061339090339089908890889060040161489c565b6020604051808303816000875af19250505080156133cb575060408051601f3d908101601f191682019092526133c8918101906148cf565b60015b613428573d8080156133f9576040519150601f19603f3d011682016040523d82523d6000602084013e6133fe565b606091505b5080516000036134205760405162461bcd60e51b8152600401610e8d90614725565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061123a565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061348c5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106134b8576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106134d657662386f26fc10000830492506010015b6305f5e10083106134ee576305f5e100830492506008015b612710831061350257612710830492506004015b60648310613514576064830492506002015b600a8310610d5a5760010192915050565b6001600160a01b03821661357b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610e8d565b600081815260cd60205260409020546001600160a01b0316156135e05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6135ee600083836001612f68565b600081815260cd60205260409020546001600160a01b0316156136535760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610e8d565b6001600160a01b038216600081815260ce602090815260408083208054600101905584835260cd90915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b600060016136cb84612989565b6136d59190614522565b600083815260d26020526040902054909150808214613728576001600160a01b038416600090815260d160209081526040808320858452825280832054848452818420819055835260d290915290208190555b50600091825260d2602090815260408084208490556001600160a01b03909416835260d181528383209183525290812055565b60d35460009061376d90600190614522565b600083815260d4602052604081205460d380549394509092849081106137955761379561448c565b906000526020600020015490508060d383815481106137b6576137b661448c565b600091825260208083209091019290925582815260d4909152604080822084905585825281205560d38054806137ee576137ee6148ec565b6001900381819060005260206000200160009055905550505050565b600061381583612989565b6001600160a01b03909316600090815260d160209081526040808320868452825280832085905593825260d29052919091209190915550565b6000611d398383613a22565b6000610d5a82613a3a565b6000611d398383613a44565b60008181526002830160205260408120819055611d398383613a6e565b600061389982611901565b90506138a9816000846001612f68565b6138b282611901565b600083815260cf6020908152604080832080546001600160a01b03199081169091556001600160a01b03851680855260ce8452828520805460001901905587855260cd909352818420805490911690555192935084927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b60007f0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a76001600160a01b03166310b83dc08487878661396f8b6139e3565b6065546040516001600160e01b031960e089901b1681526139a095949392916001600160a01b031690600401614831565b60206040518083038185885af11580156139be573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906132899190614883565b63ffffffff8116600090815260ca6020526040902054606090610d5a90613a7a565b6000828152600284016020526040812082905561123a8484613a98565b60008181526001830160205260408120541515611d39565b6000610d5a825490565b6000826000018281548110613a5b57613a5b61448c565b9060005260206000200154905092915050565b6000611d398383613aa4565b6060610d5a6000833360405180602001604052806000815250613b97565b6000611d398383613bcc565b60008181526001830160205260408120548015613b8d576000613ac8600183614522565b8554909150600090613adc90600190614522565b9050818114613b41576000866000018281548110613afc57613afc61448c565b9060005260206000200154905080876000018481548110613b1f57613b1f61448c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613b5257613b526148ec565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610d5a565b6000915050610d5a565b6060600185858585604051602001613bb3959493929190614902565b6040516020818303038152906040529050949350505050565b6000818152600183016020526040812054613c1357508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610d5a565b506000610d5a565b6001600160e01b03198116811461105757600080fd5b600060208284031215613c4357600080fd5b8135611d3981613c1b565b60005b83811015613c69578181015183820152602001613c51565b50506000910152565b60008151808452613c8a816020860160208601613c4e565b601f01601f19169290920160200192915050565b602081526000611d396020830184613c72565b600060208284031215613cc357600080fd5b5035919050565b80356001600160a01b0381168114613ce157600080fd5b919050565b60008060408385031215613cf957600080fd5b613d0283613cca565b946020939093013593505050565b600060208284031215613d2257600080fd5b611d3982613cca565b600080600060608486031215613d4057600080fd5b613d4984613cca565b9250613d5760208501613cca565b9150604084013590509250925092565b803561ffff81168114613ce157600080fd5b600060208284031215613d8b57600080fd5b611d3982613d67565b803563ffffffff81168114613ce157600080fd5b600060208284031215613dba57600080fd5b611d3982613d94565b60008060408385031215613dd657600080fd5b613ddf83613cca565b9150613ded60208401613d67565b90509250929050565b6020808252825182820181905260009190848201906040850190845b81811015613e3457835163ffffffff1683529284019291840191600101613e12565b50909695505050505050565b60008060408385031215613e5357600080fd5b613d0283613d94565b60008083601f840112613e6e57600080fd5b5081356001600160401b03811115613e8557600080fd5b6020830191508360208260051b850101111561298257600080fd5b600080600060408486031215613eb557600080fd5b83356001600160401b03811115613ecb57600080fd5b613ed786828701613e5c565b9094509250613eea905060208501613d67565b90509250925092565b60008083601f840112613f0557600080fd5b5081356001600160401b03811115613f1c57600080fd5b60208301915083602082850101111561298257600080fd5b60008060008060608587031215613f4a57600080fd5b613f5385613d94565b93506020850135925060408501356001600160401b03811115613f7557600080fd5b613f8187828801613ef3565b95989497509550505050565b60008060408385031215613fa057600080fd5b82359150613ded60208401613cca565b60008060208385031215613fc357600080fd5b82356001600160401b03811115613fd957600080fd5b613fe585828601613e5c565b90969095509350505050565b60008060006060848603121561400657600080fd5b61400f84613d94565b95602085013595506040909401359392505050565b6000806040838503121561403757600080fd5b61404083613cca565b91506020830135801515811461405557600080fd5b809150509250929050565b6000806020838503121561407357600080fd5b82356001600160401b038082111561408a57600080fd5b818501915085601f83011261409e57600080fd5b8135818111156140ad57600080fd5b8660208260061b85010111156140c257600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561410057600080fd5b61410985613cca565b935061411760208601613cca565b92506040850135915060608501356001600160401b038082111561413a57600080fd5b818701915087601f83011261414e57600080fd5b813581811115614160576141606140d4565b604051601f8201601f19908116603f01168101908382118183101715614188576141886140d4565b816040528281528a60208487010111156141a157600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600080600080604085870312156141db57600080fd5b84356001600160401b03808211156141f257600080fd5b6141fe88838901613ef3565b9096509450602087013591508082111561421757600080fd5b50613f8187828801613ef3565b6000806000806040858703121561423a57600080fd5b84356001600160401b038082111561425157600080fd5b61425d88838901613e5c565b9096509450602087013591508082111561427657600080fd5b50613f8187828801613e5c565b6000806040838503121561429657600080fd5b61429f83613cca565b9150613ded60208401613cca565b600181811c908216806142c157607f821691505b6020821081036142e157634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526027908201527f4d61696c626f78436c69656e743a20696e76616c696420636f6e74726163742060408201526673657474696e6760c81b606082015260800190565b60208082526024908201527f4765744d696e744e46543732313a20496e73756666696369656e74206d696e746040820152632066656560e01b606082015260800190565b60208082526021908201527f4765744d696e744e46543732313a204d696e742065786365656473206c696d696040820152601d60fa1b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b6000600182016143db576143db6143b3565b5060010190565b80820180821115610d5a57610d5a6143b3565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b6020808252602a908201527f526566657272616c53797374656d3a20526566657272616c20626970732061726040820152690ca40e8dede40d0d2ced60b31b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417610d5a57610d5a6143b3565b6000826144d657634e487b7160e01b600052601260045260246000fd5b500490565b60208082526027908201527f4765744d696e744e46543732313a20496e76616c6964207265666572726572206040820152666164647265737360c81b606082015260800190565b81810381811115610d5a57610d5a6143b3565b60008154614542816142ad565b6001828116801561455a576001811461456f5761459e565b60ff198416875282151583028701945061459e565b8560005260208060002060005b858110156145955781548a82015290840190820161457c565b50505082870194505b5050505092915050565b60006145b48286614535565b84516145c4818360208901613c4e565b6145d081830186614535565b979650505050505050565b601f821115610f2e57600081815260208120601f850160051c810160208610156146025750805b601f850160051c820191505b8181101561249a5782815560010161460e565b6001600160401b03831115614638576146386140d4565b61464c8361464683546142ad565b836145db565b6000601f84116001811461468057600085156146685750838201355b600019600387901b1c1916600186901b178355611733565b600083815260209020601f19861690835b828110156146b15786850135825560209485019460019092019101614691565b50868210156146ce5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b7f4e6f20726f7574657220656e726f6c6c656420666f7220646f6d61696e3a20008152600082516147af81601f850160208701613c4e565b91909101601f0192915050565b600080858511156147cc57600080fd5b838611156147d957600080fd5b5050820193919092039150565b80356020831015610d5a57600019602084900360031b1b1692915050565b83815282602082015260008251614822816040850160208701613c4e565b91909101604001949350505050565b63ffffffff8616815284602082015260a06040820152600061485660a0830186613c72565b82810360608401526148688186613c72565b91505060018060a01b03831660808301529695505050505050565b60006020828403121561489557600080fd5b5051919050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061159e90830184613c72565b6000602082840312156148e157600080fd5b8151611d3981613c1b565b634e487b7160e01b600052603160045260246000fd5b61ffff60f01b8660f01b1681528460028201528360228201526bffffffffffffffffffffffff198360601b16604282015260008251614948816056850160208701613c4e565b91909101605601969550505050505056fedc9e7f115f499a243fe74d676de78b20c5c147ba36ff1e3bfc8d9f1821d30385a26469706673582212200dbea87b85038fba469b19bb6460a59d9720a74a88129da45ae72738643a942d64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a700000000000000000000000001914bd28f627031bd6fa0d82bc717548208d0000000000000000000000000000000000000000000000000000000b5e620f4800000000000000000000000000000000000000000000000000000001b48eb57e0000000000000000000000000000000000000000000000000000000000005f5e1000000000000000000000000000000000000000000000000000000000000000006
-----Decoded View---------------
Arg [0] : _mailbox (address): 0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7
Arg [1] : _feeCollector (address): 0x01914BD28f627031BD6fa0D82bC717548208D000
Arg [2] : _mintFee (uint256): 200000000000000
Arg [3] : _bridgeFee (uint256): 30000000000000
Arg [4] : _totalSupply (uint256): 100000000
Arg [5] : _idMultiplier (uint256): 6
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000002f2afae1139ce54fefc03593fee8ab2adf4a85a7
Arg [1] : 00000000000000000000000001914bd28f627031bd6fa0d82bc717548208d000
Arg [2] : 0000000000000000000000000000000000000000000000000000b5e620f48000
Arg [3] : 00000000000000000000000000000000000000000000000000001b48eb57e000
Arg [4] : 0000000000000000000000000000000000000000000000000000000005f5e100
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000006
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BASE | 36.97% | $1,779.93 | 0.9487 | $1,688.67 | |
ARB | 27.34% | $1,780.4 | 0.7015 | $1,248.89 | |
OP | 14.18% | $1,780.82 | 0.3638 | $647.8 | |
BSC | 10.93% | $604.91 | 0.8253 | $499.23 | |
SCROLL | 3.18% | $1,780.48 | 0.0816 | $145.29 | |
POL | 2.32% | $0.222707 | 474.94 | $105.77 | |
AVAX | 1.82% | $22.12 | 3.7613 | $83.21 | |
TAIKO | 1.05% | $1,780.48 | 0.027 | $48.07 | |
BLAST | 0.82% | $1,780.29 | 0.0211 | $37.55 | |
GNO | 0.66% | $0.999941 | 30.1 | $30.1 | |
CELO | 0.44% | $0.329015 | 60.6 | $19.94 | |
LINEA | 0.29% | $1,780.48 | 0.0075 | $13.35 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.