Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ScapesERC721
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {ERC165} from "@solidstate/contracts/introspection/ERC165.sol"; import {OwnableInternal} from "@solidstate/contracts/access/ownable/OwnableInternal.sol"; import {DefaultOperatorFilterer} from "operator-filter-registry/src/DefaultOperatorFilterer.sol"; import {IERC721, ERC721Base, ERC721BaseInternal, ERC721BaseStorage} from "./solidstate/ERC721Base.sol"; import {ScapesERC721MetadataStorage} from "./ScapesERC721MetadataStorage.sol"; import {IChild} from "./IChild.sol"; import {ScapesMerge} from "../metadata/ScapesMerge.sol"; import {WithFees} from "./marketplace/WithFees.sol"; import {ScapesMarketplaceStorage} from "./marketplace/ScapesMarketplaceStorage.sol"; import {IERC721MarketplaceInternal} from "./marketplace/IERC721MarketplaceInternal.sol"; /// @title ScapesERC721 /// @author akuti.eth | scapes.eth /// @notice The ERC721 functionality for Scapes /// @dev The facet to add ERC721 functionality and merging to Scapes. contract ScapesERC721 is ERC165, OwnableInternal, ERC721Base, WithFees, IERC721MarketplaceInternal, DefaultOperatorFilterer { error ScapesERC721__ChildAlreadyAdded(); error ScapesERC721__InvalidArgument(); using ERC721BaseStorage for ERC721BaseStorage.Layout; using ScapesMerge for ScapesMerge.Merge; uint256 internal constant MIN_MERGE_SIZE = 2; uint256 internal constant MAX_MERGE_SIZE = 8; /** * @notice Ceate and mint a merge out of multiple Scapes. * @dev Transfer Scape tokens to the contract and mint a merge Scape. * @param merge_ Merge settings */ function merge(ScapesMerge.Merge calldata merge_) external { if ( merge_.parts.length < MIN_MERGE_SIZE || merge_.parts.length > MAX_MERGE_SIZE ) revert ScapesERC721__InvalidArgument(); for (uint256 i = 0; i < merge_.parts.length; i++) { // transfer all containing tokens, it is supposed to fail when tokens are repeated transferFrom(msg.sender, address(this), merge_.parts[i].tokenId); } _safeMint(msg.sender, merge_.toId()); } /** * @notice Burn a merge and receive its Scapes. * @dev Burn the merge scape and transfer the contained Scapes form the contract. * @param merge_ Merge settings */ function purge(ScapesMerge.Merge calldata merge_) external { uint256 tokenId = merge_.toId(); if (_ownerOf(tokenId) != msg.sender) revert ERC721Base__NotTokenOwner(); _burn(tokenId); for (uint256 i = 0; i < merge_.parts.length; i++) { _safeTransfer( address(this), msg.sender, merge_.parts[i].tokenId, "" ); } } /** * @inheritdoc IERC721 */ function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); } /** * @inheritdoc IERC721 */ function approve(address operator, uint256 tokenId) public payable override onlyAllowedOperatorApproval(operator) { super.approve(operator, tokenId); } /** * @inheritdoc IERC721 */ function transferFrom( address from, address to, uint256 tokenId ) public payable override onlyAllowedOperator(from) { super.transferFrom(from, to, tokenId); } /** * @inheritdoc IERC721 */ function safeTransferFrom( address from, address to, uint256 tokenId ) public payable override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId); } /** * @inheritdoc IERC721 */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public payable override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId, data); } /** * @inheritdoc ERC721BaseInternal */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override(ERC721BaseInternal) { if ( from != address(0) && to != address(0) && ScapesMarketplaceStorage.layout().offers[tokenId].price > 0 ) { ScapesMarketplaceStorage.Layout storage d = ScapesMarketplaceStorage .layout(); d.offers[tokenId].price = 0; d.offers[tokenId].specificBuyer = address(0); emit OfferWithdrawn(tokenId); } super._beforeTokenTransfer(from, to, tokenId); } /** * @inheritdoc ERC721BaseInternal */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override(ERC721BaseInternal) { IChild(ScapesERC721MetadataStorage.layout().scapeBound).update( from, to, tokenId ); super._afterTokenTransfer(from, to, tokenId); } /** * @notice The total Scapes supply (ignoring Merges) */ function totalSupply() external pure returns (uint256) { return 10_000; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC173Internal } from '../../interfaces/IERC173Internal.sol'; interface IOwnableInternal is IERC173Internal { error Ownable__NotOwner(); error Ownable__NotTransitiveOwner(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC173 } from '../../interfaces/IERC173.sol'; import { AddressUtils } from '../../utils/AddressUtils.sol'; import { IOwnableInternal } from './IOwnableInternal.sol'; import { OwnableStorage } from './OwnableStorage.sol'; abstract contract OwnableInternal is IOwnableInternal { using AddressUtils for address; using OwnableStorage for OwnableStorage.Layout; modifier onlyOwner() { if (msg.sender != _owner()) revert Ownable__NotOwner(); _; } modifier onlyTransitiveOwner() { if (msg.sender != _transitiveOwner()) revert Ownable__NotTransitiveOwner(); _; } function _owner() internal view virtual returns (address) { return OwnableStorage.layout().owner; } function _transitiveOwner() internal view virtual returns (address) { address owner = _owner(); while (owner.isContract()) { try IERC173(owner).owner() returns (address transitiveOwner) { owner = transitiveOwner; } catch { return owner; } } return owner; } function _transferOwnership(address account) internal virtual { OwnableStorage.layout().setOwner(account); emit OwnershipTransferred(msg.sender, account); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; library OwnableStorage { struct Layout { address owner; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.Ownable'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } function setOwner(Layout storage l, address owner) internal { l.owner = owner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title Map implementation with enumeration functions * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license) */ library EnumerableMap { error EnumerableMap__IndexOutOfBounds(); error EnumerableMap__NonExistentKey(); struct MapEntry { bytes32 _key; bytes32 _value; } struct Map { MapEntry[] _entries; // 1-indexed to allow 0 to signify nonexistence mapping(bytes32 => uint256) _indexes; } struct AddressToAddressMap { Map _inner; } struct UintToAddressMap { Map _inner; } function at( AddressToAddressMap storage map, uint256 index ) internal view returns (address, address) { (bytes32 key, bytes32 value) = _at(map._inner, index); return ( address(uint160(uint256(key))), address(uint160(uint256(value))) ); } 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)))); } function contains( AddressToAddressMap storage map, address key ) internal view returns (bool) { return _contains(map._inner, bytes32(uint256(uint160(key)))); } function contains( UintToAddressMap storage map, uint256 key ) internal view returns (bool) { return _contains(map._inner, bytes32(key)); } function length( AddressToAddressMap storage map ) internal view returns (uint256) { return _length(map._inner); } function length( UintToAddressMap storage map ) internal view returns (uint256) { return _length(map._inner); } function get( AddressToAddressMap storage map, address key ) internal view returns (address) { return address( uint160( uint256(_get(map._inner, bytes32(uint256(uint160(key))))) ) ); } function get( UintToAddressMap storage map, uint256 key ) internal view returns (address) { return address(uint160(uint256(_get(map._inner, bytes32(key))))); } function set( AddressToAddressMap storage map, address key, address value ) internal returns (bool) { return _set( map._inner, bytes32(uint256(uint160(key))), bytes32(uint256(uint160(value))) ); } function set( UintToAddressMap storage map, uint256 key, address value ) internal returns (bool) { return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } function remove( AddressToAddressMap storage map, address key ) internal returns (bool) { return _remove(map._inner, bytes32(uint256(uint160(key)))); } function remove( UintToAddressMap storage map, uint256 key ) internal returns (bool) { return _remove(map._inner, bytes32(key)); } function toArray( AddressToAddressMap storage map ) internal view returns (address[] memory keysOut, address[] memory valuesOut) { uint256 len = map._inner._entries.length; keysOut = new address[](len); valuesOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { keysOut[i] = address( uint160(uint256(map._inner._entries[i]._key)) ); valuesOut[i] = address( uint160(uint256(map._inner._entries[i]._value)) ); } } } function toArray( UintToAddressMap storage map ) internal view returns (uint256[] memory keysOut, address[] memory valuesOut) { uint256 len = map._inner._entries.length; keysOut = new uint256[](len); valuesOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { keysOut[i] = uint256(map._inner._entries[i]._key); valuesOut[i] = address( uint160(uint256(map._inner._entries[i]._value)) ); } } } function keys( AddressToAddressMap storage map ) internal view returns (address[] memory keysOut) { uint256 len = map._inner._entries.length; keysOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { keysOut[i] = address( uint160(uint256(map._inner._entries[i]._key)) ); } } } function keys( UintToAddressMap storage map ) internal view returns (uint256[] memory keysOut) { uint256 len = map._inner._entries.length; keysOut = new uint256[](len); unchecked { for (uint256 i; i < len; ++i) { keysOut[i] = uint256(map._inner._entries[i]._key); } } } function values( AddressToAddressMap storage map ) internal view returns (address[] memory valuesOut) { uint256 len = map._inner._entries.length; valuesOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { valuesOut[i] = address( uint160(uint256(map._inner._entries[i]._value)) ); } } } function values( UintToAddressMap storage map ) internal view returns (address[] memory valuesOut) { uint256 len = map._inner._entries.length; valuesOut = new address[](len); unchecked { for (uint256 i; i < len; ++i) { valuesOut[i] = address( uint160(uint256(map._inner._entries[i]._value)) ); } } } function _at( Map storage map, uint256 index ) private view returns (bytes32, bytes32) { if (index >= map._entries.length) revert EnumerableMap__IndexOutOfBounds(); MapEntry storage entry = map._entries[index]; return (entry._key, entry._value); } function _contains( Map storage map, bytes32 key ) private view returns (bool) { return map._indexes[key] != 0; } function _length(Map storage map) private view returns (uint256) { return map._entries.length; } function _get(Map storage map, bytes32 key) private view returns (bytes32) { uint256 keyIndex = map._indexes[key]; if (keyIndex == 0) revert EnumerableMap__NonExistentKey(); unchecked { return map._entries[keyIndex - 1]._value; } } function _set( Map storage map, bytes32 key, bytes32 value ) private returns (bool) { uint256 keyIndex = map._indexes[key]; if (keyIndex == 0) { map._entries.push(MapEntry({ _key: key, _value: value })); map._indexes[key] = map._entries.length; return true; } else { unchecked { map._entries[keyIndex - 1]._value = value; } return false; } } function _remove(Map storage map, bytes32 key) private returns (bool) { uint256 keyIndex = map._indexes[key]; if (keyIndex != 0) { unchecked { MapEntry storage last = map._entries[map._entries.length - 1]; // move last entry to now-vacant index map._entries[keyIndex - 1] = last; map._indexes[last._key] = keyIndex; } // clear last index map._entries.pop(); delete map._indexes[key]; return true; } else { return false; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title Set implementation with enumeration functions * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license) */ library EnumerableSet { error EnumerableSet__IndexOutOfBounds(); struct Set { bytes32[] _values; // 1-indexed to allow 0 to signify nonexistence mapping(bytes32 => uint256) _indexes; } struct Bytes32Set { Set _inner; } struct AddressSet { Set _inner; } struct UintSet { Set _inner; } function at( Bytes32Set storage set, uint256 index ) internal view returns (bytes32) { return _at(set._inner, index); } function at( AddressSet storage set, uint256 index ) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } function at( UintSet storage set, uint256 index ) internal view returns (uint256) { return uint256(_at(set._inner, index)); } function contains( Bytes32Set storage set, bytes32 value ) internal view returns (bool) { return _contains(set._inner, value); } function contains( AddressSet storage set, address value ) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } function contains( UintSet storage set, uint256 value ) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } function indexOf( Bytes32Set storage set, bytes32 value ) internal view returns (uint256) { return _indexOf(set._inner, value); } function indexOf( AddressSet storage set, address value ) internal view returns (uint256) { return _indexOf(set._inner, bytes32(uint256(uint160(value)))); } function indexOf( UintSet storage set, uint256 value ) internal view returns (uint256) { return _indexOf(set._inner, bytes32(value)); } function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } function add( Bytes32Set storage set, bytes32 value ) internal returns (bool) { return _add(set._inner, value); } function add( AddressSet storage set, address value ) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } function remove( Bytes32Set storage set, bytes32 value ) internal returns (bool) { return _remove(set._inner, value); } function remove( AddressSet storage set, address value ) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } function remove( UintSet storage set, uint256 value ) internal returns (bool) { return _remove(set._inner, bytes32(value)); } function toArray( Bytes32Set storage set ) internal view returns (bytes32[] memory) { return set._inner._values; } function toArray( AddressSet storage set ) internal view returns (address[] memory) { bytes32[] storage values = set._inner._values; address[] storage array; assembly { array.slot := values.slot } return array; } function toArray( UintSet storage set ) internal view returns (uint256[] memory) { bytes32[] storage values = set._inner._values; uint256[] storage array; assembly { array.slot := values.slot } return array; } function _at( Set storage set, uint256 index ) private view returns (bytes32) { if (index >= set._values.length) revert EnumerableSet__IndexOutOfBounds(); return set._values[index]; } function _contains( Set storage set, bytes32 value ) private view returns (bool) { return set._indexes[value] != 0; } function _indexOf( Set storage set, bytes32 value ) private view returns (uint256) { unchecked { return set._indexes[value] - 1; } } function _length(Set storage set) private view returns (uint256) { return set._values.length; } function _add( Set storage set, bytes32 value ) private returns (bool status) { if (!_contains(set, value)) { set._values.push(value); set._indexes[value] = set._values.length; status = true; } } function _remove( Set storage set, bytes32 value ) private returns (bool status) { uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { unchecked { bytes32 last = set._values[set._values.length - 1]; // move last value to now-vacant index set._values[valueIndex - 1] = last; set._indexes[last] = valueIndex; } // clear last index set._values.pop(); delete set._indexes[value]; status = true; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title ERC165 interface registration interface * @dev see https://eips.ethereum.org/EIPS/eip-165 */ interface IERC165 { /** * @notice query whether contract has registered support for given interface * @param interfaceId interface id * @return bool whether interface is supported */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC173Internal } from './IERC173Internal.sol'; /** * @title Contract ownership standard interface * @dev see https://eips.ethereum.org/EIPS/eip-173 */ interface IERC173 is IERC173Internal { /** * @notice get the ERC173 contract owner * @return conrtact owner */ function owner() external view returns (address); /** * @notice transfer contract ownership to new account * @param account address of new owner */ function transferOwnership(address account) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title Partial ERC173 interface needed by internal functions */ interface IERC173Internal { event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC165 } from './IERC165.sol'; import { IERC721Internal } from './IERC721Internal.sol'; /** * @title ERC721 interface * @dev see https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721 is IERC721Internal, IERC165 { /** * @notice query the balance of given address * @return balance quantity of tokens held */ function balanceOf(address account) external view returns (uint256 balance); /** * @notice query the owner of given token * @param tokenId token to query * @return owner token owner */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable * @param from sender of token * @param to receiver of token * @param tokenId token id */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable * @param from sender of token * @param to receiver of token * @param tokenId token id * @param data data payload */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external payable; /** * @notice transfer token between given addresses, without checking for ERC721Receiver implementation if applicable * @param from sender of token * @param to receiver of token * @param tokenId token id */ function transferFrom( address from, address to, uint256 tokenId ) external payable; /** * @notice grant approval to given account to spend token * @param operator address to be approved * @param tokenId token to approve */ function approve(address operator, uint256 tokenId) external payable; /** * @notice get approval status for given token * @param tokenId token to query * @return operator address approved to spend token */ function getApproved( uint256 tokenId ) external view returns (address operator); /** * @notice grant approval to or revoke approval from given account to spend all tokens held by sender * @param operator address to be approved * @param status approval status */ function setApprovalForAll(address operator, bool status) external; /** * @notice query approval status of given operator with respect to given address * @param account address to query for approval granted * @param operator address to query for approval received * @return status whether operator is approved to spend tokens held by account */ function isApprovedForAll( address account, address operator ) external view returns (bool status); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title Partial ERC721 interface needed by internal functions */ interface IERC721Internal { event Transfer( address indexed from, address indexed to, uint256 indexed tokenId ); event Approval( address indexed owner, address indexed operator, uint256 indexed tokenId ); event ApprovalForAll( address indexed owner, address indexed operator, bool approved ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; interface IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC165 } from '../interfaces/IERC165.sol'; import { ERC165Storage } from './ERC165Storage.sol'; /** * @title ERC165 implementation */ abstract contract ERC165 is IERC165 { using ERC165Storage for ERC165Storage.Layout; /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) public view returns (bool) { return ERC165Storage.layout().isSupportedInterface(interfaceId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; library ERC165Storage { error ERC165Storage__InvalidInterfaceId(); struct Layout { mapping(bytes4 => bool) supportedInterfaces; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.ERC165'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } function isSupportedInterface( Layout storage l, bytes4 interfaceId ) internal view returns (bool) { return l.supportedInterfaces[interfaceId]; } function setSupportedInterface( Layout storage l, bytes4 interfaceId, bool status ) internal { if (interfaceId == 0xffffffff) revert ERC165Storage__InvalidInterfaceId(); l.supportedInterfaces[interfaceId] = status; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC721 } from '../../../interfaces/IERC721.sol'; import { IERC721BaseInternal } from './IERC721BaseInternal.sol'; /** * @title ERC721 base interface */ interface IERC721Base is IERC721BaseInternal, IERC721 { }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { IERC721Internal } from '../../../interfaces/IERC721Internal.sol'; /** * @title ERC721 base interface */ interface IERC721BaseInternal is IERC721Internal { error ERC721Base__NotOwnerOrApproved(); error ERC721Base__SelfApproval(); error ERC721Base__BalanceQueryZeroAddress(); error ERC721Base__ERC721ReceiverNotImplemented(); error ERC721Base__InvalidOwner(); error ERC721Base__MintToZeroAddress(); error ERC721Base__NonExistentToken(); error ERC721Base__NotTokenOwner(); error ERC721Base__TokenAlreadyMinted(); error ERC721Base__TransferToZeroAddress(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; import { UintUtils } from './UintUtils.sol'; library AddressUtils { using UintUtils for uint256; error AddressUtils__InsufficientBalance(); error AddressUtils__NotContract(); error AddressUtils__SendValueFailed(); function toString(address account) internal pure returns (string memory) { return uint256(uint160(account)).toHexString(20); } function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0; } function sendValue(address payable account, uint256 amount) internal { (bool success, ) = account.call{ value: amount }(''); if (!success) revert AddressUtils__SendValueFailed(); } function functionCall( address target, bytes memory data ) internal returns (bytes memory) { return functionCall(target, data, 'AddressUtils: failed low-level call'); } function functionCall( address target, bytes memory data, string memory error ) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, error); } function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, 'AddressUtils: failed low-level call with value' ); } function functionCallWithValue( address target, bytes memory data, uint256 value, string memory error ) internal returns (bytes memory) { if (value > address(this).balance) revert AddressUtils__InsufficientBalance(); return _functionCallWithValue(target, data, value, error); } /** * @notice execute arbitrary external call with limited gas usage and amount of copied return data * @dev derived from https://github.com/nomad-xyz/ExcessivelySafeCall (MIT License) * @param target recipient of call * @param gasAmount gas allowance for call * @param value native token value to include in call * @param maxCopy maximum number of bytes to copy from return data * @param data encoded call data * @return success whether call is successful * @return returnData copied return data */ function excessivelySafeCall( address target, uint256 gasAmount, uint256 value, uint16 maxCopy, bytes memory data ) internal returns (bool success, bytes memory returnData) { returnData = new bytes(maxCopy); assembly { // execute external call via assembly to avoid automatic copying of return data success := call( gasAmount, target, value, add(data, 0x20), mload(data), 0, 0 ) // determine whether to limit amount of data to copy let toCopy := returndatasize() if gt(toCopy, maxCopy) { toCopy := maxCopy } // store the length of the copied bytes mstore(returnData, toCopy) // copy the bytes from returndata[0:toCopy] returndatacopy(add(returnData, 0x20), 0, toCopy) } } function _functionCallWithValue( address target, bytes memory data, uint256 value, string memory error ) private returns (bytes memory) { if (!isContract(target)) revert AddressUtils__NotContract(); (bool success, bytes memory returnData) = target.call{ value: value }( data ); if (success) { return returnData; } else if (returnData.length > 0) { assembly { let returnData_size := mload(returnData) revert(add(32, returnData), returnData_size) } } else { revert(error); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.8; /** * @title utility functions for uint256 operations * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license) */ library UintUtils { error UintUtils__InsufficientHexLength(); bytes16 private constant HEX_SYMBOLS = '0123456789abcdef'; function add(uint256 a, int256 b) internal pure returns (uint256) { return b < 0 ? sub(a, -b) : a + uint256(b); } function sub(uint256 a, int256 b) internal pure returns (uint256) { return b < 0 ? add(a, -b) : a - uint256(b); } function toString(uint256 value) internal pure returns (string memory) { if (value == 0) { return '0'; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return '0x00'; } uint256 length = 0; for (uint256 temp = value; temp != 0; temp >>= 8) { unchecked { length++; } } return toHexString(value, 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'; unchecked { for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_SYMBOLS[value & 0xf]; value >>= 4; } } if (value != 0) revert UintUtils__InsufficientHexLength(); return string(buffer); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title ERC-721 Non-Fungible Token Standard, optional child extension * @dev See https://eips.ethereum.org/EIPS/eip-721 * * A child token does not store it's own token balances and does not support * minting, transfer, approval. All view methods are passed along to the * parent contract. */ interface IChild { error ERC721Child__InvalidCaller(); error ERC721Child__NonExistentToken(); error ERC721Child__ApprovalNotSupported(); error ERC721Child__TransferNotSupported(); /** * @dev Returns the parent collection. */ function parent() external view returns (address); /** * @dev Initialize token ownership by calling it from the parent contract. * * Only call this once in case the child contract after the parent contract. * Emits a {Transfer} event from ZeroAddress to current owner per token. */ function init(uint256 tokenIdStart, uint256 tokenIdEnd) external; /** * @dev Update token ownership from by calling it from the parent contract. * * Emits a {Transfer} event. */ function update( address from, address to, uint256 tokenId ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {IERC721BaseInternal} from "@solidstate/contracts/token/ERC721/base/IERC721BaseInternal.sol"; interface IERC721MarketplaceInternal is IERC721BaseInternal { error ERC721Marketplace__NonExistentOffer(); error ERC721Marketplace__InvalidArguments(); error ERC721Marketplace__PaymentFailed(); error ERC721Marketplace__InvalidValue(); error ERC721Marketplace__InvalidPrice(); event OfferCreated( uint256 indexed tokenId, uint256 indexed value, address indexed to ); event OfferWithdrawn(uint256 indexed tokenId); event Sale( uint256 indexed tokenId, address indexed from, address indexed to, uint256 value ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; library ScapesMarketplaceStorage { bytes32 internal constant STORAGE_SLOT = keccak256("scapes.storage.Marketplace"); struct Offer { uint80 price; uint80 specificBuyerPrice; uint80 lastPrice; address specificBuyer; } struct Layout { address beneficiary; uint256 bps; mapping(uint256 => Offer) offers; } function layout() internal pure returns (Layout storage d) { bytes32 slot = STORAGE_SLOT; assembly { d.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import {ERC165} from "@solidstate/contracts/introspection/ERC165.sol"; import {OwnableInternal} from "@solidstate/contracts/access/ownable/OwnableInternal.sol"; import {ScapesMarketplaceStorage} from "./ScapesMarketplaceStorage.sol"; abstract contract HasSecondarySaleFees is ERC165 { function getFeeRecipients(uint256 id) public view virtual returns (address payable[] memory); function getFeeBps(uint256 id) public view virtual returns (uint256[] memory); } /// @title WithFees /// @author jalil.eth, akuti.eth | scapes.eth /// @dev Implements the various fee standards that are floating around. We need a proper standard for this. abstract contract WithFees is HasSecondarySaleFees, OwnableInternal { /// Exposes a way to update the secondary sale beneficiary /// @param beneficiary_ the new beneficiary function setBeneficiary(address beneficiary_) public onlyOwner { ScapesMarketplaceStorage.layout().beneficiary = beneficiary_; } /// Implement the `HasSecondarySaleFees` Contract /// @dev implements the standard pushed by Rarible /// @return list of fee recipients, in our case always one function getFeeRecipients(uint256) public view override returns (address payable[] memory) { address payable[] memory recipients = new address payable[](1); recipients[0] = payable(ScapesMarketplaceStorage.layout().beneficiary); return recipients; } /// Implement the `HasSecondarySaleFees` Contract /// @dev implements the standard pushed by Rarible /// @return list of fee basis points, in our case always one function getFeeBps(uint256) public view override returns (uint256[] memory) { uint256[] memory bpsArray = new uint256[](1); bpsArray[0] = ScapesMarketplaceStorage.layout().bps; return bpsArray; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; library ScapesERC721MetadataStorage { bytes32 internal constant STORAGE_SLOT = keccak256("scapes.storage.ERC721Metadata"); struct Layout { string name; string symbol; string description; string externalBaseURI; address scapeBound; } function layout() internal pure returns (Layout storage d) { bytes32 slot = STORAGE_SLOT; assembly { d.slot := slot } } }
// SPDX-License-Identifier: MIT // Based on solidstate @solidstate/contracts/token/ERC721/base/ERC721Base.sol // Changes made: // - make approval, transferFrom and safeTransferFrom virtual pragma solidity ^0.8.8; import {IERC721} from "@solidstate/contracts/interfaces/IERC721.sol"; import {IERC721Receiver} from "@solidstate/contracts/interfaces/IERC721Receiver.sol"; import {EnumerableMap} from "@solidstate/contracts/data/EnumerableMap.sol"; import {EnumerableSet} from "@solidstate/contracts/data/EnumerableSet.sol"; import {AddressUtils} from "@solidstate/contracts/utils/AddressUtils.sol"; import {IERC721Base} from "@solidstate/contracts/token/ERC721/base/IERC721Base.sol"; import {ERC721BaseStorage} from "./ERC721BaseStorage.sol"; import {ERC721BaseInternal} from "./ERC721BaseInternal.sol"; /** * @title Base ERC721 implementation, excluding optional extensions */ abstract contract ERC721Base is IERC721Base, ERC721BaseInternal { using AddressUtils for address; using EnumerableMap for EnumerableMap.UintToAddressMap; using EnumerableSet for EnumerableSet.UintSet; /** * @inheritdoc IERC721 */ function balanceOf(address account) public view returns (uint256) { return _balanceOf(account) + _balanceOfMerges(account); } /** * @notice query the balance of merges of given address * @return balance quantity of merge tokens held */ function balanceOfMerges(address account) public view returns (uint256) { return _balanceOfMerges(account); } /** * @inheritdoc IERC721 */ function ownerOf(uint256 tokenId) public view returns (address) { return _ownerOf(tokenId); } /** * @inheritdoc IERC721 */ function getApproved(uint256 tokenId) public view returns (address) { return _getApproved(tokenId); } /** * @inheritdoc IERC721 */ function isApprovedForAll(address account, address operator) public view returns (bool) { return _isApprovedForAll(account, operator); } /** * @inheritdoc IERC721 */ function transferFrom( address from, address to, uint256 tokenId ) public payable virtual { _handleTransferMessageValue(from, to, tokenId, msg.value); if (!_isApprovedOrOwner(msg.sender, tokenId)) revert ERC721Base__NotOwnerOrApproved(); _transfer(from, to, tokenId); } /** * @inheritdoc IERC721 */ function safeTransferFrom( address from, address to, uint256 tokenId ) public payable virtual { safeTransferFrom(from, to, tokenId, ""); } /** * @inheritdoc IERC721 */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public payable virtual { _handleTransferMessageValue(from, to, tokenId, msg.value); if (!_isApprovedOrOwner(msg.sender, tokenId)) revert ERC721Base__NotOwnerOrApproved(); _safeTransfer(from, to, tokenId, data); } /** * @inheritdoc IERC721 */ function approve(address operator, uint256 tokenId) public payable virtual { _handleApproveMessageValue(operator, tokenId, msg.value); address owner = ownerOf(tokenId); if (operator == owner) revert ERC721Base__SelfApproval(); if (msg.sender != owner && !isApprovedForAll(owner, msg.sender)) revert ERC721Base__NotOwnerOrApproved(); _approve(operator, tokenId); } /** * @inheritdoc IERC721 */ function setApprovalForAll(address operator, bool status) public virtual { if (operator == msg.sender) revert ERC721Base__SelfApproval(); ERC721BaseStorage.layout().operatorApprovals[msg.sender][ operator ] = status; emit ApprovalForAll(msg.sender, operator, status); } }
// SPDX-License-Identifier: MIT // Based on solidstate @solidstate/contracts/token/ERC721/base/ERC721BaseInternal.sol // Changes made: // - store a holder balance instead of the individual tokens, this removes the // option to easily upgrade to ERC721Enumerable but lowers gas cost by ~45k per mint // - update balance in mint, transfer and burn functions separate balance for normal // tokens and merged tokens // - update balanceOf to return the combined balance // - add _afterTokenTransfer hook pragma solidity ^0.8.8; import {IERC721Receiver} from "@solidstate/contracts/interfaces/IERC721Receiver.sol"; import {EnumerableMap} from "@solidstate/contracts/data/EnumerableMap.sol"; import {EnumerableSet} from "@solidstate/contracts/data/EnumerableSet.sol"; import {AddressUtils} from "@solidstate/contracts/utils/AddressUtils.sol"; import {IERC721BaseInternal} from "@solidstate/contracts/token/ERC721/base/IERC721BaseInternal.sol"; import {ERC721BaseStorage} from "./ERC721BaseStorage.sol"; /** * @title Base ERC721 internal functions */ abstract contract ERC721BaseInternal is IERC721BaseInternal { using ERC721BaseStorage for ERC721BaseStorage.Layout; using AddressUtils for address; using EnumerableMap for EnumerableMap.UintToAddressMap; using EnumerableSet for EnumerableSet.UintSet; uint256 internal constant MERGES_TRESHOLD = 130_000; function _balanceOf(address account) internal view virtual returns (uint256) { if (account == address(0)) revert ERC721Base__BalanceQueryZeroAddress(); return ERC721BaseStorage.layout().holderBalances[account]; } function _balanceOfMerges(address account) internal view virtual returns (uint256) { if (account == address(0)) revert ERC721Base__BalanceQueryZeroAddress(); return ERC721BaseStorage.layout().holderBalancesMerges[account]; } function _ownerOf(uint256 tokenId) internal view virtual returns (address) { address owner = ERC721BaseStorage.layout().tokenOwners.get(tokenId); if (owner == address(0)) revert ERC721Base__InvalidOwner(); return owner; } function _getApproved(uint256 tokenId) internal view virtual returns (address) { ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); if (!l.exists(tokenId)) revert ERC721Base__NonExistentToken(); return l.tokenApprovals[tokenId]; } function _isApprovedForAll(address account, address operator) internal view virtual returns (bool) { return ERC721BaseStorage.layout().operatorApprovals[account][operator]; } function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { if (!ERC721BaseStorage.layout().exists(tokenId)) revert ERC721Base__NonExistentToken(); address owner = _ownerOf(tokenId); return (spender == owner || _getApproved(tokenId) == spender || _isApprovedForAll(owner, spender)); } function _mint(address to, uint256 tokenId) internal virtual { if (to == address(0)) revert ERC721Base__MintToZeroAddress(); ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); if (l.exists(tokenId)) revert ERC721Base__TokenAlreadyMinted(); _beforeTokenTransfer(address(0), to, tokenId); unchecked { if (tokenId > MERGES_TRESHOLD) l.holderBalancesMerges[to] += 1; else l.holderBalances[to] += 1; } l.tokenOwners.set(tokenId, to); emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); if (!_checkOnERC721Received(address(0), to, tokenId, data)) revert ERC721Base__ERC721ReceiverNotImplemented(); } function _burn(uint256 tokenId) internal virtual { address owner = _ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); _approve(address(0), tokenId); ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); unchecked { if (tokenId > MERGES_TRESHOLD) l.holderBalancesMerges[owner] -= 1; else l.holderBalances[owner] -= 1; } l.tokenOwners.remove(tokenId); emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } function _transfer( address from, address to, uint256 tokenId ) internal virtual { if (_ownerOf(tokenId) != from) revert ERC721Base__NotTokenOwner(); if (to == address(0)) revert ERC721Base__TransferToZeroAddress(); _beforeTokenTransfer(from, to, tokenId); _approve(address(0), tokenId); ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout(); unchecked { if (tokenId > MERGES_TRESHOLD) { l.holderBalancesMerges[from] -= 1; l.holderBalancesMerges[to] += 1; } else { l.holderBalances[from] -= 1; l.holderBalances[to] += 1; } } l.tokenOwners.set(tokenId, to); emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); if (!_checkOnERC721Received(from, to, tokenId, data)) revert ERC721Base__ERC721ReceiverNotImplemented(); } function _approve(address operator, uint256 tokenId) internal virtual { ERC721BaseStorage.layout().tokenApprovals[tokenId] = operator; emit Approval(_ownerOf(tokenId), operator, tokenId); } function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) internal virtual returns (bool) { if (!to.isContract()) { return true; } bytes memory returnData = to.functionCall( abi.encodeWithSelector( IERC721Receiver(to).onERC721Received.selector, msg.sender, from, tokenId, data ), "ERC721: transfer to non ERC721Receiver implementer" ); bytes4 returnValue = abi.decode(returnData, (bytes4)); return returnValue == type(IERC721Receiver).interfaceId; } /** * @notice ERC721 hook, called before externally called approvals for processing of included message value * @param operator beneficiary of approval * @param tokenId id of transferred token * @param value message value */ function _handleApproveMessageValue( address operator, uint256 tokenId, uint256 value ) internal virtual {} /** * @notice ERC721 hook, called before externally called transfers for processing of included message value * @param from sender of token * @param to receiver of token * @param tokenId id of transferred token * @param value message value */ function _handleTransferMessageValue( address from, address to, uint256 tokenId, uint256 value ) internal virtual {} /** * @notice ERC721 hook, called before all transfers including mint and burn * @dev function should be overridden and new implementation must call super * @param from sender of token * @param to receiver of token * @param tokenId id of transferred token */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @notice ERC721 hook, called after all transfers including mint and burn * @dev function should be overridden and new implementation must call super * @param from sender of token * @param to receiver of token * @param tokenId id of transferred token */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT // Based on solidstate @solidstate/contracts/token/ERC721/base/ERC721BaseStorage.sol // Changes made: // - replace holderTokens with holderBalances, this removes the // option to easily upgrade to ERC721Enumerable but lowers gas cost by ~45k per mint // - add holderBalancesMerges to separetly track the balance of merged scape tokens pragma solidity ^0.8.8; import {EnumerableMap} from "@solidstate/contracts/data/EnumerableMap.sol"; library ERC721BaseStorage { using EnumerableMap for EnumerableMap.UintToAddressMap; bytes32 internal constant STORAGE_SLOT = keccak256("scapes.storage.ERC721Base"); struct Layout { EnumerableMap.UintToAddressMap tokenOwners; mapping(address => uint256) holderBalances; mapping(address => uint256) holderBalancesMerges; mapping(uint256 => address) tokenApprovals; mapping(address => mapping(address => bool)) operatorApprovals; } function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } function exists(Layout storage l, uint256 tokenId) internal view returns (bool) { return l.tokenOwners.contains(tokenId); } function totalSupply(Layout storage l) internal view returns (uint256) { return l.tokenOwners.length(); } function tokenByIndex(Layout storage l, uint256 index) internal view returns (uint256) { (uint256 tokenId, ) = l.tokenOwners.at(index); return tokenId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; library ScapesMerge { struct MergePart { uint256 tokenId; bool flipX; bool flipY; } struct Merge { MergePart[] parts; bool isFade; } function toId(Merge calldata merge_) internal pure returns (uint256 mergeId) { for (uint256 i = 0; i < merge_.parts.length; i++) { MergePart memory part = merge_.parts[i]; uint256 partDNA = part.tokenId; if (part.flipX) { partDNA |= 1 << 14; } if (part.flipY) { partDNA |= 1 << 15; } mergeId |= partDNA << (16 * i); } mergeId = mergeId << 1; if (merge_.isFade) { mergeId |= 1; } } function fromId(uint256 mergeId) internal pure returns (Merge memory merge_) { MergePart[15] memory parts; merge_.isFade = mergeId & 1 > 0; mergeId >>= 1; uint256 numParts; for (uint256 i = 0; i < 15; i++) { MergePart memory part = parts[i]; uint256 offset = 16 * i; uint256 filter = (1 << (offset + 14)) - (1 << offset); part.tokenId = (mergeId & filter) >> offset; if (part.tokenId == 0) { break; } part.flipX = mergeId & (1 << (offset + 14)) > 0; part.flipY = mergeId & (1 << (offset + 15)) > 0; numParts++; } merge_.parts = new MergePart[](numParts); for (uint256 i = 0; i < numParts; i++) { merge_.parts[i] = parts[i]; } } function getSortedTokenIds(Merge memory merge_, bool unique) internal pure returns (uint256[] memory) { uint256[] memory tokenIds = new uint256[](merge_.parts.length); for (uint256 i = 0; i < merge_.parts.length; i++) { tokenIds[i] = merge_.parts[i].tokenId; } _quickSort(tokenIds, int256(0), int256(tokenIds.length - 1)); if (!unique) { return tokenIds; } uint256 uniqueCounter; uint256 lastTokenId; for (uint256 i = 0; i < tokenIds.length; i++) { if (tokenIds[i] != lastTokenId) uniqueCounter++; lastTokenId = tokenIds[i]; } uint256[] memory uniqueTokenIds = new uint256[](uniqueCounter); uniqueCounter = 0; lastTokenId = 0; for (uint256 i = 0; i < tokenIds.length; i++) { if (tokenIds[i] != lastTokenId) { uniqueTokenIds[uniqueCounter] = tokenIds[i]; uniqueCounter++; } } return uniqueTokenIds; } function hasNoFlip(Merge memory merge_) internal pure returns (bool) { for (uint256 i = 0; i < merge_.parts.length; i++) { if (merge_.parts[i].flipX || merge_.parts[i].flipY) return false; } return true; } // Sorts in-place function _quickSort( uint256[] memory arr, int256 left, int256 right ) internal pure { int256 i = left; int256 j = right; if (i == j) return; uint256 pivot = arr[uint256(left + (right - left) / 2)]; while (i <= j) { while (arr[uint256(i)] < pivot) i++; while (pivot < arr[uint256(j)]) j--; if (i <= j) { (arr[uint256(i)], arr[uint256(j)]) = ( arr[uint256(j)], arr[uint256(i)] ); i++; j--; } } if (left < j) _quickSort(arr, left, j); if (i < right) _quickSort(arr, i, right); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {OperatorFilterer} from "./OperatorFilterer.sol"; /** * @title DefaultOperatorFilterer * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription. */ abstract contract DefaultOperatorFilterer is OperatorFilterer { address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6); constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; interface IOperatorFilterRegistry { function isOperatorAllowed(address registrant, address operator) external view returns (bool); function register(address registrant) external; function registerAndSubscribe(address registrant, address subscription) external; function registerAndCopyEntries(address registrant, address registrantToCopy) external; function unregister(address addr) external; function updateOperator(address registrant, address operator, bool filtered) external; function updateOperators(address registrant, address[] calldata operators, bool filtered) external; function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external; function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external; function subscribe(address registrant, address registrantToSubscribe) external; function unsubscribe(address registrant, bool copyExistingEntries) external; function subscriptionOf(address addr) external returns (address registrant); function subscribers(address registrant) external returns (address[] memory); function subscriberAt(address registrant, uint256 index) external returns (address); function copyEntriesOf(address registrant, address registrantToCopy) external; function isOperatorFiltered(address registrant, address operator) external returns (bool); function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool); function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool); function filteredOperators(address addr) external returns (address[] memory); function filteredCodeHashes(address addr) external returns (bytes32[] memory); function filteredOperatorAt(address registrant, uint256 index) external returns (address); function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32); function isRegistered(address addr) external returns (bool); function codeHashOf(address addr) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {IOperatorFilterRegistry} from "./IOperatorFilterRegistry.sol"; /** * @title OperatorFilterer * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another * registrant's entries in the OperatorFilterRegistry. * @dev This smart contract is meant to be inherited by token contracts so they can use the following: * - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods. * - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods. */ abstract contract OperatorFilterer { error OperatorNotAllowed(address operator); IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY = IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E); constructor(address subscriptionOrRegistrantToCopy, bool subscribe) { // If an inheriting token contract is deployed to a network without the registry deployed, the modifier // will not revert, but the contract will need to be registered with the registry once it is deployed in // order for the modifier to filter addresses. if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { if (subscribe) { OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy); } else { if (subscriptionOrRegistrantToCopy != address(0)) { OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy); } else { OPERATOR_FILTER_REGISTRY.register(address(this)); } } } } modifier onlyAllowedOperator(address from) virtual { // Allow spending tokens from addresses with balance // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred // from an EOA. if (from != msg.sender) { _checkFilterOperator(msg.sender); } _; } modifier onlyAllowedOperatorApproval(address operator) virtual { _checkFilterOperator(operator); _; } function _checkFilterOperator(address operator) internal view virtual { // Check registry code length to facilitate testing in environments without a deployed registry. if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) { if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) { revert OperatorNotAllowed(operator); } } } }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"AddressUtils__NotContract","type":"error"},{"inputs":[],"name":"ERC721Base__BalanceQueryZeroAddress","type":"error"},{"inputs":[],"name":"ERC721Base__ERC721ReceiverNotImplemented","type":"error"},{"inputs":[],"name":"ERC721Base__InvalidOwner","type":"error"},{"inputs":[],"name":"ERC721Base__MintToZeroAddress","type":"error"},{"inputs":[],"name":"ERC721Base__NonExistentToken","type":"error"},{"inputs":[],"name":"ERC721Base__NotOwnerOrApproved","type":"error"},{"inputs":[],"name":"ERC721Base__NotTokenOwner","type":"error"},{"inputs":[],"name":"ERC721Base__SelfApproval","type":"error"},{"inputs":[],"name":"ERC721Base__TokenAlreadyMinted","type":"error"},{"inputs":[],"name":"ERC721Base__TransferToZeroAddress","type":"error"},{"inputs":[],"name":"ERC721Marketplace__InvalidArguments","type":"error"},{"inputs":[],"name":"ERC721Marketplace__InvalidPrice","type":"error"},{"inputs":[],"name":"ERC721Marketplace__InvalidValue","type":"error"},{"inputs":[],"name":"ERC721Marketplace__NonExistentOffer","type":"error"},{"inputs":[],"name":"ERC721Marketplace__PaymentFailed","type":"error"},{"inputs":[],"name":"EnumerableMap__NonExistentKey","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"Ownable__NotOwner","type":"error"},{"inputs":[],"name":"Ownable__NotTransitiveOwner","type":"error"},{"inputs":[],"name":"ScapesERC721__ChildAlreadyAdded","type":"error"},{"inputs":[],"name":"ScapesERC721__InvalidArgument","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","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":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OfferCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"OfferWithdrawn","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":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Sale","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"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfMerges","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":"uint256","name":"","type":"uint256"}],"name":"getFeeBps","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getFeeRecipients","outputs":[{"internalType":"address payable[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"flipX","type":"bool"},{"internalType":"bool","name":"flipY","type":"bool"}],"internalType":"struct ScapesMerge.MergePart[]","name":"parts","type":"tuple[]"},{"internalType":"bool","name":"isFade","type":"bool"}],"internalType":"struct ScapesMerge.Merge","name":"merge_","type":"tuple"}],"name":"merge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"flipX","type":"bool"},{"internalType":"bool","name":"flipY","type":"bool"}],"internalType":"struct ScapesMerge.MergePart[]","name":"parts","type":"tuple[]"},{"internalType":"bool","name":"isFade","type":"bool"}],"internalType":"struct ScapesMerge.Merge","name":"merge_","type":"tuple"}],"name":"purge","outputs":[],"stateMutability":"nonpayable","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":"payable","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":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary_","type":"address"}],"name":"setBeneficiary","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":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","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":"payable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50733cc6cdda760b79bafa08df41ecfa224f810dceb660016daaeb6d7670e522a718067333cd4e3b156200016e578015620000bc57604051633e9f1edf60e11b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b1580156200009d57600080fd5b505af1158015620000b2573d6000803e3d6000fd5b505050506200016e565b6001600160a01b038216156200010d5760405163a0af290360e01b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e9063a0af29039060440162000082565b604051632210724360e11b81523060048201526daaeb6d7670e522a718067333cd4e90634420e48690602401600060405180830381600087803b1580156200015457600080fd5b505af115801562000169573d6000803e3d6000fd5b505050505b5050611f2c80620001806000396000f3fe6080604052600436106101295760003560e01c806342842e0e116100a5578063a22cb46511610074578063b9c4d9fb11610059578063b9c4d9fb14610317578063e0e037f614610344578063e985e9c51461036457600080fd5b8063a22cb465146102e4578063b88d4fde1461030457600080fd5b806342842e0e146102715780636352211e1461028457806370a08231146102a4578063a20b3799146102c457600080fd5b806318160ddd116100fc57806323b872dd116100e157806323b872dd1461021c5780632c9a9a381461022f57806341f434341461024f57600080fd5b806318160ddd146101dd5780631c31f710146101fc57600080fd5b806301ffc9a71461012e578063081812fc14610163578063095ea7b31461019b5780630ebd4c7f146101b0575b600080fd5b34801561013a57600080fd5b5061014e61014936600461195f565b610384565b60405190151581526020015b60405180910390f35b34801561016f57600080fd5b5061018361017e36600461197c565b6103df565b6040516001600160a01b03909116815260200161015a565b6101ae6101a93660046119ac565b6103ea565b005b3480156101bc57600080fd5b506101d06101cb36600461197c565b610403565b60405161015a91906119d6565b3480156101e957600080fd5b506127105b60405190815260200161015a565b34801561020857600080fd5b506101ae610217366004611a1a565b610472565b6101ae61022a366004611a35565b610523565b34801561023b57600080fd5b506101ae61024a366004611a71565b61054e565b34801561025b57600080fd5b506101836daaeb6d7670e522a718067333cd4e81565b6101ae61027f366004611a35565b610616565b34801561029057600080fd5b5061018361029f36600461197c565b61063b565b3480156102b057600080fd5b506101ee6102bf366004611a1a565b610646565b3480156102d057600080fd5b506101ae6102df366004611a71565b610664565b3480156102f057600080fd5b506101ae6102ff366004611aba565b610711565b6101ae610312366004611b38565b610725565b34801561032357600080fd5b5061033761033236600461197c565b610752565b60405161015a9190611bf8565b34801561035057600080fd5b506101ee61035f366004611a1a565b6107d5565b34801561037057600080fd5b5061014e61037f366004611c39565b6107e0565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081527f326d0c59a7612f6a9919e2a8ee333c80ba689d8ba2634de89c85cbb04832e705602052604081205460ff165b92915050565b60006103d982610832565b816103f481610899565b6103fe8383610989565b505050565b60408051600180825281830190925260609160009190602080830190803683370190505090507fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594db8600101548160008151811061046157610461611c6c565b602090810291909101015292915050565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f671680460546001600160a01b031633146104d5576040517f2f7a8ee100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594db8805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b826001600160a01b038116331461053d5761053d33610899565b610548848484610a10565b50505050565b600261055a8280611c82565b905010806105735750600861056f8280611c82565b9050115b156105aa576040517f9f61f8d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b6105b78280611c82565b9050811015610600576105ee33306105cf8580611c82565b858181106105df576105df611c6c565b90506060020160000135610523565b806105f881611ce8565b9150506105ad565b506106133361060e83610a42565b610af5565b50565b826001600160a01b03811633146106305761063033610899565b610548848484610b13565b60006103d982610b2e565b600061065182610b9d565b61065a83610c01565b6103d99190611d01565b600061066f82610a42565b90503361067b82610b2e565b6001600160a01b0316146106a257604051630f2db4ad60e01b815260040160405180910390fd5b6106ab81610c65565b60005b6106b88380611c82565b90508110156103fe576106ff30336106d08680611c82565b858181106106e0576106e0611c6c565b9050606002016000013560405180602001604052806000815250610d4e565b8061070981611ce8565b9150506106ae565b8161071b81610899565b6103fe8383610d82565b836001600160a01b038116331461073f5761073f33610899565b61074b85858585610e36565b5050505050565b604080516001808252818301909252606091600091906020808301908036833750507fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594db85482519293506001600160a01b0316918391506000906107b7576107b7611c6c565b6001600160a01b039092166020928302919091019091015292915050565b60006103d982610b9d565b6001600160a01b0380831660009081527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bffa6020908152604080832093851683529290529081205460ff165b9392505050565b60007f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff561085f8184610e69565b61087c5760405163c1b843ef60e01b815260040160405180910390fd5b60009283526004016020525060409020546001600160a01b031690565b6daaeb6d7670e522a718067333cd4e3b15610613576040517fc61711340000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa15801561091f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109439190611d14565b610613576040517fede71dcc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024015b60405180910390fd5b60006109948261063b565b9050806001600160a01b0316836001600160a01b0316036109c85760405163424a22cb60e01b815260040160405180910390fd5b336001600160a01b038216148015906109e857506109e681336107e0565b155b15610a0657604051632f5de44f60e01b815260040160405180910390fd5b6103fe8383610e75565b610a1a3382610f0f565b610a3757604051632f5de44f60e01b815260040160405180910390fd5b6103fe838383610ff5565b6000805b610a508380611c82565b9050811015610ad3576000610a658480611c82565b83818110610a7557610a75611c6c565b905060600201803603810190610a8b9190611d31565b805160208201519192509015610aa057614000175b816040015115610aaf57618000175b610aba836010611d9a565b1b92909217915080610acb81611ce8565b915050610a46565b5060011b610ae76040830160208401611db9565b15610af0576001175b919050565b610b0f828260405180602001604052806000815250611171565b5050565b6103fe83838360405180602001604052806000815250610725565b600080610b5b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff5846111a5565b90506001600160a01b0381166103d9576040517f7e1a7d8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600160a01b038216610bc657604051630810ff9760e41b815260040160405180910390fd5b506001600160a01b031660009081527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff8602052604090205490565b60006001600160a01b038216610c2a57604051630810ff9760e41b815260040160405180910390fd5b506001600160a01b031660009081527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff7602052604090205490565b6000610c7082610b2e565b9050610c7e816000846111b1565b610c89600083610e75565b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff56201fbd0831115610cdc576001600160a01b038216600090815260038201602052604090208054600019019055610cff565b6001600160a01b0382166000908152600282016020526040902080546000190190555b610d0981846112c6565b5060405183906000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a46103fe826000856112d2565b610d59848484610ff5565b610d6584848484611383565b61054857604051639ff10cdd60e01b815260040160405180910390fd5b336001600160a01b03831603610dab5760405163424a22cb60e01b815260040160405180910390fd5b3360008181527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bffa602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610e403383610f0f565b610e5d57604051632f5de44f60e01b815260040160405180910390fd5b61054884848484610d4e565b600061082b83836114af565b60008181527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff960205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091558190610ed682610b2e565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000610f3b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff583610e69565b610f585760405163c1b843ef60e01b815260040160405180910390fd5b6000610f6383610b2e565b9050806001600160a01b0316846001600160a01b03161480610f9e5750836001600160a01b0316610f9384610832565b6001600160a01b0316145b80610fed57506001600160a01b0380821660009081527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bffa602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b031661100882610b2e565b6001600160a01b03161461102f57604051630f2db4ad60e01b815260040160405180910390fd5b6001600160a01b03821661106f576040517f40311a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61107a8383836111b1565b611085600082610e75565b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff56201fbd08211156110e7576001600160a01b038085166000908152600383016020526040808220805460001901905591851681522080546001019055611119565b6001600160a01b0380851660009081526002830160205260408082208054600019019055918516815220805460010190555b6111248183856114c7565b5081836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46105488484846112d2565b61117b83836114dd565b6111886000848484611383565b6103fe57604051639ff10cdd60e01b815260040160405180910390fd5b600061082b838361162e565b6001600160a01b038316158015906111d157506001600160a01b03821615155b8015611215575060008181527fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594dba602052604090205469ffffffffffffffffffff1615155b156103fe5760008181527fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594dba6020526040808220805469ffffffffffffffffffff19168155600101805473ffffffffffffffffffffffffffffffffffffffff19169055517fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594db89183917facbc44b7f46dc350c99fc0d9e5f61ed5c588cb4cdc6b69ea0deb0c5b28e5efc49190a250505050565b600061082b83836116ab565b7f4ca5b6536be965df5a6498d1883a57f2ca8946e5bd14e05eafa6e36d0ceffcd16004908101546040517f8ce516da0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811693820193909352848316602482015260448101849052911690638ce516da90606401600060405180830381600087803b15801561136657600080fd5b505af115801561137a573d6000803e3d6000fd5b50505050505050565b60006001600160a01b0384163b61139c57506001610fed565b600061144763150b7a0260e01b338887876040516024016113c09493929190611e26565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001611ec5603291396001600160a01b0388169190611793565b905060008180602001905181019061145f9190611e62565b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001492505050949350505050565b6000818152600183016020526040812054151561082b565b6000610fed84846001600160a01b0385166117a2565b6001600160a01b03821661151d576040517f23e5311a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff56115488183610e69565b1561157f576040517f6c35dbd800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61158b600084846111b1565b6201fbd08211156115bc576001600160a01b03831660009081526003820160205260409020805460010190556115de565b6001600160a01b03831660009081526002820160205260409020805460010190555b6115e98183856114c7565b5060405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a46103fe600084846112d2565b6000818152600183016020526040812054808203611678576040517ff551fb1400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600001600182038154811061169057611690611c6c565b90600052602060002090600202016001015491505092915050565b60008181526001830160205260408120548015611789578354600090859060001981019081106116dd576116dd611c6c565b906000526020600020906002020190508085600001600184038154811061170657611706611c6c565b600091825260208083208454600290930201918255600193840154918401919091559254815290860190915260409020819055835484908061174a5761174a611e7f565b60008281526020808220600260001990940193840201828155600190810183905592909355858152868201909252604082209190915591506103d99050565b60009150506103d9565b6060610fed8484600085611841565b600082815260018401602052604081205480820361180957505060408051808201825283815260208082018481528654600181810189556000898152848120955160029093029095019182559151908201558654868452818801909252929091205561082b565b8285600001600183038154811061182257611822611c6c565b906000526020600020906002020160010181905550600091505061082b565b6060843b61187b576040517f89c35afc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080866001600160a01b031685876040516118979190611e95565b60006040518083038185875af1925050503d80600081146118d4576040519150601f19603f3d011682016040523d82523d6000602084013e6118d9565b606091505b509150915081156118ed579150610fed9050565b8051156118fd5780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109809190611eb1565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461061357600080fd5b60006020828403121561197157600080fd5b813561082b81611931565b60006020828403121561198e57600080fd5b5035919050565b80356001600160a01b0381168114610af057600080fd5b600080604083850312156119bf57600080fd5b6119c883611995565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611a0e578351835292840192918401916001016119f2565b50909695505050505050565b600060208284031215611a2c57600080fd5b61082b82611995565b600080600060608486031215611a4a57600080fd5b611a5384611995565b9250611a6160208501611995565b9150604084013590509250925092565b600060208284031215611a8357600080fd5b813567ffffffffffffffff811115611a9a57600080fd5b82016040818503121561082b57600080fd5b801515811461061357600080fd5b60008060408385031215611acd57600080fd5b611ad683611995565b91506020830135611ae681611aac565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611b3057611b30611af1565b604052919050565b60008060008060808587031215611b4e57600080fd5b611b5785611995565b93506020611b66818701611995565b935060408601359250606086013567ffffffffffffffff80821115611b8a57600080fd5b818801915088601f830112611b9e57600080fd5b813581811115611bb057611bb0611af1565b611bc2601f8201601f19168501611b07565b91508082528984828501011115611bd857600080fd5b808484018584013760008482840101525080935050505092959194509250565b6020808252825182820181905260009190848201906040850190845b81811015611a0e5783516001600160a01b031683529284019291840191600101611c14565b60008060408385031215611c4c57600080fd5b611c5583611995565b9150611c6360208401611995565b90509250929050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611c9957600080fd5b83018035915067ffffffffffffffff821115611cb457600080fd5b6020019150606081023603821315611ccb57600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b600060018201611cfa57611cfa611cd2565b5060010190565b808201808211156103d9576103d9611cd2565b600060208284031215611d2657600080fd5b815161082b81611aac565b600060608284031215611d4357600080fd5b6040516060810181811067ffffffffffffffff82111715611d6657611d66611af1565b604052823581526020830135611d7b81611aac565b60208201526040830135611d8e81611aac565b60408201529392505050565b6000816000190483118215151615611db457611db4611cd2565b500290565b600060208284031215611dcb57600080fd5b813561082b81611aac565b60005b83811015611df1578181015183820152602001611dd9565b50506000910152565b60008151808452611e12816020860160208601611dd6565b601f01601f19169290920160200192915050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152611e586080830184611dfa565b9695505050505050565b600060208284031215611e7457600080fd5b815161082b81611931565b634e487b7160e01b600052603160045260246000fd5b60008251611ea7818460208701611dd6565b9190910192915050565b60208152600061082b6020830184611dfa56fe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e746572a2646970667358221220d83dbbda1b7ccf18c2da0820817ba4336eb0260154d4530f408cfddada4c3f9564736f6c63430008100033
Deployed Bytecode
0x6080604052600436106101295760003560e01c806342842e0e116100a5578063a22cb46511610074578063b9c4d9fb11610059578063b9c4d9fb14610317578063e0e037f614610344578063e985e9c51461036457600080fd5b8063a22cb465146102e4578063b88d4fde1461030457600080fd5b806342842e0e146102715780636352211e1461028457806370a08231146102a4578063a20b3799146102c457600080fd5b806318160ddd116100fc57806323b872dd116100e157806323b872dd1461021c5780632c9a9a381461022f57806341f434341461024f57600080fd5b806318160ddd146101dd5780631c31f710146101fc57600080fd5b806301ffc9a71461012e578063081812fc14610163578063095ea7b31461019b5780630ebd4c7f146101b0575b600080fd5b34801561013a57600080fd5b5061014e61014936600461195f565b610384565b60405190151581526020015b60405180910390f35b34801561016f57600080fd5b5061018361017e36600461197c565b6103df565b6040516001600160a01b03909116815260200161015a565b6101ae6101a93660046119ac565b6103ea565b005b3480156101bc57600080fd5b506101d06101cb36600461197c565b610403565b60405161015a91906119d6565b3480156101e957600080fd5b506127105b60405190815260200161015a565b34801561020857600080fd5b506101ae610217366004611a1a565b610472565b6101ae61022a366004611a35565b610523565b34801561023b57600080fd5b506101ae61024a366004611a71565b61054e565b34801561025b57600080fd5b506101836daaeb6d7670e522a718067333cd4e81565b6101ae61027f366004611a35565b610616565b34801561029057600080fd5b5061018361029f36600461197c565b61063b565b3480156102b057600080fd5b506101ee6102bf366004611a1a565b610646565b3480156102d057600080fd5b506101ae6102df366004611a71565b610664565b3480156102f057600080fd5b506101ae6102ff366004611aba565b610711565b6101ae610312366004611b38565b610725565b34801561032357600080fd5b5061033761033236600461197c565b610752565b60405161015a9190611bf8565b34801561035057600080fd5b506101ee61035f366004611a1a565b6107d5565b34801561037057600080fd5b5061014e61037f366004611c39565b6107e0565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081527f326d0c59a7612f6a9919e2a8ee333c80ba689d8ba2634de89c85cbb04832e705602052604081205460ff165b92915050565b60006103d982610832565b816103f481610899565b6103fe8383610989565b505050565b60408051600180825281830190925260609160009190602080830190803683370190505090507fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594db8600101548160008151811061046157610461611c6c565b602090810291909101015292915050565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f671680460546001600160a01b031633146104d5576040517f2f7a8ee100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594db8805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b826001600160a01b038116331461053d5761053d33610899565b610548848484610a10565b50505050565b600261055a8280611c82565b905010806105735750600861056f8280611c82565b9050115b156105aa576040517f9f61f8d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b6105b78280611c82565b9050811015610600576105ee33306105cf8580611c82565b858181106105df576105df611c6c565b90506060020160000135610523565b806105f881611ce8565b9150506105ad565b506106133361060e83610a42565b610af5565b50565b826001600160a01b03811633146106305761063033610899565b610548848484610b13565b60006103d982610b2e565b600061065182610b9d565b61065a83610c01565b6103d99190611d01565b600061066f82610a42565b90503361067b82610b2e565b6001600160a01b0316146106a257604051630f2db4ad60e01b815260040160405180910390fd5b6106ab81610c65565b60005b6106b88380611c82565b90508110156103fe576106ff30336106d08680611c82565b858181106106e0576106e0611c6c565b9050606002016000013560405180602001604052806000815250610d4e565b8061070981611ce8565b9150506106ae565b8161071b81610899565b6103fe8383610d82565b836001600160a01b038116331461073f5761073f33610899565b61074b85858585610e36565b5050505050565b604080516001808252818301909252606091600091906020808301908036833750507fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594db85482519293506001600160a01b0316918391506000906107b7576107b7611c6c565b6001600160a01b039092166020928302919091019091015292915050565b60006103d982610b9d565b6001600160a01b0380831660009081527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bffa6020908152604080832093851683529290529081205460ff165b9392505050565b60007f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff561085f8184610e69565b61087c5760405163c1b843ef60e01b815260040160405180910390fd5b60009283526004016020525060409020546001600160a01b031690565b6daaeb6d7670e522a718067333cd4e3b15610613576040517fc61711340000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa15801561091f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109439190611d14565b610613576040517fede71dcc0000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024015b60405180910390fd5b60006109948261063b565b9050806001600160a01b0316836001600160a01b0316036109c85760405163424a22cb60e01b815260040160405180910390fd5b336001600160a01b038216148015906109e857506109e681336107e0565b155b15610a0657604051632f5de44f60e01b815260040160405180910390fd5b6103fe8383610e75565b610a1a3382610f0f565b610a3757604051632f5de44f60e01b815260040160405180910390fd5b6103fe838383610ff5565b6000805b610a508380611c82565b9050811015610ad3576000610a658480611c82565b83818110610a7557610a75611c6c565b905060600201803603810190610a8b9190611d31565b805160208201519192509015610aa057614000175b816040015115610aaf57618000175b610aba836010611d9a565b1b92909217915080610acb81611ce8565b915050610a46565b5060011b610ae76040830160208401611db9565b15610af0576001175b919050565b610b0f828260405180602001604052806000815250611171565b5050565b6103fe83838360405180602001604052806000815250610725565b600080610b5b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff5846111a5565b90506001600160a01b0381166103d9576040517f7e1a7d8b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006001600160a01b038216610bc657604051630810ff9760e41b815260040160405180910390fd5b506001600160a01b031660009081527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff8602052604090205490565b60006001600160a01b038216610c2a57604051630810ff9760e41b815260040160405180910390fd5b506001600160a01b031660009081527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff7602052604090205490565b6000610c7082610b2e565b9050610c7e816000846111b1565b610c89600083610e75565b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff56201fbd0831115610cdc576001600160a01b038216600090815260038201602052604090208054600019019055610cff565b6001600160a01b0382166000908152600282016020526040902080546000190190555b610d0981846112c6565b5060405183906000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a46103fe826000856112d2565b610d59848484610ff5565b610d6584848484611383565b61054857604051639ff10cdd60e01b815260040160405180910390fd5b336001600160a01b03831603610dab5760405163424a22cb60e01b815260040160405180910390fd5b3360008181527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bffa602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b610e403383610f0f565b610e5d57604051632f5de44f60e01b815260040160405180910390fd5b61054884848484610d4e565b600061082b83836114af565b60008181527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff960205260409020805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0384169081179091558190610ed682610b2e565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000610f3b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff583610e69565b610f585760405163c1b843ef60e01b815260040160405180910390fd5b6000610f6383610b2e565b9050806001600160a01b0316846001600160a01b03161480610f9e5750836001600160a01b0316610f9384610832565b6001600160a01b0316145b80610fed57506001600160a01b0380821660009081527f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bffa602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b031661100882610b2e565b6001600160a01b03161461102f57604051630f2db4ad60e01b815260040160405180910390fd5b6001600160a01b03821661106f576040517f40311a0900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61107a8383836111b1565b611085600082610e75565b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff56201fbd08211156110e7576001600160a01b038085166000908152600383016020526040808220805460001901905591851681522080546001019055611119565b6001600160a01b0380851660009081526002830160205260408082208054600019019055918516815220805460010190555b6111248183856114c7565b5081836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a46105488484846112d2565b61117b83836114dd565b6111886000848484611383565b6103fe57604051639ff10cdd60e01b815260040160405180910390fd5b600061082b838361162e565b6001600160a01b038316158015906111d157506001600160a01b03821615155b8015611215575060008181527fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594dba602052604090205469ffffffffffffffffffff1615155b156103fe5760008181527fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594dba6020526040808220805469ffffffffffffffffffff19168155600101805473ffffffffffffffffffffffffffffffffffffffff19169055517fcc410442a83ee5ff86205e8b7585832614e9498a8404ee01ae13793dea594db89183917facbc44b7f46dc350c99fc0d9e5f61ed5c588cb4cdc6b69ea0deb0c5b28e5efc49190a250505050565b600061082b83836116ab565b7f4ca5b6536be965df5a6498d1883a57f2ca8946e5bd14e05eafa6e36d0ceffcd16004908101546040517f8ce516da0000000000000000000000000000000000000000000000000000000081526001600160a01b0386811693820193909352848316602482015260448101849052911690638ce516da90606401600060405180830381600087803b15801561136657600080fd5b505af115801561137a573d6000803e3d6000fd5b50505050505050565b60006001600160a01b0384163b61139c57506001610fed565b600061144763150b7a0260e01b338887876040516024016113c09493929190611e26565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001611ec5603291396001600160a01b0388169190611793565b905060008180602001905181019061145f9190611e62565b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a02000000000000000000000000000000000000000000000000000000001492505050949350505050565b6000818152600183016020526040812054151561082b565b6000610fed84846001600160a01b0385166117a2565b6001600160a01b03821661151d576040517f23e5311a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f24192aa1e930860a59219c92c01fd96c8fde79f41992dc1c72ae9cf26bb3bff56115488183610e69565b1561157f576040517f6c35dbd800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61158b600084846111b1565b6201fbd08211156115bc576001600160a01b03831660009081526003820160205260409020805460010190556115de565b6001600160a01b03831660009081526002820160205260409020805460010190555b6115e98183856114c7565b5060405182906001600160a01b038516906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a46103fe600084846112d2565b6000818152600183016020526040812054808203611678576040517ff551fb1400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83600001600182038154811061169057611690611c6c565b90600052602060002090600202016001015491505092915050565b60008181526001830160205260408120548015611789578354600090859060001981019081106116dd576116dd611c6c565b906000526020600020906002020190508085600001600184038154811061170657611706611c6c565b600091825260208083208454600290930201918255600193840154918401919091559254815290860190915260409020819055835484908061174a5761174a611e7f565b60008281526020808220600260001990940193840201828155600190810183905592909355858152868201909252604082209190915591506103d99050565b60009150506103d9565b6060610fed8484600085611841565b600082815260018401602052604081205480820361180957505060408051808201825283815260208082018481528654600181810189556000898152848120955160029093029095019182559151908201558654868452818801909252929091205561082b565b8285600001600183038154811061182257611822611c6c565b906000526020600020906002020160010181905550600091505061082b565b6060843b61187b576040517f89c35afc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080866001600160a01b031685876040516118979190611e95565b60006040518083038185875af1925050503d80600081146118d4576040519150601f19603f3d011682016040523d82523d6000602084013e6118d9565b606091505b509150915081156118ed579150610fed9050565b8051156118fd5780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109809190611eb1565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461061357600080fd5b60006020828403121561197157600080fd5b813561082b81611931565b60006020828403121561198e57600080fd5b5035919050565b80356001600160a01b0381168114610af057600080fd5b600080604083850312156119bf57600080fd5b6119c883611995565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611a0e578351835292840192918401916001016119f2565b50909695505050505050565b600060208284031215611a2c57600080fd5b61082b82611995565b600080600060608486031215611a4a57600080fd5b611a5384611995565b9250611a6160208501611995565b9150604084013590509250925092565b600060208284031215611a8357600080fd5b813567ffffffffffffffff811115611a9a57600080fd5b82016040818503121561082b57600080fd5b801515811461061357600080fd5b60008060408385031215611acd57600080fd5b611ad683611995565b91506020830135611ae681611aac565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611b3057611b30611af1565b604052919050565b60008060008060808587031215611b4e57600080fd5b611b5785611995565b93506020611b66818701611995565b935060408601359250606086013567ffffffffffffffff80821115611b8a57600080fd5b818801915088601f830112611b9e57600080fd5b813581811115611bb057611bb0611af1565b611bc2601f8201601f19168501611b07565b91508082528984828501011115611bd857600080fd5b808484018584013760008482840101525080935050505092959194509250565b6020808252825182820181905260009190848201906040850190845b81811015611a0e5783516001600160a01b031683529284019291840191600101611c14565b60008060408385031215611c4c57600080fd5b611c5583611995565b9150611c6360208401611995565b90509250929050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e19843603018112611c9957600080fd5b83018035915067ffffffffffffffff821115611cb457600080fd5b6020019150606081023603821315611ccb57600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b600060018201611cfa57611cfa611cd2565b5060010190565b808201808211156103d9576103d9611cd2565b600060208284031215611d2657600080fd5b815161082b81611aac565b600060608284031215611d4357600080fd5b6040516060810181811067ffffffffffffffff82111715611d6657611d66611af1565b604052823581526020830135611d7b81611aac565b60208201526040830135611d8e81611aac565b60408201529392505050565b6000816000190483118215151615611db457611db4611cd2565b500290565b600060208284031215611dcb57600080fd5b813561082b81611aac565b60005b83811015611df1578181015183820152602001611dd9565b50506000910152565b60008151808452611e12816020860160208601611dd6565b601f01601f19169290920160200192915050565b60006001600160a01b03808716835280861660208401525083604083015260806060830152611e586080830184611dfa565b9695505050505050565b600060208284031215611e7457600080fd5b815161082b81611931565b634e487b7160e01b600052603160045260246000fd5b60008251611ea7818460208701611dd6565b9190910192915050565b60208152600061082b6020830184611dfa56fe4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e746572a2646970667358221220d83dbbda1b7ccf18c2da0820817ba4336eb0260154d4530f408cfddada4c3f9564736f6c63430008100033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.