Polygon Sponsored slots available. Book your slot here!
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 18,363 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Revoke Single No... | 65963332 | 117 days ago | IN | 0 POL | 0.00126024 | ||||
Revoke Single No... | 62043374 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043368 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043363 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043359 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043354 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043342 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043330 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043318 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043312 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043307 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 62043300 | 215 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 61831689 | 220 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 61831682 | 220 days ago | IN | 0 POL | 0.00171767 | ||||
Revoke Single No... | 61831677 | 220 days ago | IN | 0 POL | 0.00171767 | ||||
Revoke Single No... | 61831670 | 220 days ago | IN | 0 POL | 0.00147567 | ||||
Buy Single Listi... | 60912538 | 243 days ago | IN | 0 POL | 0.00623559 | ||||
Buy Single Listi... | 60863473 | 244 days ago | IN | 0 POL | 0.01813435 | ||||
Revoke Single No... | 60827629 | 245 days ago | IN | 0 POL | 0.00147567 | ||||
Revoke Single No... | 60827458 | 245 days ago | IN | 0 POL | 0.00147567 | ||||
Buy Single Listi... | 59592203 | 276 days ago | IN | 21.5 POL | 0.00311289 | ||||
Buy Single Listi... | 59570429 | 277 days ago | IN | 21.5 POL | 0.00466933 | ||||
Buy Single Listi... | 59570387 | 277 days ago | IN | 21.5 POL | 0.00487686 | ||||
Buy Single Listi... | 59436440 | 280 days ago | IN | 21.5 POL | 0.00332041 | ||||
Buy Single Listi... | 59426284 | 280 days ago | IN | 21.5 POL | 0.00342417 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
60912442 | 243 days ago | 0.000975 POL | ||||
60912442 | 243 days ago | 0.000015 POL | ||||
60912442 | 243 days ago | 0.00001 POL | ||||
60912442 | 243 days ago | 0.001 POL | ||||
57805381 | 321 days ago | 0.00975 POL | ||||
57805381 | 321 days ago | 0.00015 POL | ||||
57805381 | 321 days ago | 0.0001 POL | ||||
57805381 | 321 days ago | 0.01 POL | ||||
57398829 | 332 days ago | 60 POL | ||||
56816072 | 347 days ago | 93.1 POL | ||||
56816072 | 347 days ago | 1.9 POL | ||||
56763540 | 348 days ago | 2.8855 POL | ||||
56763540 | 348 days ago | 0.0145 POL | ||||
56673927 | 351 days ago | 33.7038 POL | ||||
56673927 | 351 days ago | 0.8642 POL | ||||
56673927 | 351 days ago | 8.642 POL | ||||
56652525 | 351 days ago | 0.0294 POL | ||||
56652525 | 351 days ago | 0.0006 POL | ||||
56481785 | 356 days ago | 48.755 POL | ||||
56481785 | 356 days ago | 0.245 POL | ||||
56481785 | 356 days ago | 49 POL | ||||
56416179 | 358 days ago | 3.8805 POL | ||||
56416179 | 358 days ago | 0.0195 POL | ||||
56353993 | 359 days ago | 26 POL | ||||
56353951 | 359 days ago | 52 POL |
Loading...
Loading
Contract Name:
PaymentProcessor
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 600 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./IOwnable.sol"; import "./IPaymentProcessor.sol"; import "@openzeppelin/contracts/access/IAccessControl.sol"; import "@openzeppelin/contracts/interfaces/IERC1271.sol"; import "@openzeppelin/contracts/interfaces/IERC2981.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; /** * @title PaymentProcessor * @author Limit Break, Inc. * @notice The world's first ERC721-C compatible marketplace contract! * @notice Use ERC721-C to whitelist this contract or other marketplace contracts that process royalties entirely * on-chain manner to make them 100% enforceable and fully programmable! * * @notice <h4>Features</h4> * * @notice <ul> * <li>Creator Defined Security Profiles</li> * <ul> * <li>Exchange Whitelist On/Off</li> * <li>Payment Method Whitelist On/Off</li> * <li>Pricing Constraints On/Off</li> * <li>Private Sales On/Off</li> * <li>Delegate Purchase Wallets On/Off</li> * <li>Smart Contract Buyers/Sellers On/Off</li> * <li>Exchange Whitelist Bypass for EOAs On/Off</li> * </ul> * <li>Enforceable/Programmable Fees</li> * <ul> * <li>Built-in EIP-2981 Royalty Enforcement</li> * <li>Built-in Marketplace Fee Enforcement</li> * </ul> * <li>Multi-Standard Support</li> * <ul> * <li>ERC721-C</li> * <li>ERC1155-C</li> * <li>ERC721 + EIP-2981</li> * <li>ERC1155 + EIP-2981</li> * </ul> * <li>Payments</li> * <ul> * <li>Native Currency (ETH or Equivalent)</li> * <li>ERC-20 Coin Payments</li> * </ul> * <li>A Multitude of Supported Sale Types</li> * <ul> * <li>Buy Single Listing</li> * <ul> * <li>Collection-Level Offers</li> * <li>Item-Specific Offers</li> * </ul> * <li>Buy Batch of Listings (Shopping Cart)</li> * <li>Buy Bundled Listing (From One Collection)</li> * <li>Sweep Listings (From One Collection)</li> * <li>Partial Order Fills (When ERC-20 Payment Method Is Used)</li> * </ul> * </ul> * * @notice <h4>Security Considerations for Users</h4> * * @notice Virtually all on-chain marketplace contracts have the potential to be front-run. * When purchasing high-value items, whether individually or in a batch/bundle it is highly * recommended to execute transactions using Flashbots RPC Relay/private mempool to avoid * sniper bots. Partial fills are available for batched purchases, bundled listing purchases, * and collection sweeps when the method of payment is an ERC-20 token, but not for purchases * using native currency. It is preferable to use wrapped ETH (or equivalent) when buying * multiple tokens and it is highly advisable to use Flashbots whenever possible. [Read the * quickstart guide for more information](https://docs.flashbots.net/flashbots-protect/rpc/quick-start). */ contract PaymentProcessor is ERC165, EIP712, Ownable, Pausable, IPaymentProcessor { error PaymentProcessor__AddressCannotBeZero(); error PaymentProcessor__AmountForERC721SalesMustEqualOne(); error PaymentProcessor__AmountForERC1155SalesGreaterThanZero(); error PaymentProcessor__BundledOfferPriceMustEqualSumOfAllListingPrices(); error PaymentProcessor__BuyerDidNotAuthorizePurchase(); error PaymentProcessor__BuyerMustBeDesignatedPrivateBuyer(); error PaymentProcessor__CallerDoesNotOwnSecurityPolicy(); error PaymentProcessor__CallerIsNotTheDelegatedPurchaser(); error PaymentProcessor__CallerIsNotWhitelistedMarketplace(); error PaymentProcessor__CallerMustHaveElevatedPermissionsForSpecifiedNFT(); error PaymentProcessor__CannotIncludeNativeFundsWhenPaymentMethodIsAnERC20Coin(); error PaymentProcessor__CeilingPriceMustBeGreaterThanFloorPrice(); error PaymentProcessor__CoinDoesNotImplementDecimalsAndLikelyIsNotAnERC20Token(); error PaymentProcessor__CoinIsApproved(); error PaymentProcessor__CoinIsNotApproved(); error PaymentProcessor__CollectionLevelOrItemLevelOffersCanOnlyBeMadeUsingERC20PaymentMethods(); error PaymentProcessor__DispensingTokenWasUnsuccessful(); error PaymentProcessor__EIP1271SignaturesAreDisabled(); error PaymentProcessor__EIP1271SignatureInvalid(); error PaymentProcessor__ExchangeIsWhitelisted(); error PaymentProcessor__ExchangeIsNotWhitelisted(); error PaymentProcessor__FailedToTransferProceeds(); error PaymentProcessor__InputArrayLengthCannotBeZero(); error PaymentProcessor__InputArrayLengthMismatch(); error PaymentProcessor__MarketplaceAndRoyaltyFeesWillExceedSalePrice(); error PaymentProcessor__NativeCurrencyIsNotAnApprovedPaymentMethod(); error PaymentProcessor__OfferHasExpired(); error PaymentProcessor__OfferPriceMustEqualSalePrice(); error PaymentProcessor__OnchainRoyaltiesExceedMaximumApprovedRoyaltyFee(); error PaymentProcessor__OverpaidNativeFunds(); error PaymentProcessor__PaymentCoinIsNotAnApprovedPaymentMethod(); error PaymentProcessor__PricingBoundsAreImmutable(); error PaymentProcessor__RanOutOfNativeFunds(); error PaymentProcessor__SaleHasExpired(); error PaymentProcessor__SalePriceAboveMaximumCeiling(); error PaymentProcessor__SalePriceBelowMinimumFloor(); error PaymentProcessor__SalePriceBelowSellerApprovedMinimum(); error PaymentProcessor__SecurityPolicyDoesNotExist(); error PaymentProcessor__SecurityPolicyOwnershipCannotBeTransferredToZeroAddress(); error PaymentProcessor__SellerDidNotAuthorizeSale(); error PaymentProcessor__SignatureAlreadyUsedOrRevoked(); error PaymentProcessor__TokenSecurityPolicyDoesNotAllowDelegatedPurchases(); error PaymentProcessor__TokenSecurityPolicyDoesNotAllowEOACallers(); error PaymentProcessor__TokenSecurityPolicyDoesNotAllowPrivateListings(); /// @dev Convenience to avoid magic number in bitmask get/set logic. uint256 private constant ONE = uint256(1); /// @notice The default admin role for NFT collections using Access Control. bytes32 private constant DEFAULT_ACCESS_CONTROL_ADMIN_ROLE = 0x00; /// @notice The default security policy id. uint256 public constant DEFAULT_SECURITY_POLICY_ID = 0; /// @notice The denominator used when calculating the marketplace fee. /// @dev 0.5% fee numerator is 50, 1% fee numerator is 100, 10% fee numerator is 1,000 and so on. uint256 public constant FEE_DENOMINATOR = 10_000; /// @notice keccack256("OfferApproval(uint8 protocol,address marketplace,uint256 marketplaceFeeNumerator,address delegatedPurchaser,address buyer,address tokenAddress,uint256 tokenId,uint256 amount,uint256 price,uint256 expiration,uint256 nonce,uint256 masterNonce,address coin)") bytes32 public constant OFFER_APPROVAL_HASH = 0x2008a1ab898fdaa2d8f178bc39e807035d2d6e330dac5e42e913ca727ab56038; /// @notice keccack256("CollectionOfferApproval(uint8 protocol,bool collectionLevelOffer,address marketplace,uint256 marketplaceFeeNumerator,address delegatedPurchaser,address buyer,address tokenAddress,uint256 amount,uint256 price,uint256 expiration,uint256 nonce,uint256 masterNonce,address coin)") bytes32 public constant COLLECTION_OFFER_APPROVAL_HASH = 0x0bc3075778b80a2341ce445063e81924b88d61eb5f21c815e8f9cc824af096d0; /// @notice keccack256("BundledOfferApproval(uint8 protocol,address marketplace,uint256 marketplaceFeeNumerator,address delegatedPurchaser,address buyer,address tokenAddress,uint256 price,uint256 expiration,uint256 nonce,uint256 masterNonce,address coin,uint256[] tokenIds,uint256[] amounts,uint256[] itemSalePrices)") bytes32 public constant BUNDLED_OFFER_APPROVAL_HASH = 0x126520d0bca0cfa7e5852d004cc4335723ce67c638cbd55cd530fe992a089e7b; /// @notice keccack256("SaleApproval(uint8 protocol,bool sellerAcceptedOffer,address marketplace,uint256 marketplaceFeeNumerator,uint256 maxRoyaltyFeeNumerator,address privateBuyer,address seller,address tokenAddress,uint256 tokenId,uint256 amount,uint256 minPrice,uint256 expiration,uint256 nonce,uint256 masterNonce,address coin)") bytes32 public constant SALE_APPROVAL_HASH = 0xd3f4273db8ff5262b6bc5f6ee07d139463b4f826cce90c05165f63062f3686dc; /// @notice keccack256("BundledSaleApproval(uint8 protocol,address marketplace,uint256 marketplaceFeeNumerator,address privateBuyer,address seller,address tokenAddress,uint256 expiration,uint256 nonce,uint256 masterNonce,address coin,uint256[] tokenIds,uint256[] amounts,uint256[] maxRoyaltyFeeNumerators,uint256[] itemPrices)") bytes32 public constant BUNDLED_SALE_APPROVAL_HASH = 0x80244acca7a02d7199149a3038653fc8cb10ca984341ec429a626fab631e1662; /// @dev Tracks the most recently created security profile id uint256 private lastSecurityPolicyId; /// @dev Mapping of token address (NFT collection) to a security policy id. mapping(address => uint256) private tokenSecurityPolicies; /// @dev Mapping of whitelisted exchange addresses, organized by security policy id. mapping(uint256 => mapping(address => bool)) private exchangeWhitelist; /// @dev Mapping of coin addresses that are approved for payments, organized by security policy id. mapping(uint256 => mapping(address => bool)) private paymentMethodWhitelist; /// @dev Mapping of security policy id to security policy settings. mapping(uint256 => SecurityPolicy) private securityPolicies; /** * @notice User-specific master nonce that allows buyers and sellers to efficiently cancel all listings or offers * they made previously. The master nonce for a user only changes when they explicitly request to revoke all * existing listings and offers. * * @dev When prompting sellers to sign a listing or offer, marketplaces must query the current master nonce of * the user and include it in the listing/offer signature data. */ mapping(address => uint256) public masterNonces; /** * @dev The mapping key is the keccak256 hash of marketplace address and user address. * * @dev ```keccak256(abi.encodePacked(marketplace, user))``` * * @dev The mapping value is another nested mapping of "slot" (key) to a bitmap (value) containing boolean flags * indicating whether or not a nonce has been used or invalidated. * * @dev Marketplaces MUST track their own nonce by user, incrementing it for every signed listing or offer the user * creates. Listings and purchases may be executed out of order, and they may never be executed if orders * are not matched prior to expriation. * * @dev The slot and the bit offset within the mapped value are computed as: * * @dev ```slot = nonce / 256;``` * @dev ```offset = nonce % 256;``` */ mapping(bytes32 => mapping(uint256 => uint256)) private invalidatedSignatures; /** * @dev Mapping of token contract addresses to the address of the ERC-20 payment coin tokens are priced in. * When unspecified, the default currency for collections is the native currency. * * @dev If the designated ERC-20 payment coin is not in the list of approved coins, sales cannot be executed * until the designated coin is set to an approved payment coin. */ mapping (address => address) public collectionPaymentCoins; /** * @dev Mapping of token contract addresses to the collection-level pricing boundaries (floor and ceiling price). */ mapping (address => PricingBounds) private collectionPricingBounds; /** * @dev Mapping of token contract addresses to the token-level pricing boundaries (floor and ceiling price). */ mapping (address => mapping (uint256 => PricingBounds)) private tokenPricingBounds; constructor( address defaultContractOwner_, uint32 defaultPushPaymentGasLimit_, address[] memory defaultPaymentMethods) EIP712("PaymentProcessor", "1") { securityPolicies[DEFAULT_SECURITY_POLICY_ID] = SecurityPolicy({ enforceExchangeWhitelist: false, enforcePaymentMethodWhitelist: true, enforcePricingConstraints: false, disablePrivateListings: false, disableDelegatedPurchases: false, disableEIP1271Signatures: false, disableExchangeWhitelistEOABypass: false, pushPaymentGasLimit: defaultPushPaymentGasLimit_, policyOwner: address(0) }); emit CreatedOrUpdatedSecurityPolicy( DEFAULT_SECURITY_POLICY_ID, false, true, false, false, false, false, false, defaultPushPaymentGasLimit_, "DEFAULT SECURITY POLICY"); for (uint256 i = 0; i < defaultPaymentMethods.length;) { address coin = defaultPaymentMethods[i]; paymentMethodWhitelist[DEFAULT_SECURITY_POLICY_ID][coin] = true; emit PaymentMethodAddedToWhitelist(DEFAULT_SECURITY_POLICY_ID, coin); unchecked { ++i; } } _transferOwnership(defaultContractOwner_); } /** * @notice Allows Payment Processor contract owner to pause trading on this contract. This is only to be used * in case a future vulnerability emerges to allow a migration to an updated contract. * * @dev Throws when caller is not the contract owner. * @dev Throws when contract is already paused. * * @dev <h4>Postconditions:</h4> * @dev 1. The contract has been placed in the `paused` state. * @dev 2. Trading is frozen. */ function pause() external { _checkOwner(); _pause(); } /** * @notice Allows Payment Processor contract owner to resume trading on this contract. This is only to be used * in case a pause was not necessary and trading can safely resume. * * @dev Throws when caller is not the contract owner. * @dev Throws when contract is not currently paused. * * @dev <h4>Postconditions:</h4> * @dev 1. The contract has been placed in the `unpaused` state. * @dev 2. Trading is resumed. */ function unpause() external { _checkOwner(); _unpause(); } /** * @notice Allows any user to create a new security policy for the payment processor. * * @dev <h4>Postconditions:</h4> * @dev 1. The security policy id tracker has been incremented by `1`. * @dev 2. The security policy has been added to the security policies mapping. * @dev 3. The caller has been assigned as the owner of the security policy. * @dev 4. A `CreatedOrUpdatedSecurityPolicy` event has been emitted. * * @param enforceExchangeWhitelist Requires external exchange contracts be whitelisted to make buy calls. * @param enforcePaymentMethodWhitelist Requires that ERC-20 payment methods be pre-approved. * @param enforcePricingConstraints Allows the creator to specify exactly one approved payment method, * a minimum floor price and a maximum ceiling price. * When true, this value supercedes `enforcePaymentMethodWhitelist`. * @param disablePrivateListings Prevents private sales. * @param disableDelegatedPurchases Prevents delegated purchases. * @param disableEIP1271Signatures Prevents EIP-1271 compliant smart contracts such as multi-sig wallets * from buying or selling. Forces buyers and sellers to be EOAs. * @param disableExchangeWhitelistEOABypass When exchange whitelists are enforced, prevents EOAs from executing * purchases directly and bypassing whitelisted exchange contracts. * @param pushPaymentGasLimit The amount of gas to forward when pushing native proceeds. * @param registryName A human readable name that describes the security policy. */ function createSecurityPolicy( bool enforceExchangeWhitelist, bool enforcePaymentMethodWhitelist, bool enforcePricingConstraints, bool disablePrivateListings, bool disableDelegatedPurchases, bool disableEIP1271Signatures, bool disableExchangeWhitelistEOABypass, uint32 pushPaymentGasLimit, string calldata registryName) external override returns (uint256) { uint256 securityPolicyId; unchecked { securityPolicyId = ++lastSecurityPolicyId; } _createOrUpdateSecurityPolicy( securityPolicyId, enforceExchangeWhitelist, enforcePaymentMethodWhitelist, enforcePricingConstraints, disablePrivateListings, disableDelegatedPurchases, disableEIP1271Signatures, disableExchangeWhitelistEOABypass, pushPaymentGasLimit, registryName ); return securityPolicyId; } /** * @notice Allows security policy owners to update existing security policies. * * @dev Throws when caller is not the owner of the specified security policy. * @dev Throws when the specified security policy id does not exist. * * @dev <h4>Postconditions:</h4> * @dev 1. The security policy details have been updated in the security policies mapping. * @dev 2. A `CreatedOrUpdatedSecurityPolicy` event has been emitted. * * @param enforceExchangeWhitelist Requires external exchange contracts be whitelisted to make buy calls. * @param enforcePaymentMethodWhitelist Requires that ERC-20 payment methods be pre-approved. * @param enforcePricingConstraints Allows the creator to specify exactly one approved payment method, * a minimum floor price and a maximum ceiling price. * When true, this value supercedes `enforcePaymentMethodWhitelist`. * @param disablePrivateListings Prevents private sales. * @param disableDelegatedPurchases Prevents delegated purchases. * @param disableEIP1271Signatures Prevents EIP-1271 compliant smart contracts such as multi-sig wallets * from buying or selling. Forces buyers and sellers to be EOAs. * @param disableExchangeWhitelistEOABypass When exchange whitelists are enforced, prevents EOAs from executing * purchases directly and bypassing whitelisted exchange contracts. * @param pushPaymentGasLimit The amount of gas to forward when pushing native proceeds. * @param registryName A human readable name that describes the security policy. */ function updateSecurityPolicy( uint256 securityPolicyId, bool enforceExchangeWhitelist, bool enforcePaymentMethodWhitelist, bool enforcePricingConstraints, bool disablePrivateListings, bool disableDelegatedPurchases, bool disableEIP1271Signatures, bool disableExchangeWhitelistEOABypass, uint32 pushPaymentGasLimit, string calldata registryName) external override { _requireCallerOwnsSecurityPolicy(securityPolicyId); _createOrUpdateSecurityPolicy( securityPolicyId, enforceExchangeWhitelist, enforcePaymentMethodWhitelist, enforcePricingConstraints, disablePrivateListings, disableDelegatedPurchases, disableEIP1271Signatures, disableExchangeWhitelistEOABypass, pushPaymentGasLimit, registryName ); } /** * @notice Allow security policy owners to transfer ownership of their security policy to a new account. * * @dev Throws when `newOwner` is the zero address. * @dev Throws when caller is not the owner of the specified security policy. * * @dev <h4>Postconditions:</h4> * @dev 1. The security policy owner has been updated in the security policies mapping. * @dev 2. A `SecurityPolicyOwnershipTransferred` event has been emitted. * * @param securityPolicyId The id of the security policy to update. * @param newOwner The new policy owner address. */ function transferSecurityPolicyOwnership(uint256 securityPolicyId, address newOwner) external override { if(newOwner == address(0)) { revert PaymentProcessor__SecurityPolicyOwnershipCannotBeTransferredToZeroAddress(); } _transferSecurityPolicyOwnership(securityPolicyId, newOwner); } /** * @notice Allow security policy owners to transfer ownership of their security policy to the zero address. * This can be done to make a security policy permanently immutable. * * @dev Throws when caller is not the owner of the specified security policy. * * @dev <h4>Postconditions:</h4> * @dev 1. The security policy owner has been set to the zero address in the security policies mapping. * @dev 2. A `SecurityPolicyOwnershipTransferred` event has been emitted. * * @param securityPolicyId The id of the security policy to update. */ function renounceSecurityPolicyOwnership(uint256 securityPolicyId) external override { _transferSecurityPolicyOwnership(securityPolicyId, address(0)); } /** * @notice Allows the smart contract, the contract owner, or the contract admin of any NFT collection to * set the security policy for their collection.. * * @dev Throws when the specified tokenAddress is address(0). * @dev Throws when the caller is not the contract, the owner or the administrator of the specified collection. * * @dev <h4>Postconditions:</h4> * @dev 1. The `tokenSecurityPolicies` mapping has be updated to reflect the designated security policy id. * @dev 2. An `UpdatedCollectionSecurityPolicy` event has been emitted. * * @param tokenAddress The smart contract address of the NFT collection. * @param securityPolicyId The security policy id to use for the collection. */ function setCollectionSecurityPolicy(address tokenAddress, uint256 securityPolicyId) external override { _requireCallerIsNFTOrContractOwnerOrAdmin(tokenAddress); if (securityPolicyId > lastSecurityPolicyId) { revert PaymentProcessor__SecurityPolicyDoesNotExist(); } tokenSecurityPolicies[tokenAddress] = securityPolicyId; emit UpdatedCollectionSecurityPolicy(tokenAddress, securityPolicyId); } /** * @notice Allows the smart contract, the contract owner, or the contract admin of any NFT collection to * specify the currency their collection is priced in. Only applicable when `enforcePricingConstraints` * security setting is in effect for a collection. * * @dev Throws when the specified tokenAddress is address(0). * @dev Throws when the caller is not the contract, the owner or the administrator of the specified tokenAddress. * @dev Throws when the specified coin address non-zero and does not implement decimals() > 0. * * @dev <h4>Postconditions:</h4> * @dev 1. The `collectionPaymentCoins` mapping has be updated to reflect the designated payment coin. * @dev 2. An `UpdatedCollectionPaymentCoin` event has been emitted. * * @param tokenAddress The smart contract address of the NFT collection. * @param coin The address of the designated ERC-20 payment coin smart contract. * Specify address(0) to designate native currency as the payment currency. */ function setCollectionPaymentCoin(address tokenAddress, address coin) external override { _requireCallerIsNFTOrContractOwnerOrAdmin(tokenAddress); collectionPaymentCoins[tokenAddress] = coin; emit UpdatedCollectionPaymentCoin(tokenAddress, coin); } /** * @notice Allows the smart contract, the contract owner, or the contract admin of any NFT collection to * specify their own bounded price at the collection level. * * @dev Throws when the specified tokenAddress is address(0). * @dev Throws when the caller is not the contract, the owner or the administrator of the specified tokenAddress. * @dev Throws when the previously set pricing bounds were set to be immutable. * @dev Throws when the specified floor price is greater than the ceiling price. * * @dev <h4>Postconditions:</h4> * @dev 1. The collection-level pricing bounds for the specified tokenAddress has been set. * @dev 2. An `UpdatedCollectionLevelPricingBoundaries` event has been emitted. * * @param tokenAddress The smart contract address of the NFT collection. * @param pricingBounds Including the floor price, ceiling price, and an immutability flag. */ function setCollectionPricingBounds(address tokenAddress, PricingBounds calldata pricingBounds) external override { _requireCallerIsNFTOrContractOwnerOrAdmin(tokenAddress); if(collectionPricingBounds[tokenAddress].isImmutable) { revert PaymentProcessor__PricingBoundsAreImmutable(); } if(pricingBounds.floorPrice > pricingBounds.ceilingPrice) { revert PaymentProcessor__CeilingPriceMustBeGreaterThanFloorPrice(); } collectionPricingBounds[tokenAddress] = pricingBounds; emit UpdatedCollectionLevelPricingBoundaries( tokenAddress, pricingBounds.floorPrice, pricingBounds.ceilingPrice); } /** * @notice Allows the smart contract, the contract owner, or the contract admin of any NFT collection to * specify their own bounded price at the individual token level. * * @dev Throws when the specified tokenAddress is address(0). * @dev Throws when the caller is not the contract, the owner or the administrator of the specified tokenAddress. * @dev Throws when the lengths of the tokenIds and pricingBounds array don't match. * @dev Throws when the tokenIds or pricingBounds array length is zero. * @dev Throws when the previously set pricing bounds of a token were set to be immutable. * @dev Throws when the any of the specified floor prices is greater than the ceiling price for that token id. * * @dev <h4>Postconditions:</h4> * @dev 1. The token-level pricing bounds for the specified tokenAddress and token ids has been set. * @dev 2. An `UpdatedTokenLevelPricingBoundaries` event has been emitted. * * @param tokenAddress The smart contract address of the NFT collection. * @param tokenIds An array of token ids for which pricing bounds are being set. * @param pricingBounds An array of pricing bounds used to set the floor, ceiling and immutability flag on the * individual token level. */ function setTokenPricingBounds( address tokenAddress, uint256[] calldata tokenIds, PricingBounds[] calldata pricingBounds) external override { _requireCallerIsNFTOrContractOwnerOrAdmin(tokenAddress); if(tokenIds.length != pricingBounds.length) { revert PaymentProcessor__InputArrayLengthMismatch(); } if(tokenIds.length == 0) { revert PaymentProcessor__InputArrayLengthCannotBeZero(); } mapping (uint256 => PricingBounds) storage ptrTokenPricingBounds = tokenPricingBounds[tokenAddress]; uint256 tokenId; for(uint256 i = 0; i < tokenIds.length;) { tokenId = tokenIds[i]; PricingBounds memory pricingBounds_ = pricingBounds[i]; if(ptrTokenPricingBounds[tokenId].isImmutable) { revert PaymentProcessor__PricingBoundsAreImmutable(); } if(pricingBounds_.floorPrice > pricingBounds_.ceilingPrice) { revert PaymentProcessor__CeilingPriceMustBeGreaterThanFloorPrice(); } ptrTokenPricingBounds[tokenId] = pricingBounds_; emit UpdatedTokenLevelPricingBoundaries( tokenAddress, tokenId, pricingBounds_.floorPrice, pricingBounds_.ceilingPrice); unchecked { ++i; } } } /** * @notice Allows security policy owners to whitelist an exchange. * * @dev Throws when caller is not the owner of the specified security policy. * @dev Throws when the specified address is address(0). * @dev Throws when the specified address is already whitelisted under the specified security policy. * * @dev <h4>Postconditions:</h4> * @dev 1. `account` has been whitelisted in `exchangeWhitelist` mapping. * @dev 2. An `ExchangeAddedToWhitelist` event has been emitted. * * @param securityPolicyId The id of the security policy to update. * @param account The address of the exchange to whitelist. */ function whitelistExchange(uint256 securityPolicyId, address account) external override { _requireCallerOwnsSecurityPolicy(securityPolicyId); if (account == address(0)) { revert PaymentProcessor__AddressCannotBeZero(); } mapping (address => bool) storage ptrExchangeWhitelist = exchangeWhitelist[securityPolicyId]; if (ptrExchangeWhitelist[account]) { revert PaymentProcessor__ExchangeIsWhitelisted(); } ptrExchangeWhitelist[account] = true; emit ExchangeAddedToWhitelist(securityPolicyId, account); } /** * @notice Allows security policy owners to remove an exchange from the whitelist. * * @dev Throws when caller is not the owner of the specified security policy. * @dev Throws when the specified address is not whitelisted under the specified security policy. * * @dev <h4>Postconditions:</h4> * @dev 1. `account` has been unwhitelisted and removed from the `exchangeWhitelist` mapping. * @dev 2. An `ExchangeRemovedFromWhitelist` event has been emitted. * * @param securityPolicyId The id of the security policy to update. * @param account The address of the exchange to unwhitelist. */ function unwhitelistExchange(uint256 securityPolicyId, address account) external override { _requireCallerOwnsSecurityPolicy(securityPolicyId); mapping (address => bool) storage ptrExchangeWhitelist = exchangeWhitelist[securityPolicyId]; if (!ptrExchangeWhitelist[account]) { revert PaymentProcessor__ExchangeIsNotWhitelisted(); } delete ptrExchangeWhitelist[account]; emit ExchangeRemovedFromWhitelist(securityPolicyId, account); } /** * @notice Allows security policy owners to approve a new coin for use as a payment currency. * * @dev Throws when caller is not the owner of the specified security policy. * @dev Throws when the specified coin address is address(0). * @dev Throws when the specified coin does not implement the decimals() that returns a non-zero value. * @dev Throws when the specified coin is already approved under the specified security policy. * * @dev <h4>Postconditions:</h4> * @dev 1. `coin` has been approved in `paymentMethodWhitelist` mapping. * @dev 2. A `PaymentMethodAddedToWhitelist` event has been emitted. * * @param securityPolicyId The id of the security policy to update. * @param coin The address of the coin to approve. */ function whitelistPaymentMethod(uint256 securityPolicyId, address coin) external override { _requireCallerOwnsSecurityPolicy(securityPolicyId); mapping (address => bool) storage ptrPaymentMethodWhitelist = paymentMethodWhitelist[securityPolicyId]; if (ptrPaymentMethodWhitelist[coin]) { revert PaymentProcessor__CoinIsApproved(); } ptrPaymentMethodWhitelist[coin] = true; emit PaymentMethodAddedToWhitelist(securityPolicyId, coin); } /** * @notice Allows security policy owners to remove a coin from the list of approved payment currencies. * * @dev Throws when caller is not the owner of the specified security policy. * @dev Throws when the specified coin is not currently approved under the specified security policy. * * @dev <h4>Postconditions:</h4> * @dev 1. `coin` has been removed from the `paymentMethodWhitelist` mapping. * @dev 2. A `PaymentMethodRemovedFromWhitelist` event has been emitted. * * @param securityPolicyId The id of the security policy to update. * @param coin The address of the coin to disapprove. */ function unwhitelistPaymentMethod(uint256 securityPolicyId, address coin) external override { _requireCallerOwnsSecurityPolicy(securityPolicyId); mapping (address => bool) storage ptrPaymentMethodWhitelist = paymentMethodWhitelist[securityPolicyId]; if (!ptrPaymentMethodWhitelist[coin]) { revert PaymentProcessor__CoinIsNotApproved(); } delete ptrPaymentMethodWhitelist[coin]; emit PaymentMethodRemovedFromWhitelist(securityPolicyId, coin); } /** * @notice Allows a user to revoke/cancel all prior signatures of listings and offers. * * @dev <h4>Postconditions:</h4> * @dev 1. The user's master nonce has been incremented by `1` in contract storage, rendering all signed * approvals using the prior nonce unusable. * @dev 2. A `MasterNonceInvalidated` event has been emitted. */ function revokeMasterNonce() external override { emit MasterNonceInvalidated(masterNonces[_msgSender()], _msgSender()); unchecked { ++masterNonces[_msgSender()]; } } /** * @notice Allows a user to revoke/cancel a single, previously signed listing or offer by specifying the marketplace * and nonce of the listing or offer. * * @dev Throws when the user has already revoked the nonce. * @dev Throws when the nonce was already used to successfully buy or sell an NFT. * * @dev <h4>Postconditions:</h4> * @dev 1. The specified `nonce` for the specified `marketplace` and `msg.sender` pair has been revoked and can * no longer be used to execute a sale or purchase. * @dev 2. A `RevokedListingOrOffer` event has been emitted. * * @param marketplace The marketplace where the `msg.sender` signed the listing or offer. * @param nonce The nonce that was signed in the revoked listing or offer. */ function revokeSingleNonce(address marketplace, uint256 nonce) external override { _checkAndInvalidateNonce(marketplace, _msgSender(), nonce, true); } /** * @notice Executes the sale of one ERC-721 or ERC-1155 token. * * @notice The seller's signature must be provided that proves that they approved the sale. * @notice This an an EIP-712 signature with the following data format. * @notice ```EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)``` * @notice ``` * SaleApproval( * uint8 protocol, * bool sellerAcceptedOffer, * address marketplace, * uint256 marketplaceFeeNumerator, * uint256 maxRoyaltyFeeNumerator, * address privateBuyer, * address seller, * address tokenAddress, * uint256 tokenId, * uint256 amount, * uint256 minPrice, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin) * ``` * * @notice The buyer's signature must be provided that proves that they approved the purchase. There are two * formats for this approval, one format to be used for collection-level offers when a specific token id is * not specified and one format to be used for item-level offers when a specific token id is specified. * * @notice This an an EIP-712 signature with the following data format. * @notice ```EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)``` * @notice ``` * OfferApproval( * uint8 protocol, * address marketplace, * uint256 marketplaceFeeNumerator, * address delegatedPurchaser, * address buyer, * address tokenAddress, * uint256 tokenId, * uint256 amount, * uint256 price, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin) * ``` * * @notice OR * * @notice ``` * CollectionOfferApproval( * uint8 protocol, * bool collectionLevelOffer, * address marketplace, * uint256 marketplaceFeeNumerator, * address delegatedPurchaser, * address buyer, * address tokenAddress, * uint256 amount, * uint256 price, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin) * ``` * * @dev WARNING: Calling marketplaces MUST be aware that for ERC-1155 sales, a `safeTransferFrom` function is * called which provides surface area for cross-contract re-entrancy. Marketplace contracts are responsible * for ensuring this is safely handled. * * @dev Throws when payment processor has been `paused`. * @dev Throws when payment method is ETH/native currency and offer price does not equal `msg.value`. * @dev Throws when payment method is ETH/native currency and the order was a collection or item offer. * @dev Throws when payment method is an ERC-20 coin and `msg.value` is not equal to zero. * @dev Throws when the protocol is ERC-721 and amount is not equal to `1`. * @dev Throws when the protocol is ERC-1155 and amount is equal to `0`. * @dev Throws when the expiration timestamp of the listing or offer is in the past/expired. * @dev Throws when the offer price is less than the seller-approved minimum price. * @dev Throws when the marketplace fee + royalty fee numerators exceeds 10,000 (100%). * @dev Throws when the collection security policy enforces pricing constraints and the payment/sale price * violates the constraints. * @dev Throws when a private buyer is specified and the buyer does not match the private buyer. * @dev Throws when a private buyer is specified and private listings are disabled by collection security policy. * @dev Throws when a delegated purchaser is specified and the `msg.sender` is not the delegated purchaser. * @dev Throws when a delegated purchaser is specified and delegated purchases are disabled by collection * security policy. * @dev Throws when the seller or buyer is a smart contract and EIP-1271 signatures are disabled by collection * security policy. * @dev Throws when the exchange whitelist is enforced by collection security policy and `msg.sender` is a * smart contract that is not on the whitelist. * @dev Throws when the exchange whitelist is enforced AND exchange whitelist EOA bypass is disabled by * collection security policy and `msg.sender` is an EOA that is not whitelisted. * @dev Throws when the seller's nonce on the specified marketplace has already been used to execute a sale. * @dev Throws when the seller's nonce on the specified marketplace has already been revoked/canceled. * @dev Throws when the buyer's nonce on the specified marketplace has already been used to execute a sale. * @dev Throws when the buyer's nonce on the specified marketplace has already been revoked/canceled. * @dev Throws when the `masterNonce` in the signed listing is not equal to the seller's current `masterNonce. * @dev Throws when the `masterNonce` in the signed offer is not equal to the buyer's current `masterNonce. * @dev Throws when the seller is an EOA and ECDSA recover operation on the SaleApproval EIP-712 signature * does not return the seller's address, meaning the seller did not approve the sale with the provided * sale details. * @dev Throws when the seller is a smart contract and EIP-1271 signature validation returns false for the * supplied listing signature. * @dev Throws when the buyer is an EOA and ECDSA recover operation on the OfferApproval EIP-712 signature * does not return the buyer's address, meaning the buyer did not approve the purchase with the provided * purchase details. * @dev Throws when the buyer is a smart contract and EIP-1271 signature validation returns false for the * supplied offer signature. * @dev Throws when the onchain royalty amount exceeds the seller-approved maximum royalty fee. * @dev Throws when the seller has not approved the Payment Processor contract for transfers of the specified * token or collection. * @dev Throws when transferFrom (ERC-721) or safeTransferFrom (ERC-1155) fails to transfer the token from the * seller to the buyer. * @dev Throws when the transfer of ERC-20 coin payment tokens from the purchaser fails. * @dev Throws when the distribution of native proceeds cannot be accepted or fails for any reason. * * @dev <h4>Postconditions:</h4> * @dev 1. The listing nonce for the specified marketplace and seller has been marked as invalidated so that it * cannot be replayed/used again. * @dev 2. The offer nonce for the specified marketplace and buyer has been marked as invalidated so that it * cannot be replayed/used again. * @dev 3. Applicable royalties have been paid to the address designated with EIP-2981 (when implemented on the * NFT contract). * @dev 4. Applicable marketplace fees have been paid to the designated marketplace. * @dev 5. All remaining funds have been paid to the seller of the token. * @dev 6. The `BuySingleListing` event has been emitted. * @dev 7. The token has been transferred from the seller to the buyer. * * @param saleDetails See `MatchedOrder` struct. * @param signedListing See `SignatureECSA` struct. * @param signedOffer See `SignatureECSA` struct. */ function buySingleListing( MatchedOrder memory saleDetails, SignatureECDSA memory signedListing, SignatureECDSA memory signedOffer ) external payable override { _requireNotPaused(); if (!_executeMatchedOrderSale(msg.value, saleDetails, signedListing, signedOffer)) { revert PaymentProcessor__DispensingTokenWasUnsuccessful(); } } /** * @notice Executes the sale of multiple ERC-721 or ERC-1155 tokens. * * @notice Sales may be a combination of native currency and ERC-20 payments. Matched orders may be any combination * of ERC-721 or ERC-1155 sales, as each matched order signature is validated independently against * individual listings/orders associated with the matched orders. * * @notice A batch of orders will be partially filled in the case where an NFT is not available at the time of sale, * but only if the method of payment is an ERC-20 token. Partial fills are not supported for native * payments to limit re-entrancy risks associated with issuing refunds. * * @notice The seller's signatures must be provided that proves that they approved the sales of each item. * @notice This an an EIP-712 signature with the following data format. * @notice ```EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)``` * @notice ``` * SaleApproval( * uint8 protocol, * bool sellerAcceptedOffer, * address marketplace, * uint256 marketplaceFeeNumerator, * uint256 maxRoyaltyFeeNumerator, * address privateBuyer, * address seller, * address tokenAddress, * uint256 tokenId, * uint256 amount, * uint256 minPrice, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin) * ``` * * @notice The buyer's signature must be provided that proves that they approved the purchase of each item. * There are two formats for this approval, one format to be used for collection-level offers when a * specific token id is not specified and one format to be used for item-level offers when a specific token * id is specified. * * @notice This an an EIP-712 signature with the following data format. * @notice ```EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)``` * @notice ``` * OfferApproval( * uint8 protocol, * address marketplace, * uint256 marketplaceFeeNumerator, * address delegatedPurchaser, * address buyer, * address tokenAddress, * uint256 tokenId, * uint256 amount, * uint256 price, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin) * ``` * * @notice OR * * @notice ``` * CollectionOfferApproval( * uint8 protocol, * bool collectionLevelOffer, * address marketplace, * uint256 marketplaceFeeNumerator, * address delegatedPurchaser, * address buyer, * address tokenAddress, * uint256 amount, * uint256 price, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin) * ``` * * @dev Throws when payment processor has been `paused`. * @dev Throws when any of the input arrays have mismatched lengths. * @dev Throws when any of the input arrays are empty. * @dev Throws when the the amount of native funds included isn't exactly equal to the sum of the native sale * prices of individual items. * @dev Throws when the the amount of ERC-20 funds approved is less than the sum of the ERC-20 * prices of individual items. * * @dev WARNING: Calling marketplaces MUST be aware that for ERC-1155 sales, a `safeTransferFrom` function is * called which provides surface area for cross-contract re-entrancy. Marketplace contracts are responsible * for ensuring this is safely handled. * * @dev For each individual matched order to process: * * @dev Throws when payment method is ETH/native currency and the order was a collection or item offer. * @dev Throws when payment method is an ERC-20 coin and supplied ETH/native funds for item is not equal to zero. * @dev Throws when the protocol is ERC-721 and amount is not equal to `1`. * @dev Throws when the protocol is ERC-1155 and amount is equal to `0`. * @dev Throws when the expiration timestamp of the listing or offer is in the past/expired. * @dev Throws when the offer price is less than the seller-approved minimum price. * @dev Throws when the marketplace fee + royalty fee numerators exceeds 10,000 (100%). * @dev Throws when the collection security policy enforces pricing constraints and the payment/sale price * violates the constraints. * @dev Throws when a private buyer is specified and the buyer does not match the private buyer. * @dev Throws when a private buyer is specified and private listings are disabled by collection security policy. * @dev Throws when a delegated purchaser is specified and the `msg.sender` is not the delegated purchaser. * @dev Throws when a delegated purchaser is specified and delegated purchases are disabled by collection * security policy. * @dev Throws when the seller or buyer is a smart contract and EIP-1271 signatures are disabled by collection * security policy. * @dev Throws when the exchange whitelist is enforced by collection security policy and `msg.sender` is a * smart contract that is not on the whitelist. * @dev Throws when the exchange whitelist is enforced AND exchange whitelist EOA bypass is disabled by * collection security policy and `msg.sender` is an EOA that is not whitelisted. * @dev Throws when the seller's nonce on the specified marketplace has already been used to execute a sale. * @dev Throws when the seller's nonce on the specified marketplace has already been revoked/canceled. * @dev Throws when the buyer's nonce on the specified marketplace has already been used to execute a sale. * @dev Throws when the buyer's nonce on the specified marketplace has already been revoked/canceled. * @dev Throws when the `masterNonce` in the signed listing is not equal to the seller's current `masterNonce. * @dev Throws when the `masterNonce` in the signed offer is not equal to the buyer's current `masterNonce. * @dev Throws when the seller is an EOA and ECDSA recover operation on the SaleApproval EIP-712 signature * does not return the seller's address, meaning the seller did not approve the sale with the provided * sale details. * @dev Throws when the seller is a smart contract and EIP-1271 signature validation returns false for the * supplied listing signature. * @dev Throws when the buyer is an EOA and ECDSA recover operation on the OfferApproval EIP-712 signature * does not return the buyer's address, meaning the buyer did not approve the purchase with the provided * purchase details. * @dev Throws when the buyer is a smart contract and EIP-1271 signature validation returns false for the * supplied offer signature. * @dev Throws when the onchain royalty amount exceeds the seller-approved maximum royalty fee. * @dev Throws when the seller has not approved the Payment Processor contract for transfers of the specified * token or collection. * @dev Throws when transferFrom (ERC-721) or safeTransferFrom (ERC-1155) fails to transfer the token from the * seller to the buyer and method of payment is native currency. (Partial fills allowed for ERC-20 payments). * @dev Throws when the transfer of ERC-20 coin payment tokens from the purchaser fails. * @dev Throws when the distribution of native proceeds cannot be accepted or fails for any reason. * * @dev <h4>Postconditions:</h4> * @dev For each item: * * @dev 1. The listing nonce for the specified marketplace and seller has been marked as invalidated so that it * cannot be replayed/used again. * @dev 2. The offer nonce for the specified marketplace and buyer has been marked as invalidated so that it * cannot be replayed/used again. * @dev 3. Applicable royalties have been paid to the address designated with EIP-2981 (when implemented on the * NFT contract). * @dev 4. Applicable marketplace fees have been paid to the designated marketplace. * @dev 5. All remaining funds have been paid to the seller of the token. * @dev 6. The `BuySingleListing` event has been emitted. * @dev 7. The token has been transferred from the seller to the buyer. * * @param saleDetailsArray An array of `MatchedOrder` structs. * @param signedListings An array of `SignatureECDSA` structs. * @param signedOffers An array of `SignatureECDSA` structs. */ function buyBatchOfListings( MatchedOrder[] calldata saleDetailsArray, SignatureECDSA[] calldata signedListings, SignatureECDSA[] calldata signedOffers ) external payable override { _requireNotPaused(); if (saleDetailsArray.length != signedListings.length || saleDetailsArray.length != signedOffers.length) { revert PaymentProcessor__InputArrayLengthMismatch(); } if (saleDetailsArray.length == 0) { revert PaymentProcessor__InputArrayLengthCannotBeZero(); } uint256 runningBalanceNativeProceeds = msg.value; MatchedOrder memory saleDetails; SignatureECDSA memory signedListing; SignatureECDSA memory signedOffer; uint256 msgValue; for (uint256 i = 0; i < saleDetailsArray.length;) { saleDetails = saleDetailsArray[i]; signedListing = signedListings[i]; signedOffer = signedOffers[i]; msgValue = 0; if(saleDetails.paymentCoin == address(0)) { msgValue = saleDetails.offerPrice; if (runningBalanceNativeProceeds < msgValue) { revert PaymentProcessor__RanOutOfNativeFunds(); } unchecked { runningBalanceNativeProceeds -= msgValue; } if (!_executeMatchedOrderSale(msgValue, saleDetails, signedListing, signedOffer)) { revert PaymentProcessor__DispensingTokenWasUnsuccessful(); } } else { _executeMatchedOrderSale(msgValue, saleDetails, signedListing, signedOffer); } unchecked { ++i; } } if (runningBalanceNativeProceeds > 0) { revert PaymentProcessor__OverpaidNativeFunds(); } } /** * @notice Executes the bundled sale of ERC-721 or ERC-1155 token listed by a single seller for a single collection. * * @notice Orders will be partially filled in the case where an NFT is not available at the time of sale, * but only if the method of payment is an ERC-20 token. Partial fills are not supported for native * payments to limit re-entrancy risks associated with issuing refunds. * * @notice The seller's signature must be provided that proves that they approved the sale of each token. * @notice This an an EIP-712 signature with the following data format. * @notice ```EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)``` * @notice ``` * BundledSaleApproval( * uint8 protocol, * address marketplace, * uint256 marketplaceFeeNumerator, * address privateBuyer, * address seller, * address tokenAddress, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin, * uint256[] tokenIds, * uint256[] amounts, * uint256[] maxRoyaltyFeeNumerators, * uint256[] itemPrices) * ``` * * @notice The buyer's signature must be provided that proves that they approved the purchase of each token. * @notice This an an EIP-712 signature with the following data format. * @notice ```EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)``` * @notice ``` * BundledOfferApproval( * uint8 protocol, * address marketplace, * uint256 marketplaceFeeNumerator, * address delegatedPurchaser, * address buyer, * address tokenAddress, * uint256 price, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin, * uint256[] tokenIds, * uint256[] amounts, * uint256[] itemSalePrices) * ``` * * @dev WARNING: Calling marketplaces MUST be aware that for ERC-1155 sales, a `safeTransferFrom` function is * called which provides surface area for cross-contract re-entrancy. Marketplace contracts are responsible * for ensuring this is safely handled. * * @dev Throws when payment processor has been `paused`. * @dev Throws when the bundled items array has a length of zero. * @dev Throws when payment method is ETH/native currency and offer price does not equal `msg.value`. * @dev Throws when payment method is an ERC-20 coin and `msg.value` is not equal to zero. * @dev Throws when the offer price does not equal the sum of the individual item prices in the listing. * @dev Throws when the expiration timestamp of the offer is in the past/expired. * @dev Throws when a private buyer is specified and the buyer does not match the private buyer. * @dev Throws when a private buyer is specified and private listings are disabled by collection security policy. * @dev Throws when a delegated purchaser is specified and the `msg.sender` is not the delegated purchaser. * @dev Throws when a delegated purchaser is specified and delegated purchases are disabled by collection * security policy. * @dev Throws when the exchange whitelist is enforced by collection security policy and `msg.sender` is a * smart contract that is not on the whitelist. * @dev Throws when the exchange whitelist is enforced AND exchange whitelist EOA bypass is disabled by * collection security policy and `msg.sender` is an EOA that is not whitelisted. * @dev Throws when the seller's nonce on the specified marketplace has already been used to execute a sale. * @dev Throws when the seller's nonce on the specified marketplace has already been revoked/canceled. * @dev Throws when the buyer's nonce on the specified marketplace has already been used to execute a sale. * @dev Throws when the buyer's nonce on the specified marketplace has already been revoked/canceled. * @dev Throws when the `masterNonce` in the signed listing is not equal to the seller's current `masterNonce. * @dev Throws when the `masterNonce` in the signed offer is not equal to the buyer's current `masterNonce. * @dev Throws when the seller is an EOA and ECDSA recover operation on the SaleApproval EIP-712 signature * does not return the seller's address, meaning the seller did not approve the sale with the provided * sale details. * @dev Throws when the seller is a smart contract and EIP-1271 signature validation returns false for the * supplied listing signature. * @dev Throws when the buyer is an EOA and ECDSA recover operation on the OfferApproval EIP-712 signature * does not return the buyer's address, meaning the buyer did not approve the purchase with the provided * purchase details. * @dev Throws when the buyer is a smart contract and EIP-1271 signature validation returns false for the * supplied offer signature. * @dev Throws when the transfer of ERC-20 coin payment tokens from the purchaser fails. * @dev Throws when the distribution of native proceeds cannot be accepted or fails for any reason. * * @dev For each item in the bundled listing: * * @dev Throws when the protocol is ERC-721 and amount is not equal to `1`. * @dev Throws when the protocol is ERC-1155 and amount is equal to `0`. * @dev Throws when the marketplace fee + royalty fee numerators exceeds 10,000 (100%). * @dev Throws when the collection security policy enforces pricing constraints and the payment/sale price * violates the constraints. * @dev Throws when the expiration timestamp of the listing is in the past/expired. * @dev Throws when the seller is a smart contract and EIP-1271 signatures are disabled by collection * security policy. * @dev Throws when the onchain royalty amount exceeds the seller-approved maximum royalty fee. * @dev Throws when the seller has not approved the Payment Processor contract for transfers of the specified * tokens in the collection. * @dev Throws when transferFrom (ERC-721) or safeTransferFrom (ERC-1155) fails to transfer the tokens from the * seller to the buyer and method of payment is native currency. (Partial fills allowed for ERC-20 payments). * * @dev <h4>Postconditions:</h4> * @dev 1. The listing nonce for the specified marketplace and seller has been marked as invalidated so that it * cannot be replayed/used again. * @dev 2. The offer nonce for the specified marketplace and buyer has been marked as invalidated so that it * cannot be replayed/used again. * @dev 3. Applicable royalties have been paid to the address designated with EIP-2981 (when implemented on the * NFT contract). * @dev 4. Applicable marketplace fees have been paid to the designated marketplace. * @dev 5. All remaining funds have been paid to the seller of the token. * @dev 6. The `BuyBundledListingERC721` or `BuyBundledListingERC1155` event has been emitted. * @dev 7. The tokens in the bundle has been transferred from the seller to the buyer. * * @param signedListing See `SignatureECSA` struct. * @param signedOffer See `SignatureECSA` struct. * @param bundleDetails See `MatchedOrderBundleExtended` struct. * @param bundleItems See `BundledItem` struct. */ function buyBundledListing( SignatureECDSA memory signedListing, SignatureECDSA memory signedOffer, MatchedOrderBundleExtended memory bundleDetails, BundledItem[] calldata bundleItems) external payable override { _requireNotPaused(); if (bundleItems.length == 0) { revert PaymentProcessor__InputArrayLengthCannotBeZero(); } (uint256 securityPolicyId, SecurityPolicy storage securityPolicy) = _getTokenSecurityPolicy(bundleDetails.bundleBase.tokenAddress); SignatureECDSA[] memory signedListingAsSingletonArray = new SignatureECDSA[](1); signedListingAsSingletonArray[0] = signedListing; (Accumulator memory accumulator, MatchedOrder[] memory saleDetailsBatch) = _validateBundledItems( false, securityPolicy, bundleDetails, bundleItems, signedListingAsSingletonArray ); _validateBundledOffer( securityPolicyId, securityPolicy, bundleDetails.bundleBase, accumulator, signedOffer ); bool[] memory unsuccessfulFills = _computeAndDistributeProceeds( ComputeAndDistributeProceedsArgs({ pushPaymentGasLimit: securityPolicy.pushPaymentGasLimit, purchaser: bundleDetails.bundleBase.delegatedPurchaser == address(0) ? bundleDetails.bundleBase.buyer : bundleDetails.bundleBase.delegatedPurchaser, paymentCoin: IERC20(bundleDetails.bundleBase.paymentCoin), funcPayout: bundleDetails.bundleBase.paymentCoin == address(0) ? _payoutNativeCurrency : _payoutCoinCurrency, funcDispenseToken: bundleDetails.bundleBase.protocol == TokenProtocols.ERC1155 ? _dispenseERC1155Token : _dispenseERC721Token }), saleDetailsBatch ); if (bundleDetails.bundleBase.protocol == TokenProtocols.ERC1155) { emit BuyBundledListingERC1155( bundleDetails.bundleBase.marketplace, bundleDetails.bundleBase.tokenAddress, bundleDetails.bundleBase.paymentCoin, bundleDetails.bundleBase.buyer, bundleDetails.seller, unsuccessfulFills, accumulator.tokenIds, accumulator.amounts, accumulator.salePrices); } else { emit BuyBundledListingERC721( bundleDetails.bundleBase.marketplace, bundleDetails.bundleBase.tokenAddress, bundleDetails.bundleBase.paymentCoin, bundleDetails.bundleBase.buyer, bundleDetails.seller, unsuccessfulFills, accumulator.tokenIds, accumulator.salePrices); } } /** * @notice Executes the bundled purchase of ERC-721 or ERC-1155 tokens individually listed for a single collection. * * @notice The seller's signatures must be provided that proves that they approved the sales of each item. * @notice This an an EIP-712 signature with the following data format. * @notice ```EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)``` * @notice ``` * SaleApproval( * uint8 protocol, * bool sellerAcceptedOffer, * address marketplace, * uint256 marketplaceFeeNumerator, * uint256 maxRoyaltyFeeNumerator, * address privateBuyer, * address seller, * address tokenAddress, * uint256 tokenId, * uint256 amount, * uint256 minPrice, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin) * ``` * * @notice The buyer's signature must be provided that proves that they approved the purchase of each token. * @notice This an an EIP-712 signature with the following data format. * @notice ```EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)``` * @notice ``` * BundledOfferApproval( * uint8 protocol, * address marketplace, * uint256 marketplaceFeeNumerator, * address delegatedPurchaser, * address buyer, * address tokenAddress, * uint256 price, * uint256 expiration, * uint256 nonce, * uint256 masterNonce, * address coin, * uint256[] tokenIds, * uint256[] amounts, * uint256[] itemSalePrices) * ``` * * @dev WARNING: Calling marketplaces MUST be aware that for ERC-1155 sales, a `safeTransferFrom` function is * called which provides surface area for cross-contract re-entrancy. Marketplace contracts are responsible * for ensuring this is safely handled. * * @dev Throws when payment processor has been `paused`. * @dev Throws when any of the input arrays have mismatched lengths. * @dev Throws when any of the input array have a length of zero. * @dev Throws when payment method is ETH/native currency and offer price does not equal `msg.value`. * @dev Throws when payment method is an ERC-20 coin and `msg.value` is not equal to zero. * @dev Throws when the offer price does not equal the sum of the individual item prices in the listing. * @dev Throws when the expiration timestamp of the offer is in the past/expired. * @dev Throws when a private buyer is specified and the buyer does not match the private buyer. * @dev Throws when a private buyer is specified and private listings are disabled by collection security policy. * @dev Throws when a delegated purchaser is specified and the `msg.sender` is not the delegated purchaser. * @dev Throws when a delegated purchaser is specified and delegated purchases are disabled by collection * security policy. * @dev Throws when the exchange whitelist is enforced by collection security policy and `msg.sender` is a * smart contract that is not on the whitelist. * @dev Throws when the exchange whitelist is enforced AND exchange whitelist EOA bypass is disabled by * collection security policy and `msg.sender` is an EOA that is not whitelisted. * @dev Throws when the buyer's nonce on the specified marketplace has already been used to execute a sale. * @dev Throws when the buyer's nonce on the specified marketplace has already been revoked/canceled. * @dev Throws when the `masterNonce` in the signed offer is not equal to the buyer's current `masterNonce. * @dev Throws when the buyer is an EOA and ECDSA recover operation on the OfferApproval EIP-712 signature * does not return the buyer's address, meaning the buyer did not approve the purchase with the provided * purchase details. * @dev Throws when the buyer is a smart contract and EIP-1271 signature validation returns false for the * supplied offer signature. * @dev Throws when the transfer of ERC-20 coin payment tokens from the purchaser fails. * @dev Throws when the distribution of native proceeds cannot be accepted or fails for any reason. * * @dev For each item in the bundled listing: * * @dev Throws when the protocol is ERC-721 and amount is not equal to `1`. * @dev Throws when the protocol is ERC-1155 and amount is equal to `0`. * @dev Throws when the marketplace fee + royalty fee numerators exceeds 10,000 (100%). * @dev Throws when the collection security policy enforces pricing constraints and the payment/sale price * violates the constraints. * @dev Throws when the expiration timestamp of the listing is in the past/expired. * @dev Throws when the seller's nonce on the specified marketplace has already been used to execute a sale. * @dev Throws when the seller's nonce on the specified marketplace has already been revoked/canceled. * @dev Throws when the `masterNonce` in the signed listing is not equal to the seller's current `masterNonce. * @dev Throws when the seller is a smart contract and EIP-1271 signatures are disabled by collection * security policy. * @dev Throws when the seller is an EOA and ECDSA recover operation on the SaleApproval EIP-712 signature * does not return the seller's address, meaning the seller did not approve the sale with the provided * sale details. * @dev Throws when the seller is a smart contract and EIP-1271 signature validation returns false for the * supplied listing signature. * @dev Throws when the onchain royalty amount exceeds the seller-approved maximum royalty fee. * @dev Throws when the seller has not approved the Payment Processor contract for transfers of the specified * tokens in the collection. * @dev Throws when transferFrom (ERC-721) or safeTransferFrom (ERC-1155) fails to transfer the tokens from the * seller to the buyer and method of payment is native currency. (Partial fills allowed for ERC-20 payments). * * @dev <h4>Postconditions:</h4> * @dev 1. The listing nonce for the specified marketplace and seller has been marked as invalidated so that it * cannot be replayed/used again. * @dev 2. The offer nonce for the specified marketplace and buyer has been marked as invalidated so that it * cannot be replayed/used again. * @dev 3. Applicable royalties have been paid to the address designated with EIP-2981 (when implemented on the * NFT contract). * @dev 4. Applicable marketplace fees have been paid to the designated marketplace. * @dev 5. All remaining funds have been paid to the seller of the token. * @dev 6. The `SweepCollectionERC721` or `SweepCollectionERC1155` event has been emitted. * @dev 7. The tokens in the bundle has been transferred from the seller to the buyer. * * @param signedOffer See `SignatureECSA` struct. * @param bundleDetails See `MatchedOrderBundleBase` struct. * @param bundleItems See `BundledItem` struct. * @param signedListings See `SignatureECSA` struct. */ function sweepCollection( SignatureECDSA memory signedOffer, MatchedOrderBundleBase memory bundleDetails, BundledItem[] calldata bundleItems, SignatureECDSA[] calldata signedListings) external payable override { _requireNotPaused(); if (bundleItems.length != signedListings.length) { revert PaymentProcessor__InputArrayLengthMismatch(); } if (bundleItems.length == 0) { revert PaymentProcessor__InputArrayLengthCannotBeZero(); } (uint256 securityPolicyId, SecurityPolicy storage securityPolicy) = _getTokenSecurityPolicy(bundleDetails.tokenAddress); (Accumulator memory accumulator, MatchedOrder[] memory saleDetailsBatch) = _validateBundledItems( true, securityPolicy, MatchedOrderBundleExtended({ bundleBase: bundleDetails, seller: address(0), listingNonce: 0, listingExpiration: 0 }), bundleItems, signedListings ); _validateBundledOffer( securityPolicyId, securityPolicy, bundleDetails, accumulator, signedOffer ); bool[] memory unsuccessfulFills = _computeAndDistributeProceeds( ComputeAndDistributeProceedsArgs({ pushPaymentGasLimit: securityPolicy.pushPaymentGasLimit, purchaser: bundleDetails.delegatedPurchaser == address(0) ? bundleDetails.buyer : bundleDetails.delegatedPurchaser, paymentCoin: IERC20(bundleDetails.paymentCoin), funcPayout: bundleDetails.paymentCoin == address(0) ? _payoutNativeCurrency : _payoutCoinCurrency, funcDispenseToken: bundleDetails.protocol == TokenProtocols.ERC1155 ? _dispenseERC1155Token : _dispenseERC721Token }), saleDetailsBatch ); if (bundleDetails.protocol == TokenProtocols.ERC1155) { emit SweepCollectionERC1155( bundleDetails.marketplace, bundleDetails.tokenAddress, bundleDetails.paymentCoin, bundleDetails.buyer, unsuccessfulFills, accumulator.sellers, accumulator.tokenIds, accumulator.amounts, accumulator.salePrices); } else { emit SweepCollectionERC721( bundleDetails.marketplace, bundleDetails.tokenAddress, bundleDetails.paymentCoin, bundleDetails.buyer, unsuccessfulFills, accumulator.sellers, accumulator.tokenIds, accumulator.salePrices); } } /** * @notice Returns the EIP-712 domain separator for this contract. */ function getDomainSeparator() external view override returns (bytes32) { return _domainSeparatorV4(); } /** * @notice Returns the security policy details for the specified security policy id. * * @param securityPolicyId The security policy id to lookup. * @return securityPolicy The security policy details. */ function getSecurityPolicy(uint256 securityPolicyId) external view override returns (SecurityPolicy memory) { return securityPolicies[securityPolicyId]; } /** * @notice Returns whitelist status of the exchange address for the specified security policy id. * * @param securityPolicyId The security policy id to lookup. * @param account The address to check. * @return isWhitelisted True if the address is whitelisted, false otherwise. */ function isWhitelisted(uint256 securityPolicyId, address account) external view override returns (bool) { return exchangeWhitelist[securityPolicyId][account]; } /** * @notice Returns approval status of the payment coin address for the specified security policy id. * * @param securityPolicyId The security policy id to lookup. * @param coin The coin address to check. * @return isPaymentMethodApproved True if the coin address is approved, false otherwise. */ function isPaymentMethodApproved(uint256 securityPolicyId, address coin) external view override returns (bool) { return paymentMethodWhitelist[securityPolicyId][coin]; } /** * @notice Returns the current security policy id for the specified collection address. * * @param collectionAddress The address of the collection to lookup. * @return securityPolicyId The current security policy id for the specifed collection. */ function getTokenSecurityPolicyId(address collectionAddress) external view override returns (uint256) { return tokenSecurityPolicies[collectionAddress]; } /** * @notice Returns whether or not the price of a collection is immutable. * @param tokenAddress The smart contract address of the NFT collection. * @return True if the floor and ceiling price for the specified token contract has been set immutably, false otherwise. */ function isCollectionPricingImmutable(address tokenAddress) external view override returns (bool) { return collectionPricingBounds[tokenAddress].isImmutable; } /** * @notice Returns whether or not the price of a specific token is immutable. * @param tokenAddress The smart contract address of the NFT collection. * @param tokenId The token id. * @return True if the floor and ceiling price for the specified token contract and tokenId has been set immutably, false otherwise. */ function isTokenPricingImmutable(address tokenAddress, uint256 tokenId) external view override returns (bool) { return tokenPricingBounds[tokenAddress][tokenId].isImmutable; } /** * @notice Gets the floor price for the specified nft contract address and token id. * * @param tokenAddress The smart contract address of the NFT collection. * @param tokenId The token id. * @return The floor price. */ function getFloorPrice(address tokenAddress, uint256 tokenId) external view override returns (uint256) { (uint256 floorPrice,) = _getFloorAndCeilingPrices(tokenAddress, tokenId); return floorPrice; } /** * @notice Gets the ceiling price for the specified nft contract address and token id. * * @param tokenAddress The smart contract address of the NFT collection. * @param tokenId The token id. * @return The ceiling price. */ function getCeilingPrice(address tokenAddress, uint256 tokenId) external view override returns (uint256) { (, uint256 ceilingPrice) = _getFloorAndCeilingPrices(tokenAddress, tokenId); return ceilingPrice; } /** * @notice ERC-165 Interface Introspection Support. * @dev Supports `IPaymentProcessor` interface as well as parent contract interfaces. * @param interfaceId The interface to query. * @return True if the interface is supported, false otherwise. */ function supportsInterface( bytes4 interfaceId ) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IPaymentProcessor).interfaceId || super.supportsInterface(interfaceId); } function _payoutNativeCurrency( address payee, address /*payer*/, IERC20 /*paymentCoin*/, uint256 proceeds, uint256 gasLimit_) internal { _pushProceeds(payee, proceeds, gasLimit_); } function _payoutCoinCurrency( address payee, address payer, IERC20 paymentCoin, uint256 proceeds, uint256 /*gasLimit_*/) internal { SafeERC20.safeTransferFrom(paymentCoin, payer, payee, proceeds); } function _dispenseERC721Token( address from, address to, address tokenAddress, uint256 tokenId, uint256 /*amount*/) internal returns (bool) { try IERC721(tokenAddress).transferFrom(from, to, tokenId) { return true; } catch { return false; } } function _dispenseERC1155Token( address from, address to, address tokenAddress, uint256 tokenId, uint256 amount) internal returns (bool) { try IERC1155(tokenAddress).safeTransferFrom(from, to, tokenId, amount, "") { return true; } catch { return false; } } function _requireCallerIsNFTOrContractOwnerOrAdmin(address tokenAddress) internal view { bool callerHasPermissions = false; callerHasPermissions = _msgSender() == tokenAddress; if(!callerHasPermissions) { try IOwnable(tokenAddress).owner() returns (address contractOwner) { callerHasPermissions = _msgSender() == contractOwner; } catch {} if(!callerHasPermissions) { try IAccessControl(tokenAddress).hasRole(DEFAULT_ACCESS_CONTROL_ADMIN_ROLE, _msgSender()) returns (bool callerIsContractAdmin) { callerHasPermissions = callerIsContractAdmin; } catch {} } } if(!callerHasPermissions) { revert PaymentProcessor__CallerMustHaveElevatedPermissionsForSpecifiedNFT(); } } function _verifyPaymentCoinIsApproved( uint256 securityPolicyId, bool enforcePaymentMethodWhitelist, bool enforcePricingConstraints, address tokenAddress, address coin) internal view virtual { if (enforcePricingConstraints) { if(collectionPaymentCoins[tokenAddress] != coin) { revert PaymentProcessor__PaymentCoinIsNotAnApprovedPaymentMethod(); } } else if (enforcePaymentMethodWhitelist) { if (!paymentMethodWhitelist[securityPolicyId][coin]) { revert PaymentProcessor__PaymentCoinIsNotAnApprovedPaymentMethod(); } } } function _createOrUpdateSecurityPolicy( uint256 securityPolicyId, bool enforceExchangeWhitelist, bool enforcePaymentMethodWhitelist, bool enforcePricingConstraints, bool disablePrivateListings, bool disableDelegatedPurchases, bool disableEIP1271Signatures, bool disableExchangeWhitelistEOABypass, uint32 pushPaymentGasLimit, string calldata registryName) private { securityPolicies[securityPolicyId] = SecurityPolicy({ enforceExchangeWhitelist: enforceExchangeWhitelist, enforcePaymentMethodWhitelist: enforcePaymentMethodWhitelist, enforcePricingConstraints: enforcePricingConstraints, disablePrivateListings: disablePrivateListings, disableDelegatedPurchases: disableDelegatedPurchases, disableEIP1271Signatures: disableEIP1271Signatures, disableExchangeWhitelistEOABypass: disableExchangeWhitelistEOABypass, pushPaymentGasLimit: pushPaymentGasLimit, policyOwner: _msgSender() }); emit CreatedOrUpdatedSecurityPolicy( securityPolicyId, enforceExchangeWhitelist, enforcePaymentMethodWhitelist, enforcePricingConstraints, disablePrivateListings, disableDelegatedPurchases, disableEIP1271Signatures, disableExchangeWhitelistEOABypass, pushPaymentGasLimit, registryName); } function _transferSecurityPolicyOwnership(uint256 securityPolicyId, address newOwner) private { _requireCallerOwnsSecurityPolicy(securityPolicyId); SecurityPolicy storage securityPolicy = securityPolicies[securityPolicyId]; address oldOwner = securityPolicy.policyOwner; securityPolicy.policyOwner = newOwner; emit SecurityPolicyOwnershipTransferred(oldOwner, newOwner); } function _executeMatchedOrderSale( uint256 msgValue, MatchedOrder memory saleDetails, SignatureECDSA memory signedListing, SignatureECDSA memory signedOffer ) private returns (bool tokenDispensedSuccessfully) { uint256 securityPolicyId = tokenSecurityPolicies[saleDetails.tokenAddress]; SecurityPolicy memory securityPolicy = securityPolicies[securityPolicyId]; if (saleDetails.paymentCoin == address(0)) { if (saleDetails.offerPrice != msgValue) { revert PaymentProcessor__OfferPriceMustEqualSalePrice(); } if (saleDetails.sellerAcceptedOffer || saleDetails.seller == tx.origin) { revert PaymentProcessor__CollectionLevelOrItemLevelOffersCanOnlyBeMadeUsingERC20PaymentMethods(); } } else { if (msgValue > 0) { revert PaymentProcessor__CannotIncludeNativeFundsWhenPaymentMethodIsAnERC20Coin(); } _verifyPaymentCoinIsApproved( securityPolicyId, securityPolicy.enforcePaymentMethodWhitelist, securityPolicy.enforcePricingConstraints, saleDetails.tokenAddress, saleDetails.paymentCoin); } if (saleDetails.protocol == TokenProtocols.ERC1155) { if (saleDetails.amount == 0) { revert PaymentProcessor__AmountForERC1155SalesGreaterThanZero(); } } else { if (saleDetails.amount != ONE) { revert PaymentProcessor__AmountForERC721SalesMustEqualOne(); } } if (block.timestamp > saleDetails.listingExpiration) { revert PaymentProcessor__SaleHasExpired(); } if (block.timestamp > saleDetails.offerExpiration) { revert PaymentProcessor__OfferHasExpired(); } if (saleDetails.offerPrice < saleDetails.listingMinPrice) { revert PaymentProcessor__SalePriceBelowSellerApprovedMinimum(); } if (saleDetails.marketplaceFeeNumerator + saleDetails.maxRoyaltyFeeNumerator > FEE_DENOMINATOR) { revert PaymentProcessor__MarketplaceAndRoyaltyFeesWillExceedSalePrice(); } if (saleDetails.privateBuyer != address(0)) { if (saleDetails.buyer != saleDetails.privateBuyer) { revert PaymentProcessor__BuyerMustBeDesignatedPrivateBuyer(); } if (securityPolicy.disablePrivateListings) { revert PaymentProcessor__TokenSecurityPolicyDoesNotAllowPrivateListings(); } } if (saleDetails.delegatedPurchaser != address(0)) { if (_msgSender() != saleDetails.delegatedPurchaser) { revert PaymentProcessor__CallerIsNotTheDelegatedPurchaser(); } if(securityPolicy.disableDelegatedPurchases) { revert PaymentProcessor__TokenSecurityPolicyDoesNotAllowDelegatedPurchases(); } } if(securityPolicy.disableEIP1271Signatures) { if (saleDetails.seller.code.length > 0) { revert PaymentProcessor__EIP1271SignaturesAreDisabled(); } if (saleDetails.buyer.code.length > 0) { revert PaymentProcessor__EIP1271SignaturesAreDisabled(); } } if (securityPolicy.enforceExchangeWhitelist) { if (_msgSender() != tx.origin) { if (!exchangeWhitelist[securityPolicyId][_msgSender()]) { revert PaymentProcessor__CallerIsNotWhitelistedMarketplace(); } } else if (securityPolicy.disableExchangeWhitelistEOABypass) { if (!exchangeWhitelist[securityPolicyId][_msgSender()]) { revert PaymentProcessor__TokenSecurityPolicyDoesNotAllowEOACallers(); } } } if (securityPolicy.enforcePricingConstraints) { if (saleDetails.paymentCoin == address(0)) { if(collectionPaymentCoins[saleDetails.tokenAddress] != address(0)) { revert PaymentProcessor__NativeCurrencyIsNotAnApprovedPaymentMethod(); } } _verifySalePriceInRange( saleDetails.tokenAddress, saleDetails.tokenId, saleDetails.amount, saleDetails.offerPrice); } _verifySignedItemListing(saleDetails, signedListing); if (saleDetails.collectionLevelOffer) { _verifySignedCollectionOffer(saleDetails, signedOffer); } else { _verifySignedItemOffer(saleDetails, signedOffer); } MatchedOrder[] memory saleDetailsSingletonBatch = new MatchedOrder[](1); saleDetailsSingletonBatch[0] = saleDetails; bool[] memory unsuccessfulFills = _computeAndDistributeProceeds( ComputeAndDistributeProceedsArgs({ pushPaymentGasLimit: securityPolicy.pushPaymentGasLimit, purchaser: saleDetails.delegatedPurchaser == address(0) ? saleDetails.buyer : saleDetails.delegatedPurchaser, paymentCoin: IERC20(saleDetails.paymentCoin), funcPayout: saleDetails.paymentCoin == address(0) ? _payoutNativeCurrency : _payoutCoinCurrency, funcDispenseToken: saleDetails.protocol == TokenProtocols.ERC1155 ? _dispenseERC1155Token : _dispenseERC721Token }), saleDetailsSingletonBatch ); tokenDispensedSuccessfully = !unsuccessfulFills[0]; if (tokenDispensedSuccessfully) { emit BuySingleListing( saleDetails.marketplace, saleDetails.tokenAddress, saleDetails.paymentCoin, saleDetails.buyer, saleDetails.seller, saleDetails.tokenId, saleDetails.amount, saleDetails.offerPrice); } } function _validateBundledOffer( uint256 securityPolicyId, SecurityPolicy storage securityPolicy, MatchedOrderBundleBase memory bundleDetails, Accumulator memory accumulator, SignatureECDSA memory signedOffer) private { if (bundleDetails.paymentCoin != address(0)) { if (msg.value > 0) { revert PaymentProcessor__CannotIncludeNativeFundsWhenPaymentMethodIsAnERC20Coin(); } _verifyPaymentCoinIsApproved( securityPolicyId, securityPolicy.enforcePaymentMethodWhitelist, securityPolicy.enforcePricingConstraints, bundleDetails.tokenAddress, bundleDetails.paymentCoin); } else { if (msg.value != bundleDetails.offerPrice) { revert PaymentProcessor__OfferPriceMustEqualSalePrice(); } if (securityPolicy.enforcePricingConstraints) { if(collectionPaymentCoins[bundleDetails.tokenAddress] != address(0)) { revert PaymentProcessor__NativeCurrencyIsNotAnApprovedPaymentMethod(); } } } if (block.timestamp > bundleDetails.offerExpiration) { revert PaymentProcessor__OfferHasExpired(); } if (bundleDetails.delegatedPurchaser != address(0)) { if (_msgSender() != bundleDetails.delegatedPurchaser) { revert PaymentProcessor__CallerIsNotTheDelegatedPurchaser(); } if(securityPolicy.disableDelegatedPurchases) { revert PaymentProcessor__TokenSecurityPolicyDoesNotAllowDelegatedPurchases(); } } if(securityPolicy.disableEIP1271Signatures) { if (bundleDetails.buyer.code.length > 0) { revert PaymentProcessor__EIP1271SignaturesAreDisabled(); } } if (securityPolicy.enforceExchangeWhitelist) { if (_msgSender() != tx.origin) { if (!exchangeWhitelist[securityPolicyId][_msgSender()]) { revert PaymentProcessor__CallerIsNotWhitelistedMarketplace(); } } else if (securityPolicy.disableExchangeWhitelistEOABypass) { if (!exchangeWhitelist[securityPolicyId][_msgSender()]) { revert PaymentProcessor__TokenSecurityPolicyDoesNotAllowEOACallers(); } } } if (accumulator.sumListingPrices != bundleDetails.offerPrice) { revert PaymentProcessor__BundledOfferPriceMustEqualSumOfAllListingPrices(); } _verifySignedOfferForBundledItems( keccak256(abi.encodePacked(accumulator.tokenIds)), keccak256(abi.encodePacked(accumulator.amounts)), keccak256(abi.encodePacked(accumulator.salePrices)), bundleDetails, signedOffer ); } function _validateBundledItems( bool individualListings, SecurityPolicy storage securityPolicy, MatchedOrderBundleExtended memory bundleDetails, BundledItem[] memory bundledOfferItems, SignatureECDSA[] memory signedListings) private returns (Accumulator memory accumulator, MatchedOrder[] memory saleDetailsBatch) { saleDetailsBatch = new MatchedOrder[](bundledOfferItems.length); accumulator = Accumulator({ tokenIds: new uint256[](bundledOfferItems.length), amounts: new uint256[](bundledOfferItems.length), salePrices: new uint256[](bundledOfferItems.length), maxRoyaltyFeeNumerators: new uint256[](bundledOfferItems.length), sellers: new address[](bundledOfferItems.length), sumListingPrices: 0 }); for (uint256 i = 0; i < bundledOfferItems.length;) { address seller = bundleDetails.seller; uint256 listingNonce = bundleDetails.listingNonce; uint256 listingExpiration = bundleDetails.listingExpiration; if (individualListings) { seller = bundledOfferItems[i].seller; listingNonce = bundledOfferItems[i].listingNonce; listingExpiration = bundledOfferItems[i].listingExpiration; } MatchedOrder memory saleDetails = MatchedOrder({ sellerAcceptedOffer: false, collectionLevelOffer: false, protocol: bundleDetails.bundleBase.protocol, paymentCoin: bundleDetails.bundleBase.paymentCoin, tokenAddress: bundleDetails.bundleBase.tokenAddress, seller: seller, privateBuyer: bundleDetails.bundleBase.privateBuyer, buyer: bundleDetails.bundleBase.buyer, delegatedPurchaser: bundleDetails.bundleBase.delegatedPurchaser, marketplace: bundleDetails.bundleBase.marketplace, marketplaceFeeNumerator: bundleDetails.bundleBase.marketplaceFeeNumerator, maxRoyaltyFeeNumerator: bundledOfferItems[i].maxRoyaltyFeeNumerator, listingNonce: listingNonce, offerNonce: bundleDetails.bundleBase.offerNonce, listingMinPrice: bundledOfferItems[i].itemPrice, offerPrice: bundledOfferItems[i].itemPrice, listingExpiration: listingExpiration, offerExpiration: bundleDetails.bundleBase.offerExpiration, tokenId: bundledOfferItems[i].tokenId, amount: bundledOfferItems[i].amount }); saleDetailsBatch[i] = saleDetails; accumulator.tokenIds[i] = saleDetails.tokenId; accumulator.amounts[i] = saleDetails.amount; accumulator.salePrices[i] = saleDetails.listingMinPrice; accumulator.maxRoyaltyFeeNumerators[i] = saleDetails.maxRoyaltyFeeNumerator; accumulator.sellers[i] = saleDetails.seller; accumulator.sumListingPrices += saleDetails.listingMinPrice; if (saleDetails.protocol == TokenProtocols.ERC1155) { if (saleDetails.amount == 0) { revert PaymentProcessor__AmountForERC1155SalesGreaterThanZero(); } } else { if (saleDetails.amount != ONE) { revert PaymentProcessor__AmountForERC721SalesMustEqualOne(); } } if (saleDetails.marketplaceFeeNumerator + saleDetails.maxRoyaltyFeeNumerator > FEE_DENOMINATOR) { revert PaymentProcessor__MarketplaceAndRoyaltyFeesWillExceedSalePrice(); } if (securityPolicy.enforcePricingConstraints) { _verifySalePriceInRange( saleDetails.tokenAddress, saleDetails.tokenId, saleDetails.amount, saleDetails.offerPrice); } if (individualListings) { if (block.timestamp > saleDetails.listingExpiration) { revert PaymentProcessor__SaleHasExpired(); } if (saleDetails.privateBuyer != address(0)) { if (saleDetails.buyer != saleDetails.privateBuyer) { revert PaymentProcessor__BuyerMustBeDesignatedPrivateBuyer(); } if (securityPolicy.disablePrivateListings) { revert PaymentProcessor__TokenSecurityPolicyDoesNotAllowPrivateListings(); } } if(securityPolicy.disableEIP1271Signatures) { if (saleDetails.seller.code.length > 0) { revert PaymentProcessor__EIP1271SignaturesAreDisabled(); } } _verifySignedItemListing(saleDetails, signedListings[i]); } unchecked { ++i; } } if(!individualListings) { if (block.timestamp > bundleDetails.listingExpiration) { revert PaymentProcessor__SaleHasExpired(); } if (bundleDetails.bundleBase.privateBuyer != address(0)) { if (bundleDetails.bundleBase.buyer != bundleDetails.bundleBase.privateBuyer) { revert PaymentProcessor__BuyerMustBeDesignatedPrivateBuyer(); } if (securityPolicy.disablePrivateListings) { revert PaymentProcessor__TokenSecurityPolicyDoesNotAllowPrivateListings(); } } if(securityPolicy.disableEIP1271Signatures) { if (bundleDetails.seller.code.length > 0) { revert PaymentProcessor__EIP1271SignaturesAreDisabled(); } } _verifySignedBundleListing( AccumulatorHashes({ tokenIdsKeccakHash: keccak256(abi.encodePacked(accumulator.tokenIds)), amountsKeccakHash: keccak256(abi.encodePacked(accumulator.amounts)), maxRoyaltyFeeNumeratorsKeccakHash: keccak256(abi.encodePacked(accumulator.maxRoyaltyFeeNumerators)), itemPricesKeccakHash: keccak256(abi.encodePacked(accumulator.salePrices)) }), bundleDetails, signedListings[0]); } } function _verifySignedItemOffer( MatchedOrder memory saleDetails, SignatureECDSA memory signedOffer) private { bytes32 digest = _hashTypedDataV4(keccak256( bytes.concat( abi.encode( OFFER_APPROVAL_HASH, uint8(saleDetails.protocol), saleDetails.marketplace, saleDetails.marketplaceFeeNumerator, saleDetails.delegatedPurchaser, saleDetails.buyer, saleDetails.tokenAddress, saleDetails.tokenId, saleDetails.amount, saleDetails.offerPrice ), abi.encode( saleDetails.offerExpiration, saleDetails.offerNonce, _checkAndInvalidateNonce( saleDetails.marketplace, saleDetails.buyer, saleDetails.offerNonce, false ), saleDetails.paymentCoin ) ) ) ); if(saleDetails.buyer.code.length > 0) { _verifyEIP1271Signature(saleDetails.buyer, digest, signedOffer); } else if (saleDetails.buyer != ECDSA.recover(digest, signedOffer.v, signedOffer.r, signedOffer.s)) { revert PaymentProcessor__BuyerDidNotAuthorizePurchase(); } } function _verifySignedCollectionOffer( MatchedOrder memory saleDetails, SignatureECDSA memory signedOffer) private { bytes32 digest = _hashTypedDataV4(keccak256( bytes.concat( abi.encode( COLLECTION_OFFER_APPROVAL_HASH, uint8(saleDetails.protocol), saleDetails.collectionLevelOffer, saleDetails.marketplace, saleDetails.marketplaceFeeNumerator, saleDetails.delegatedPurchaser, saleDetails.buyer, saleDetails.tokenAddress, saleDetails.amount, saleDetails.offerPrice ), abi.encode( saleDetails.offerExpiration, saleDetails.offerNonce, _checkAndInvalidateNonce( saleDetails.marketplace, saleDetails.buyer, saleDetails.offerNonce, false ), saleDetails.paymentCoin ) ) ) ); if(saleDetails.buyer.code.length > 0) { _verifyEIP1271Signature(saleDetails.buyer, digest, signedOffer); } else if (saleDetails.buyer != ECDSA.recover(digest, signedOffer.v, signedOffer.r, signedOffer.s)) { revert PaymentProcessor__BuyerDidNotAuthorizePurchase(); } } function _verifySignedOfferForBundledItems( bytes32 tokenIdsKeccakHash, bytes32 amountsKeccakHash, bytes32 salePricesKeccakHash, MatchedOrderBundleBase memory bundledOfferDetails, SignatureECDSA memory signedOffer) private { bytes32 digest = _hashTypedDataV4(keccak256( bytes.concat( abi.encode( BUNDLED_OFFER_APPROVAL_HASH, uint8(bundledOfferDetails.protocol), bundledOfferDetails.marketplace, bundledOfferDetails.marketplaceFeeNumerator, bundledOfferDetails.delegatedPurchaser, bundledOfferDetails.buyer, bundledOfferDetails.tokenAddress, bundledOfferDetails.offerPrice ), abi.encode( bundledOfferDetails.offerExpiration, bundledOfferDetails.offerNonce, _checkAndInvalidateNonce( bundledOfferDetails.marketplace, bundledOfferDetails.buyer, bundledOfferDetails.offerNonce, false ), bundledOfferDetails.paymentCoin, tokenIdsKeccakHash, amountsKeccakHash, salePricesKeccakHash ) ) ) ); if(bundledOfferDetails.buyer.code.length > 0) { _verifyEIP1271Signature(bundledOfferDetails.buyer, digest, signedOffer); } else if (bundledOfferDetails.buyer != ECDSA.recover(digest, signedOffer.v, signedOffer.r, signedOffer.s)) { revert PaymentProcessor__BuyerDidNotAuthorizePurchase(); } } function _verifySignedBundleListing( AccumulatorHashes memory accumulatorHashes, MatchedOrderBundleExtended memory bundleDetails, SignatureECDSA memory signedListing) private { bytes32 digest = _hashTypedDataV4(keccak256( bytes.concat( abi.encode( BUNDLED_SALE_APPROVAL_HASH, uint8(bundleDetails.bundleBase.protocol), bundleDetails.bundleBase.marketplace, bundleDetails.bundleBase.marketplaceFeeNumerator, bundleDetails.bundleBase.privateBuyer, bundleDetails.seller, bundleDetails.bundleBase.tokenAddress ), abi.encode( bundleDetails.listingExpiration, bundleDetails.listingNonce, _checkAndInvalidateNonce( bundleDetails.bundleBase.marketplace, bundleDetails.seller, bundleDetails.listingNonce, false ), bundleDetails.bundleBase.paymentCoin, accumulatorHashes.tokenIdsKeccakHash, accumulatorHashes.amountsKeccakHash, accumulatorHashes.maxRoyaltyFeeNumeratorsKeccakHash, accumulatorHashes.itemPricesKeccakHash ) ) ) ); if(bundleDetails.seller.code.length > 0) { _verifyEIP1271Signature(bundleDetails.seller, digest, signedListing); } else if (bundleDetails.seller != ECDSA.recover(digest, signedListing.v, signedListing.r, signedListing.s)) { revert PaymentProcessor__SellerDidNotAuthorizeSale(); } } function _verifySignedItemListing( MatchedOrder memory saleDetails, SignatureECDSA memory signedListing) private { bytes32 digest = _hashTypedDataV4(keccak256( bytes.concat( abi.encode( SALE_APPROVAL_HASH, uint8(saleDetails.protocol), saleDetails.sellerAcceptedOffer, saleDetails.marketplace, saleDetails.marketplaceFeeNumerator, saleDetails.maxRoyaltyFeeNumerator, saleDetails.privateBuyer ), abi.encode( saleDetails.seller, saleDetails.tokenAddress, saleDetails.tokenId, saleDetails.amount, saleDetails.listingMinPrice, saleDetails.listingExpiration, saleDetails.listingNonce, _checkAndInvalidateNonce( saleDetails.marketplace, saleDetails.seller, saleDetails.listingNonce, false ), saleDetails.paymentCoin ) ) ) ); if(saleDetails.seller.code.length > 0) { _verifyEIP1271Signature(saleDetails.seller, digest, signedListing); } else if (saleDetails.seller != ECDSA.recover(digest, signedListing.v, signedListing.r, signedListing.s)) { revert PaymentProcessor__SellerDidNotAuthorizeSale(); } } function _checkAndInvalidateNonce( address marketplace, address account, uint256 nonce, bool wasCancellation) private returns (uint256) { mapping(uint256 => uint256) storage ptrInvalidatedSignatureBitmap = invalidatedSignatures[keccak256(abi.encodePacked(marketplace, account))]; unchecked { uint256 slot = nonce / 256; uint256 offset = nonce % 256; uint256 slotValue = ptrInvalidatedSignatureBitmap[slot]; if (((slotValue >> offset) & ONE) == ONE) { revert PaymentProcessor__SignatureAlreadyUsedOrRevoked(); } ptrInvalidatedSignatureBitmap[slot] = (slotValue | ONE << offset); } emit NonceInvalidated(nonce, account, marketplace, wasCancellation); return masterNonces[account]; } function _computeAndDistributeProceeds( ComputeAndDistributeProceedsArgs memory args, MatchedOrder[] memory saleDetailsBatch) private returns (bool[] memory unsuccessfulFills) { unsuccessfulFills = new bool[](saleDetailsBatch.length); PayoutsAccumulator memory accumulator = PayoutsAccumulator({ lastSeller: address(0), lastMarketplace: address(0), lastRoyaltyRecipient: address(0), accumulatedSellerProceeds: 0, accumulatedMarketplaceProceeds: 0, accumulatedRoyaltyProceeds: 0 }); for (uint256 i = 0; i < saleDetailsBatch.length;) { MatchedOrder memory saleDetails = saleDetailsBatch[i]; bool successfullyDispensedToken = args.funcDispenseToken( saleDetails.seller, saleDetails.buyer, saleDetails.tokenAddress, saleDetails.tokenId, saleDetails.amount); if (!successfullyDispensedToken) { if (address(args.paymentCoin) == address(0)) { revert PaymentProcessor__DispensingTokenWasUnsuccessful(); } unsuccessfulFills[i] = true; } else { SplitProceeds memory proceeds = _computePaymentSplits( saleDetails.offerPrice, saleDetails.tokenAddress, saleDetails.tokenId, saleDetails.marketplace, saleDetails.marketplaceFeeNumerator, saleDetails.maxRoyaltyFeeNumerator ); if (proceeds.royaltyRecipient != accumulator.lastRoyaltyRecipient) { if(accumulator.accumulatedRoyaltyProceeds > 0) { args.funcPayout(accumulator.lastRoyaltyRecipient, args.purchaser, args.paymentCoin, accumulator.accumulatedRoyaltyProceeds, args.pushPaymentGasLimit); } accumulator.lastRoyaltyRecipient = proceeds.royaltyRecipient; accumulator.accumulatedRoyaltyProceeds = 0; } if (saleDetails.marketplace != accumulator.lastMarketplace) { if(accumulator.accumulatedMarketplaceProceeds > 0) { args.funcPayout(accumulator.lastMarketplace, args.purchaser, args.paymentCoin, accumulator.accumulatedMarketplaceProceeds, args.pushPaymentGasLimit); } accumulator.lastMarketplace = saleDetails.marketplace; accumulator.accumulatedMarketplaceProceeds = 0; } if (saleDetails.seller != accumulator.lastSeller) { if(accumulator.accumulatedSellerProceeds > 0) { args.funcPayout(accumulator.lastSeller, args.purchaser, args.paymentCoin, accumulator.accumulatedSellerProceeds, args.pushPaymentGasLimit); } accumulator.lastSeller = saleDetails.seller; accumulator.accumulatedSellerProceeds = 0; } unchecked { accumulator.accumulatedRoyaltyProceeds += proceeds.royaltyProceeds; accumulator.accumulatedMarketplaceProceeds += proceeds.marketplaceProceeds; accumulator.accumulatedSellerProceeds += proceeds.sellerProceeds; } } unchecked { ++i; } } if(accumulator.accumulatedRoyaltyProceeds > 0) { args.funcPayout(accumulator.lastRoyaltyRecipient, args.purchaser, args.paymentCoin, accumulator.accumulatedRoyaltyProceeds, args.pushPaymentGasLimit); } if(accumulator.accumulatedMarketplaceProceeds > 0) { args.funcPayout(accumulator.lastMarketplace, args.purchaser, args.paymentCoin, accumulator.accumulatedMarketplaceProceeds, args.pushPaymentGasLimit); } if(accumulator.accumulatedSellerProceeds > 0) { args.funcPayout(accumulator.lastSeller, args.purchaser, args.paymentCoin, accumulator.accumulatedSellerProceeds, args.pushPaymentGasLimit); } return unsuccessfulFills; } function _pushProceeds(address to, uint256 proceeds, uint256 pushPaymentGasLimit_) private { bool success; assembly { // Transfer the ETH and store if it succeeded or not. success := call(pushPaymentGasLimit_, to, proceeds, 0, 0, 0, 0) } if (!success) { revert PaymentProcessor__FailedToTransferProceeds(); } } function _computePaymentSplits( uint256 salePrice, address tokenAddress, uint256 tokenId, address marketplaceFeeRecipient, uint256 marketplaceFeeNumerator, uint256 maxRoyaltyFeeNumerator) private view returns (SplitProceeds memory proceeds) { proceeds.sellerProceeds = salePrice; try IERC2981(tokenAddress).royaltyInfo( tokenId, salePrice) returns (address royaltyReceiver, uint256 royaltyAmount) { if (royaltyReceiver == address(0)) { royaltyAmount = 0; } if (royaltyAmount > 0) { if (royaltyAmount > (salePrice * maxRoyaltyFeeNumerator) / FEE_DENOMINATOR) { revert PaymentProcessor__OnchainRoyaltiesExceedMaximumApprovedRoyaltyFee(); } proceeds.royaltyRecipient = royaltyReceiver; proceeds.royaltyProceeds = royaltyAmount; unchecked { proceeds.sellerProceeds -= royaltyAmount; } } } catch (bytes memory) {} proceeds.marketplaceProceeds = marketplaceFeeRecipient != address(0) ? (salePrice * marketplaceFeeNumerator) / FEE_DENOMINATOR : 0; if (proceeds.marketplaceProceeds > 0) { unchecked { proceeds.sellerProceeds -= proceeds.marketplaceProceeds; } } } function _getTokenSecurityPolicy(address tokenAddress) private view returns (uint256, SecurityPolicy storage) { uint256 securityPolicyId = tokenSecurityPolicies[tokenAddress]; SecurityPolicy storage securityPolicy = securityPolicies[securityPolicyId]; return (securityPolicyId, securityPolicy); } function _requireCallerOwnsSecurityPolicy(uint256 securityPolicyId) private view { if(_msgSender() != securityPolicies[securityPolicyId].policyOwner) { revert PaymentProcessor__CallerDoesNotOwnSecurityPolicy(); } } function _getFloorAndCeilingPrices( address tokenAddress, uint256 tokenId) private view returns (uint256, uint256) { PricingBounds memory tokenLevelPricingBounds = tokenPricingBounds[tokenAddress][tokenId]; if (tokenLevelPricingBounds.isEnabled) { return (tokenLevelPricingBounds.floorPrice, tokenLevelPricingBounds.ceilingPrice); } else { PricingBounds memory collectionLevelPricingBounds = collectionPricingBounds[tokenAddress]; if (collectionLevelPricingBounds.isEnabled) { return (collectionLevelPricingBounds.floorPrice, collectionLevelPricingBounds.ceilingPrice); } } return (0, type(uint256).max); } function _verifySalePriceInRange( address tokenAddress, uint256 tokenId, uint256 amount, uint256 salePrice) private view { uint256 salePricePerUnit = salePrice / amount; (uint256 floorPrice, uint256 ceilingPrice) = _getFloorAndCeilingPrices(tokenAddress, tokenId); if(salePricePerUnit < floorPrice) { revert PaymentProcessor__SalePriceBelowMinimumFloor(); } if(salePricePerUnit > ceilingPrice) { revert PaymentProcessor__SalePriceAboveMaximumCeiling(); } } function _verifyEIP1271Signature( address signer, bytes32 hash, SignatureECDSA memory signatureComponents) private view { bool isValidSignatureNow; try IERC1271(signer).isValidSignature( hash, abi.encodePacked(signatureComponents.r, signatureComponents.s, signatureComponents.v)) returns (bytes4 magicValue) { isValidSignatureNow = magicValue == IERC1271.isValidSignature.selector; } catch {} if (!isValidSignatureNow) { revert PaymentProcessor__EIP1271SignatureInvalid(); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; interface IOwnable { function owner() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "./PaymentProcessorDataTypes.sol"; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @title IPaymentProcessor * @author Limit Break, Inc. * @notice Interface definition for payment processor contracts. */ interface IPaymentProcessor is IERC165 { /// @notice Emitted when a bundle of ERC-721 tokens is successfully purchased using `buyBundledListing` event BuyBundledListingERC721( address indexed marketplace, address indexed tokenAddress, address indexed paymentCoin, address buyer, address seller, bool[] unsuccessfulFills, uint256[] tokenIds, uint256[] salePrices); /// @notice Emitted when a bundle of ERC-1155 tokens is successfully purchased using `buyBundledListing` event BuyBundledListingERC1155( address indexed marketplace, address indexed tokenAddress, address indexed paymentCoin, address buyer, address seller, bool[] unsuccessfulFills, uint256[] tokenIds, uint256[] amounts, uint256[] salePrices); /// @notice Emitted for each token successfully purchased using either `buySingleLising` or `buyBatchOfListings` event BuySingleListing( address indexed marketplace, address indexed tokenAddress, address indexed paymentCoin, address buyer, address seller, uint256 tokenId, uint256 amount, uint256 salePrice); /// @notice Emitted when a security policy is either created or modified event CreatedOrUpdatedSecurityPolicy( uint256 indexed securityPolicyId, bool enforceExchangeWhitelist, bool enforcePaymentMethodWhitelist, bool enforcePricingConstraints, bool disablePrivateListings, bool disableDelegatedPurchases, bool disableEIP1271Signatures, bool disableExchangeWhitelistEOABypass, uint32 pushPaymentGasLimit, string policyName); /// @notice Emitted when an address is added to the exchange whitelist for a security policy event ExchangeAddedToWhitelist(uint256 indexed securityPolicyId, address indexed exchange); /// @notice Emitted when an address is removed from the exchange whitelist for a security policy event ExchangeRemovedFromWhitelist(uint256 indexed securityPolicyId, address indexed exchange); /// @notice Emitted when a user revokes all of their existing listings or offers that share the master nonce. event MasterNonceInvalidated(uint256 indexed nonce, address indexed account); /// @notice Emitted when a user revokes a single listing or offer nonce for a specific marketplace. event NonceInvalidated( uint256 indexed nonce, address indexed account, address indexed marketplace, bool wasCancellation); /// @notice Emitted when a coin is added to the approved coins mapping for a security policy event PaymentMethodAddedToWhitelist(uint256 indexed securityPolicyId, address indexed coin); /// @notice Emitted when a coin is removed from the approved coins mapping for a security policy event PaymentMethodRemovedFromWhitelist(uint256 indexed securityPolicyId, address indexed coin); /// @notice Emitted when the ownership of a security policy is transferred to a new account event SecurityPolicyOwnershipTransferred(address indexed previousOwner, address indexed newOwner); /// @notice Emitted when a collection of ERC-721 tokens is successfully swept using `sweepCollection` event SweepCollectionERC721( address indexed marketplace, address indexed tokenAddress, address indexed paymentCoin, address buyer, bool[] unsuccessfulFills, address[] sellers, uint256[] tokenIds, uint256[] salePrices); /// @notice Emitted when a collection of ERC-1155 tokens is successfully swept using `sweepCollection` event SweepCollectionERC1155( address indexed marketplace, address indexed tokenAddress, address indexed paymentCoin, address buyer, bool[] unsuccessfulFills, address[] sellers, uint256[] tokenIds, uint256[] amounts, uint256[] salePrices); /// @notice Emitted whenever the designated security policy id changes for a collection. event UpdatedCollectionSecurityPolicy(address indexed tokenAddress, uint256 indexed securityPolicyId); /// @notice Emitted whenever the supported ERC-20 payment is set for price-constrained collections. event UpdatedCollectionPaymentCoin(address indexed tokenAddress, address indexed paymentCoin); /// @notice Emitted whenever pricing bounds change at a collection level for price-constrained collections. event UpdatedCollectionLevelPricingBoundaries( address indexed tokenAddress, uint256 floorPrice, uint256 ceilingPrice); /// @notice Emitted whenever pricing bounds change at a token level for price-constrained collections. event UpdatedTokenLevelPricingBoundaries( address indexed tokenAddress, uint256 indexed tokenId, uint256 floorPrice, uint256 ceilingPrice); function createSecurityPolicy( bool enforceExchangeWhitelist, bool enforcePaymentMethodWhitelist, bool enforcePricingConstraints, bool disablePrivateListings, bool disableDelegatedPurchases, bool disableEIP1271Signatures, bool disableExchangeWhitelistEOABypass, uint32 pushPaymentGasLimit, string calldata registryName) external returns (uint256); function updateSecurityPolicy( uint256 securityPolicyId, bool enforceExchangeWhitelist, bool enforcePaymentMethodWhitelist, bool enforcePricingConstraints, bool disablePrivateListings, bool disableDelegatedPurchases, bool disableEIP1271Signatures, bool disableExchangeWhitelistEOABypass, uint32 pushPaymentGasLimit, string calldata registryName) external; function transferSecurityPolicyOwnership(uint256 securityPolicyId, address newOwner) external; function renounceSecurityPolicyOwnership(uint256 securityPolicyId) external; function setCollectionSecurityPolicy(address tokenAddress, uint256 securityPolicyId) external; function setCollectionPaymentCoin(address tokenAddress, address coin) external; function setCollectionPricingBounds(address tokenAddress, PricingBounds calldata pricingBounds) external; function setTokenPricingBounds( address tokenAddress, uint256[] calldata tokenIds, PricingBounds[] calldata pricingBounds) external; function whitelistExchange(uint256 securityPolicyId, address account) external; function unwhitelistExchange(uint256 securityPolicyId, address account) external; function whitelistPaymentMethod(uint256 securityPolicyId, address coin) external; function unwhitelistPaymentMethod(uint256 securityPolicyId, address coin) external; function revokeMasterNonce() external; function revokeSingleNonce(address marketplace, uint256 nonce) external; function buySingleListing( MatchedOrder memory saleDetails, SignatureECDSA memory signedListing, SignatureECDSA memory signedOffer ) external payable; function buyBatchOfListings( MatchedOrder[] calldata saleDetailsArray, SignatureECDSA[] calldata signedListings, SignatureECDSA[] calldata signedOffers ) external payable; function buyBundledListing( SignatureECDSA memory signedListing, SignatureECDSA memory signedOffer, MatchedOrderBundleExtended memory bundleDetails, BundledItem[] calldata bundleItems) external payable; function sweepCollection( SignatureECDSA memory signedOffer, MatchedOrderBundleBase memory bundleDetails, BundledItem[] calldata bundleItems, SignatureECDSA[] calldata signedListings) external payable; function getDomainSeparator() external view returns (bytes32); function getSecurityPolicy(uint256 securityPolicyId) external view returns (SecurityPolicy memory); function isWhitelisted(uint256 securityPolicyId, address account) external view returns (bool); function isPaymentMethodApproved(uint256 securityPolicyId, address coin) external view returns (bool); function getTokenSecurityPolicyId(address collectionAddress) external view returns (uint256); function isCollectionPricingImmutable(address tokenAddress) external view returns (bool); function isTokenPricingImmutable(address tokenAddress, uint256 tokenId) external view returns (bool); function getFloorPrice(address tokenAddress, uint256 tokenId) external view returns (uint256); function getCeilingPrice(address tokenAddress, uint256 tokenId) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981 is IERC165 { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a // good first aproximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1; uint256 x = a; if (x >> 128 > 0) { x >>= 128; result <<= 64; } if (x >> 64 > 0) { x >>= 64; result <<= 32; } if (x >> 32 > 0) { x >>= 32; result <<= 16; } if (x >> 16 > 0) { x >>= 16; result <<= 8; } if (x >> 8 > 0) { x >>= 8; result <<= 4; } if (x >> 4 > 0) { x >>= 4; result <<= 2; } if (x >> 2 > 0) { result <<= 1; } // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { uint256 result = sqrt(a); if (rounding == Rounding.Up && result * result < a) { result += 1; } return result; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.9; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; enum TokenProtocols { ERC721, ERC1155 } /** * @dev The `v`, `r`, and `s` components of an ECDSA signature. For more information * [refer to this article](https://medium.com/mycrypto/the-magic-of-digital-signatures-on-ethereum-98fe184dc9c7). */ struct SignatureECDSA { uint8 v; bytes32 r; bytes32 s; } /** * @dev This struct is used as input to `buySingleListing` and `buyBatchOfListings` calls after an exchange matches * @dev a buyer and seller. * * @dev **sellerAcceptedOffer**: Denotes that the transaction was initiated by the seller account by accepting an offer. * @dev When true, ETH/native payments are not accepted, and only ERC-20 payment methods can be used. * @dev **collectionLevelOffer**: Denotes that the offer that was accepted was at the collection level. When `true`, * @dev the Buyer should be prompted to sign the the collection offer approval stucture. When false, the Buyer should * @dev prompted to sign the offer approval structure. * @dev **protocol**: 0 for ERC-721 or 1 for ERC-1155. See `TokenProtocols`. * @dev **paymentCoin**: `address(0)` denotes native currency sale. Otherwise ERC-20 payment coin address. * @dev **tokenAddress**: The smart contract address of the ERC-721 or ERC-1155 token being sold. * @dev **seller**: The seller/current owner of the token. * @dev **privateBuyer**: `address(0)` denotes a listing available to any buyer. Otherwise, this denotes the privately * @dev designated buyer. * @dev **buyer**: The buyer/new owner of the token. * @dev **delegatedPurchaser**: Allows a buyer to delegate an address to buy a token on their behalf. This would allow * @dev a warm burner wallet to purchase tokens and allow them to be received in a cold wallet, for example. * @dev **marketplace**: The address designated to receive marketplace fees, if applicable. * @dev **marketplaceFeeNumerator**: Marketplace fee percentage. Denominator is 10,000. * @dev 0.5% fee numerator is 50, 1% fee numerator is 100, 10% fee numerator is 1,000 and so on. * @dev **maxRoyaltyFeeNumerator**: Maximum approved royalty fee percentage. Denominator is 10,000. * @dev 0.5% fee numerator is 50, 1% fee numerator is 100, 10% fee numerator is 1,000 and so on. * @dev Marketplaces are responsible to query EIP-2981 royalty info from the NFT contract when presenting this * @dev for signature. * @dev **listingNonce**: The nonce the seller signed in the listing. * @dev **offerNonce**: The nonce the buyer signed in the offer. * @dev **listingMinPrice**: The minimum price the seller signed off on, in wei. Buyer can buy above, * @dev but not below the seller-approved minimum price. * @dev **offerPrice**: The sale price of the matched order, in wei. Buyer signs off on the final offer price. * @dev **listingExpiration**: The timestamp at which the listing expires. * @dev **offerExpiration**: The timestamp at which the offer expires. * @dev **tokenId**: The id of the token being sold. For ERC-721 tokens, this is the specific NFT token id. * @dev For ERC-1155 tokens, this denotes the token type id. * @dev **amount**: The number of tokens being sold. For ERC-721 tokens, this must always be `1`. * @dev For ERC-1155 tokens where balances are transferred, this must be greater than or equal to `1`. */ struct MatchedOrder { bool sellerAcceptedOffer; bool collectionLevelOffer; TokenProtocols protocol; address paymentCoin; address tokenAddress; address seller; address privateBuyer; address buyer; address delegatedPurchaser; address marketplace; uint256 marketplaceFeeNumerator; uint256 maxRoyaltyFeeNumerator; uint256 listingNonce; uint256 offerNonce; uint256 listingMinPrice; uint256 offerPrice; uint256 listingExpiration; uint256 offerExpiration; uint256 tokenId; uint256 amount; } /** * @dev This struct is used as input to `buyBundledListing` calls after an exchange matches a buyer and seller. * @dev Wraps `MatchedOrderBundleBase` and adds seller, listing nonce and listing expiration. * * @dev **bundleBase**: Includes all fields from `MatchedOrderBundleBase`. * @dev **seller**: The seller/current owner of all the tokens in a bundled listing. * @dev **listingNonce**: The nonce the seller signed in the listing. Only one nonce is required approving the sale * @dev of multiple tokens from one collection. * @dev **listingExpiration**: The timestamp at which the listing expires. */ struct MatchedOrderBundleExtended { MatchedOrderBundleBase bundleBase; address seller; uint256 listingNonce; uint256 listingExpiration; } /** * @dev This struct is used as input to `sweepCollection` calls after an exchange matches multiple individual listings * @dev with a single buyer. * * @dev **protocol**: 0 for ERC-721 or 1 for ERC-1155. See `TokenProtocols`. * @dev **paymentCoin**: `address(0)` denotes native currency sale. Otherwise ERC-20 payment coin address. * @dev **tokenAddress**: The smart contract address of the ERC-721 or ERC-1155 token being sold. * @dev **privateBuyer**: `address(0)` denotes a listing available to any buyer. Otherwise, this denotes the privately * @dev designated buyer. * @dev **buyer**: The buyer/new owner of the token. * @dev **delegatedPurchaser**: Allows a buyer to delegate an address to buy a token on their behalf. This would allow * @dev a warm burner wallet to purchase tokens and allow them to be received in a cold wallet, for example. * @dev **marketplace**: The address designated to receive marketplace fees, if applicable. * @dev **marketplaceFeeNumerator**: Marketplace fee percentage. Denominator is 10,000. * @dev 0.5% fee numerator is 50, 1% fee numerator is 100, 10% fee numerator is 1,000 and so on. * @dev **offerNonce**: The nonce the buyer signed in the offer. Only one nonce is required approving the purchase * @dev of multiple tokens from one collection. * @dev **offerPrice**: The sale price of the entire order, in wei. Buyer signs off on the final offer price. * @dev **offerExpiration**: The timestamp at which the offer expires. */ struct MatchedOrderBundleBase { TokenProtocols protocol; address paymentCoin; address tokenAddress; address privateBuyer; address buyer; address delegatedPurchaser; address marketplace; uint256 marketplaceFeeNumerator; uint256 offerNonce; uint256 offerPrice; uint256 offerExpiration; } /** * @dev This struct is used as input to `sweepCollection` and `buyBundledListing` calls. * @dev These fields are required per individual item listed. * * @dev **tokenId**: The id of the token being sold. For ERC-721 tokens, this is the specific NFT token id. * @dev For ERC-1155 tokens, this denotes the token type id. * @dev **amount**: The number of tokens being sold. For ERC-721 tokens, this must always be `1`. * @dev For ERC-1155 tokens where balances are transferred, this must be greater than or equal to `1`. * @dev **maxRoyaltyFeeNumerator**: Maximum approved royalty fee percentage. Denominator is 10,000. * @dev 0.5% fee numerator is 50, 1% fee numerator is 100, 10% fee numerator is 1,000 and so on. * @dev Marketplaces are responsible to query EIP-2981 royalty info from the NFT contract when presenting this * @dev for signature. * @dev **itemPrice**: The exact price the seller signed off on for an individual item, in wei. * @dev Purchase price for the item must be exactly the listing item price. * @dev **listingNonce**: The nonce the seller signed in the listing for an individual item. This should be set * @dev for collection sweep transactions, but it should be zero for bundled listings, as the listing nonce is global * @dev in that case. * @dev **listingExpiration**: The timestamp at which an individual listing expires. This should be set * @dev for collection sweep transactions, but it should be zero for bundled listings, as the listing nonce is global * @dev in that case. * @dev **seller**: The seller/current owner of the token. This should be set * @dev for collection sweep transactions, but it should be zero for bundled listings, as the listing nonce is global * @dev in that case. */ struct BundledItem { uint256 tokenId; uint256 amount; uint256 maxRoyaltyFeeNumerator; uint256 itemPrice; uint256 listingNonce; uint256 listingExpiration; address seller; } /** * @dev This struct is used to define the marketplace behavior and constraints, giving creators flexibility to define * marketplace behavior(s). * * @dev **enforceExchangeWhitelist**: Requires `buy` calls from smart contracts to be whitelisted. * @dev **enforcePaymentMethodWhitelist**: Requires ERC-20 payment coins for `buy` calls to be whitelisted as an * @dev approved payment method. * @dev **enforcePricingConstraints**: Allows the creator to specify exactly one approved payment method, a minimum * @dev floor price and a maximum ceiling price. When true, this value supercedes `enforcePaymentMethodWhitelist`. * @dev **disablePrivateListings**: Disables private sales. * @dev **disableDelegatedPurchases**: Disables purchases by delegated accounts on behalf of buyers. * @dev **disableEIP1271Signatures**: Disables sales and purchases using multi-sig wallets that implement EIP-1271. * @dev Enforces that buyers and sellers are EOAs. * @dev **disableExchangeWhitelistEOABypass**: Has no effect when `enforceExchangeWhitelist` is false. * @dev When exchange whitelist is enforced, this disables calls from EOAs, effectively requiring purchases to be * @dev composed by whitelisted 3rd party exchange contracts. * @dev **pushPaymentGasLimit**: This is the amount of gas to forward when pushing native payments. * @dev At the time this contract was written, 2300 gas is the recommended amount, but should costs of EVM opcodes * @dev change in the future, this field can be used to increase or decrease the amount of forwarded gas. Care should * @dev be taken to ensure not enough gas is forwarded to result in possible re-entrancy. * @dev **policyOwner**: The account that has access to modify a security policy or update the exchange whitelist * @dev or approved payment list for the security policy. */ struct SecurityPolicy { bool enforceExchangeWhitelist; bool enforcePaymentMethodWhitelist; bool enforcePricingConstraints; bool disablePrivateListings; bool disableDelegatedPurchases; bool disableEIP1271Signatures; bool disableExchangeWhitelistEOABypass; uint32 pushPaymentGasLimit; address policyOwner; } /** * @dev This struct is used to define pricing constraints for a collection or individual token. * * @dev **isEnabled**: When true, this indicates that pricing constraints are set for the collection or token. * @dev **isImmutable**: When true, this indicates that pricing constraints are immutable and cannot be changed. * @dev **floorPrice**: The minimum price for a token or collection. This is only enforced when * @dev `enforcePricingConstraints` is `true`. * @dev **ceilingPrice**: The maximum price for a token or collection. This is only enforced when * @dev `enforcePricingConstraints` is `true`. */ struct PricingBounds { bool isEnabled; bool isImmutable; uint256 floorPrice; uint256 ceilingPrice; } /** * @dev Internal contract use only - this is not a public-facing struct */ struct SplitProceeds { address royaltyRecipient; uint256 royaltyProceeds; uint256 marketplaceProceeds; uint256 sellerProceeds; } /** * @dev Internal contract use only - this is not a public-facing struct */ struct Accumulator { uint256[] tokenIds; uint256[] amounts; uint256[] salePrices; uint256[] maxRoyaltyFeeNumerators; address[] sellers; uint256 sumListingPrices; } /** * @dev Internal contract use only - this is not a public-facing struct */ struct AccumulatorHashes { bytes32 tokenIdsKeccakHash; bytes32 amountsKeccakHash; bytes32 maxRoyaltyFeeNumeratorsKeccakHash; bytes32 itemPricesKeccakHash; } /** * @dev Internal contract use only - this is not a public-facing struct */ struct PayoutsAccumulator { address lastSeller; address lastMarketplace; address lastRoyaltyRecipient; uint256 accumulatedSellerProceeds; uint256 accumulatedMarketplaceProceeds; uint256 accumulatedRoyaltyProceeds; } /** * @dev Internal contract use only - this is not a public-facing struct */ struct ComputeAndDistributeProceedsArgs { uint256 pushPaymentGasLimit; address purchaser; IERC20 paymentCoin; function(address,address,IERC20,uint256,uint256) funcPayout; function(address,address,address,uint256,uint256) returns (bool) funcDispenseToken; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol 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); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
{ "remappings": [ "@ensdomains/=node_modules/@ensdomains/", "@limitbreak/=node_modules/@limitbreak/", "@openzeppelin/=node_modules/@openzeppelin/", "ds-test/=lib/forge-std/lib/ds-test/src/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/", "@rari-capital/solmate/=node_modules/@rari-capital/solmate/" ], "optimizer": { "enabled": true, "runs": 600 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"defaultContractOwner_","type":"address"},{"internalType":"uint32","name":"defaultPushPaymentGasLimit_","type":"uint32"},{"internalType":"address[]","name":"defaultPaymentMethods","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"PaymentProcessor__AddressCannotBeZero","type":"error"},{"inputs":[],"name":"PaymentProcessor__AmountForERC1155SalesGreaterThanZero","type":"error"},{"inputs":[],"name":"PaymentProcessor__AmountForERC721SalesMustEqualOne","type":"error"},{"inputs":[],"name":"PaymentProcessor__BundledOfferPriceMustEqualSumOfAllListingPrices","type":"error"},{"inputs":[],"name":"PaymentProcessor__BuyerDidNotAuthorizePurchase","type":"error"},{"inputs":[],"name":"PaymentProcessor__BuyerMustBeDesignatedPrivateBuyer","type":"error"},{"inputs":[],"name":"PaymentProcessor__CallerDoesNotOwnSecurityPolicy","type":"error"},{"inputs":[],"name":"PaymentProcessor__CallerIsNotTheDelegatedPurchaser","type":"error"},{"inputs":[],"name":"PaymentProcessor__CallerIsNotWhitelistedMarketplace","type":"error"},{"inputs":[],"name":"PaymentProcessor__CallerMustHaveElevatedPermissionsForSpecifiedNFT","type":"error"},{"inputs":[],"name":"PaymentProcessor__CannotIncludeNativeFundsWhenPaymentMethodIsAnERC20Coin","type":"error"},{"inputs":[],"name":"PaymentProcessor__CeilingPriceMustBeGreaterThanFloorPrice","type":"error"},{"inputs":[],"name":"PaymentProcessor__CoinDoesNotImplementDecimalsAndLikelyIsNotAnERC20Token","type":"error"},{"inputs":[],"name":"PaymentProcessor__CoinIsApproved","type":"error"},{"inputs":[],"name":"PaymentProcessor__CoinIsNotApproved","type":"error"},{"inputs":[],"name":"PaymentProcessor__CollectionLevelOrItemLevelOffersCanOnlyBeMadeUsingERC20PaymentMethods","type":"error"},{"inputs":[],"name":"PaymentProcessor__DispensingTokenWasUnsuccessful","type":"error"},{"inputs":[],"name":"PaymentProcessor__EIP1271SignatureInvalid","type":"error"},{"inputs":[],"name":"PaymentProcessor__EIP1271SignaturesAreDisabled","type":"error"},{"inputs":[],"name":"PaymentProcessor__ExchangeIsNotWhitelisted","type":"error"},{"inputs":[],"name":"PaymentProcessor__ExchangeIsWhitelisted","type":"error"},{"inputs":[],"name":"PaymentProcessor__FailedToTransferProceeds","type":"error"},{"inputs":[],"name":"PaymentProcessor__InputArrayLengthCannotBeZero","type":"error"},{"inputs":[],"name":"PaymentProcessor__InputArrayLengthMismatch","type":"error"},{"inputs":[],"name":"PaymentProcessor__MarketplaceAndRoyaltyFeesWillExceedSalePrice","type":"error"},{"inputs":[],"name":"PaymentProcessor__NativeCurrencyIsNotAnApprovedPaymentMethod","type":"error"},{"inputs":[],"name":"PaymentProcessor__OfferHasExpired","type":"error"},{"inputs":[],"name":"PaymentProcessor__OfferPriceMustEqualSalePrice","type":"error"},{"inputs":[],"name":"PaymentProcessor__OnchainRoyaltiesExceedMaximumApprovedRoyaltyFee","type":"error"},{"inputs":[],"name":"PaymentProcessor__OverpaidNativeFunds","type":"error"},{"inputs":[],"name":"PaymentProcessor__PaymentCoinIsNotAnApprovedPaymentMethod","type":"error"},{"inputs":[],"name":"PaymentProcessor__PricingBoundsAreImmutable","type":"error"},{"inputs":[],"name":"PaymentProcessor__RanOutOfNativeFunds","type":"error"},{"inputs":[],"name":"PaymentProcessor__SaleHasExpired","type":"error"},{"inputs":[],"name":"PaymentProcessor__SalePriceAboveMaximumCeiling","type":"error"},{"inputs":[],"name":"PaymentProcessor__SalePriceBelowMinimumFloor","type":"error"},{"inputs":[],"name":"PaymentProcessor__SalePriceBelowSellerApprovedMinimum","type":"error"},{"inputs":[],"name":"PaymentProcessor__SecurityPolicyDoesNotExist","type":"error"},{"inputs":[],"name":"PaymentProcessor__SecurityPolicyOwnershipCannotBeTransferredToZeroAddress","type":"error"},{"inputs":[],"name":"PaymentProcessor__SellerDidNotAuthorizeSale","type":"error"},{"inputs":[],"name":"PaymentProcessor__SignatureAlreadyUsedOrRevoked","type":"error"},{"inputs":[],"name":"PaymentProcessor__TokenSecurityPolicyDoesNotAllowDelegatedPurchases","type":"error"},{"inputs":[],"name":"PaymentProcessor__TokenSecurityPolicyDoesNotAllowEOACallers","type":"error"},{"inputs":[],"name":"PaymentProcessor__TokenSecurityPolicyDoesNotAllowPrivateListings","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"marketplace","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"paymentCoin","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"bool[]","name":"unsuccessfulFills","type":"bool[]"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"salePrices","type":"uint256[]"}],"name":"BuyBundledListingERC1155","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"marketplace","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"paymentCoin","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"bool[]","name":"unsuccessfulFills","type":"bool[]"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"salePrices","type":"uint256[]"}],"name":"BuyBundledListingERC721","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"marketplace","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"paymentCoin","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"BuySingleListing","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"enforceExchangeWhitelist","type":"bool"},{"indexed":false,"internalType":"bool","name":"enforcePaymentMethodWhitelist","type":"bool"},{"indexed":false,"internalType":"bool","name":"enforcePricingConstraints","type":"bool"},{"indexed":false,"internalType":"bool","name":"disablePrivateListings","type":"bool"},{"indexed":false,"internalType":"bool","name":"disableDelegatedPurchases","type":"bool"},{"indexed":false,"internalType":"bool","name":"disableEIP1271Signatures","type":"bool"},{"indexed":false,"internalType":"bool","name":"disableExchangeWhitelistEOABypass","type":"bool"},{"indexed":false,"internalType":"uint32","name":"pushPaymentGasLimit","type":"uint32"},{"indexed":false,"internalType":"string","name":"policyName","type":"string"}],"name":"CreatedOrUpdatedSecurityPolicy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"indexed":true,"internalType":"address","name":"exchange","type":"address"}],"name":"ExchangeAddedToWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"indexed":true,"internalType":"address","name":"exchange","type":"address"}],"name":"ExchangeRemovedFromWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"MasterNonceInvalidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nonce","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"marketplace","type":"address"},{"indexed":false,"internalType":"bool","name":"wasCancellation","type":"bool"}],"name":"NonceInvalidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"indexed":true,"internalType":"address","name":"coin","type":"address"}],"name":"PaymentMethodAddedToWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"indexed":true,"internalType":"address","name":"coin","type":"address"}],"name":"PaymentMethodRemovedFromWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"SecurityPolicyOwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"marketplace","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"paymentCoin","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"bool[]","name":"unsuccessfulFills","type":"bool[]"},{"indexed":false,"internalType":"address[]","name":"sellers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"salePrices","type":"uint256[]"}],"name":"SweepCollectionERC1155","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"marketplace","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"paymentCoin","type":"address"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"bool[]","name":"unsuccessfulFills","type":"bool[]"},{"indexed":false,"internalType":"address[]","name":"sellers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"salePrices","type":"uint256[]"}],"name":"SweepCollectionERC721","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"floorPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ceilingPrice","type":"uint256"}],"name":"UpdatedCollectionLevelPricingBoundaries","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"paymentCoin","type":"address"}],"name":"UpdatedCollectionPaymentCoin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"securityPolicyId","type":"uint256"}],"name":"UpdatedCollectionSecurityPolicy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"floorPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ceilingPrice","type":"uint256"}],"name":"UpdatedTokenLevelPricingBoundaries","type":"event"},{"inputs":[],"name":"BUNDLED_OFFER_APPROVAL_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BUNDLED_SALE_APPROVAL_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COLLECTION_OFFER_APPROVAL_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_SECURITY_POLICY_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OFFER_APPROVAL_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SALE_APPROVAL_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"sellerAcceptedOffer","type":"bool"},{"internalType":"bool","name":"collectionLevelOffer","type":"bool"},{"internalType":"enum TokenProtocols","name":"protocol","type":"uint8"},{"internalType":"address","name":"paymentCoin","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"privateBuyer","type":"address"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"address","name":"delegatedPurchaser","type":"address"},{"internalType":"address","name":"marketplace","type":"address"},{"internalType":"uint256","name":"marketplaceFeeNumerator","type":"uint256"},{"internalType":"uint256","name":"maxRoyaltyFeeNumerator","type":"uint256"},{"internalType":"uint256","name":"listingNonce","type":"uint256"},{"internalType":"uint256","name":"offerNonce","type":"uint256"},{"internalType":"uint256","name":"listingMinPrice","type":"uint256"},{"internalType":"uint256","name":"offerPrice","type":"uint256"},{"internalType":"uint256","name":"listingExpiration","type":"uint256"},{"internalType":"uint256","name":"offerExpiration","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct MatchedOrder[]","name":"saleDetailsArray","type":"tuple[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureECDSA[]","name":"signedListings","type":"tuple[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureECDSA[]","name":"signedOffers","type":"tuple[]"}],"name":"buyBatchOfListings","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureECDSA","name":"signedListing","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureECDSA","name":"signedOffer","type":"tuple"},{"components":[{"components":[{"internalType":"enum TokenProtocols","name":"protocol","type":"uint8"},{"internalType":"address","name":"paymentCoin","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"privateBuyer","type":"address"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"address","name":"delegatedPurchaser","type":"address"},{"internalType":"address","name":"marketplace","type":"address"},{"internalType":"uint256","name":"marketplaceFeeNumerator","type":"uint256"},{"internalType":"uint256","name":"offerNonce","type":"uint256"},{"internalType":"uint256","name":"offerPrice","type":"uint256"},{"internalType":"uint256","name":"offerExpiration","type":"uint256"}],"internalType":"struct MatchedOrderBundleBase","name":"bundleBase","type":"tuple"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"uint256","name":"listingNonce","type":"uint256"},{"internalType":"uint256","name":"listingExpiration","type":"uint256"}],"internalType":"struct MatchedOrderBundleExtended","name":"bundleDetails","type":"tuple"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"maxRoyaltyFeeNumerator","type":"uint256"},{"internalType":"uint256","name":"itemPrice","type":"uint256"},{"internalType":"uint256","name":"listingNonce","type":"uint256"},{"internalType":"uint256","name":"listingExpiration","type":"uint256"},{"internalType":"address","name":"seller","type":"address"}],"internalType":"struct BundledItem[]","name":"bundleItems","type":"tuple[]"}],"name":"buyBundledListing","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"sellerAcceptedOffer","type":"bool"},{"internalType":"bool","name":"collectionLevelOffer","type":"bool"},{"internalType":"enum TokenProtocols","name":"protocol","type":"uint8"},{"internalType":"address","name":"paymentCoin","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"privateBuyer","type":"address"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"address","name":"delegatedPurchaser","type":"address"},{"internalType":"address","name":"marketplace","type":"address"},{"internalType":"uint256","name":"marketplaceFeeNumerator","type":"uint256"},{"internalType":"uint256","name":"maxRoyaltyFeeNumerator","type":"uint256"},{"internalType":"uint256","name":"listingNonce","type":"uint256"},{"internalType":"uint256","name":"offerNonce","type":"uint256"},{"internalType":"uint256","name":"listingMinPrice","type":"uint256"},{"internalType":"uint256","name":"offerPrice","type":"uint256"},{"internalType":"uint256","name":"listingExpiration","type":"uint256"},{"internalType":"uint256","name":"offerExpiration","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct MatchedOrder","name":"saleDetails","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureECDSA","name":"signedListing","type":"tuple"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureECDSA","name":"signedOffer","type":"tuple"}],"name":"buySingleListing","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collectionPaymentCoins","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"enforceExchangeWhitelist","type":"bool"},{"internalType":"bool","name":"enforcePaymentMethodWhitelist","type":"bool"},{"internalType":"bool","name":"enforcePricingConstraints","type":"bool"},{"internalType":"bool","name":"disablePrivateListings","type":"bool"},{"internalType":"bool","name":"disableDelegatedPurchases","type":"bool"},{"internalType":"bool","name":"disableEIP1271Signatures","type":"bool"},{"internalType":"bool","name":"disableExchangeWhitelistEOABypass","type":"bool"},{"internalType":"uint32","name":"pushPaymentGasLimit","type":"uint32"},{"internalType":"string","name":"registryName","type":"string"}],"name":"createSecurityPolicy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getCeilingPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getFloorPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"}],"name":"getSecurityPolicy","outputs":[{"components":[{"internalType":"bool","name":"enforceExchangeWhitelist","type":"bool"},{"internalType":"bool","name":"enforcePaymentMethodWhitelist","type":"bool"},{"internalType":"bool","name":"enforcePricingConstraints","type":"bool"},{"internalType":"bool","name":"disablePrivateListings","type":"bool"},{"internalType":"bool","name":"disableDelegatedPurchases","type":"bool"},{"internalType":"bool","name":"disableEIP1271Signatures","type":"bool"},{"internalType":"bool","name":"disableExchangeWhitelistEOABypass","type":"bool"},{"internalType":"uint32","name":"pushPaymentGasLimit","type":"uint32"},{"internalType":"address","name":"policyOwner","type":"address"}],"internalType":"struct SecurityPolicy","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collectionAddress","type":"address"}],"name":"getTokenSecurityPolicyId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"isCollectionPricingImmutable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"internalType":"address","name":"coin","type":"address"}],"name":"isPaymentMethodApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"isTokenPricingImmutable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"masterNonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"}],"name":"renounceSecurityPolicyOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revokeMasterNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"marketplace","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"revokeSingleNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"coin","type":"address"}],"name":"setCollectionPaymentCoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"bool","name":"isImmutable","type":"bool"},{"internalType":"uint256","name":"floorPrice","type":"uint256"},{"internalType":"uint256","name":"ceilingPrice","type":"uint256"}],"internalType":"struct PricingBounds","name":"pricingBounds","type":"tuple"}],"name":"setCollectionPricingBounds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"securityPolicyId","type":"uint256"}],"name":"setCollectionSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"components":[{"internalType":"bool","name":"isEnabled","type":"bool"},{"internalType":"bool","name":"isImmutable","type":"bool"},{"internalType":"uint256","name":"floorPrice","type":"uint256"},{"internalType":"uint256","name":"ceilingPrice","type":"uint256"}],"internalType":"struct PricingBounds[]","name":"pricingBounds","type":"tuple[]"}],"name":"setTokenPricingBounds","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":[{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureECDSA","name":"signedOffer","type":"tuple"},{"components":[{"internalType":"enum TokenProtocols","name":"protocol","type":"uint8"},{"internalType":"address","name":"paymentCoin","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"privateBuyer","type":"address"},{"internalType":"address","name":"buyer","type":"address"},{"internalType":"address","name":"delegatedPurchaser","type":"address"},{"internalType":"address","name":"marketplace","type":"address"},{"internalType":"uint256","name":"marketplaceFeeNumerator","type":"uint256"},{"internalType":"uint256","name":"offerNonce","type":"uint256"},{"internalType":"uint256","name":"offerPrice","type":"uint256"},{"internalType":"uint256","name":"offerExpiration","type":"uint256"}],"internalType":"struct MatchedOrderBundleBase","name":"bundleDetails","type":"tuple"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"maxRoyaltyFeeNumerator","type":"uint256"},{"internalType":"uint256","name":"itemPrice","type":"uint256"},{"internalType":"uint256","name":"listingNonce","type":"uint256"},{"internalType":"uint256","name":"listingExpiration","type":"uint256"},{"internalType":"address","name":"seller","type":"address"}],"internalType":"struct BundledItem[]","name":"bundleItems","type":"tuple[]"},{"components":[{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct SignatureECDSA[]","name":"signedListings","type":"tuple[]"}],"name":"sweepCollection","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferSecurityPolicyOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"unwhitelistExchange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"internalType":"address","name":"coin","type":"address"}],"name":"unwhitelistPaymentMethod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"internalType":"bool","name":"enforceExchangeWhitelist","type":"bool"},{"internalType":"bool","name":"enforcePaymentMethodWhitelist","type":"bool"},{"internalType":"bool","name":"enforcePricingConstraints","type":"bool"},{"internalType":"bool","name":"disablePrivateListings","type":"bool"},{"internalType":"bool","name":"disableDelegatedPurchases","type":"bool"},{"internalType":"bool","name":"disableEIP1271Signatures","type":"bool"},{"internalType":"bool","name":"disableExchangeWhitelistEOABypass","type":"bool"},{"internalType":"uint32","name":"pushPaymentGasLimit","type":"uint32"},{"internalType":"string","name":"registryName","type":"string"}],"name":"updateSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"whitelistExchange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"securityPolicyId","type":"uint256"},{"internalType":"address","name":"coin","type":"address"}],"name":"whitelistPaymentMethod","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101406040523480156200001257600080fd5b5060405162006621380380620066218339810160408190526200003591620004ba565b604080518082018252601081526f2830bcb6b2b73a283937b1b2b9b9b7b960811b6020808301918252835180850190945260018452603160f81b908401528151902060e08190527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66101008190524660a0529192917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6200011b8184846040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6080523060c05261012052506200013e9250620001389150503390565b62000437565b6000805460ff60a01b19168155604080516101208101825282815260016020808301828152838501868152606085018781526080860188815260a0870189815260c088018a815263ffffffff808e1660e08b019081526101008b81018e81528e80526005909a529a517f05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc805499519851975196519551945192519a516001600160a01b03166b01000000000000000000000002600160581b600160f81b03199b9094166701000000000000000263ffffffff60381b199315156601000000000000029390931664ffffffffff60301b19951515650100000000000260ff60281b19971515640100000000029790971661ffff60201b1998151563010000000263ff000000199a151562010000029a909a1663ffff0000199b1515909f0261ff00199415159490941661ffff19909c169b909b1792909217989098169b909b1795909517939093169590951717939093169590951794909417919091161790915590517ffa0f19ecb97e973eefa78c4ef4f6be467d4e0d320b88fa6b3e785f09df7089f6916200037291849190829081908190819081908c90971515885295151560208801529315156040870152911515606086015215156080850152151560a0840152151560c083015263ffffffff1660e082015261012061010082018190526017908201527f44454641554c5420534543555249545920504f4c4943590000000000000000006101408201526101600190565b60405180910390a260005b8151811015620004225760008282815181106200039e576200039e620005be565b6020908102919091018101516001600160a01b03811660008181527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec9093526040808420805460ff191660011790555191935091907fbb1b20966aa1c5d6ce073b9c8bf92e61bc7637cfa60464b83d2be54b7fe11eb3908290a3506001016200037d565b506200042e8362000437565b505050620005d4565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200049f57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600060608486031215620004d057600080fd5b620004db8462000487565b925060208085015163ffffffff81168114620004f657600080fd5b60408601519093506001600160401b03808211156200051457600080fd5b818701915087601f8301126200052957600080fd5b8151818111156200053e576200053e620004a4565b8060051b604051601f19603f83011681018181108582111715620005665762000566620004a4565b60405291825284820192508381018501918a8311156200058557600080fd5b938501935b82851015620005ae576200059e8562000487565b845293850193928501926200058a565b8096505050505050509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516101005161012051615ffd620006246000396000613a9801526000613ada01526000613ab901526000613a1d01526000613a4701526000613a710152615ffd6000f3fe6080604052600436106102dc5760003560e01c80636c2be897116101845780639627a039116100d6578063dbcbf11b1161008a578063ed24911d11610064578063ed24911d146109b8578063f2e69c42146109cd578063f2fde38b14610a1857600080fd5b8063dbcbf11b14610858578063e67feac814610983578063ec72573f1461099857600080fd5b8063d3055dde116100bb578063d3055dde1461080f578063d3a5e4a114610822578063d73792a91461084257600080fd5b80639627a039146107dc578063c519e3d7146107fc57600080fd5b80637996eef0116101385780637d26279c116101125780637d26279c146107965780638456cb59146107a95780638da5cb5b146107be57600080fd5b80637996eef0146106fc5780637a2170d51461071c5780637d22c35c1461075057600080fd5b8063715018a611610169578063715018a61461066d578063753d130914610682578063755205e8146106b657600080fd5b80636c2be897146106195780636e80a2591461064d57600080fd5b80632ff3449f1161023d5780634faee3fe116101f15780635ed1f9bb116101cb5780635ed1f9bb146105945780635f3e9f42146105a7578063666c2334146105e557600080fd5b80634faee3fe146104f15780635731737c146105275780635c975abb1461057557600080fd5b8063414ab72711610222578063414ab72714610484578063420dab43146104a457806345253c53146104c457600080fd5b80632ff3449f1461044f5780633f4ba83a1461046f57600080fd5b80631af161cb1161029457806326c6ac301161027957806326c6ac30146103ef57806326ed4aa11461040f5780632f3ba8021461042f57600080fd5b80631af161cb146103ba578063226d4adb146103da57600080fd5b8063138315a3116102c5578063138315a31461033857806316ea5ca8146103585780631a2125cf1461037857600080fd5b806301ffc9a7146102e1578063096ff95d14610316575b600080fd5b3480156102ed57600080fd5b506103016102fc366004614e44565b610a38565b60405190151581526020015b60405180910390f35b34801561032257600080fd5b50610336610331366004614ecb565b610a6f565b005b34801561034457600080fd5b50610336610353366004614f7f565b610c1f565b34801561036457600080fd5b50610336610373366004614faf565b610cb9565b34801561038457600080fd5b506103ac7f80244acca7a02d7199149a3038653fc8cb10ca984341ec429a626fab631e166281565b60405190815260200161030d565b3480156103c657600080fd5b506103366103d5366004614fdb565b610d2c565b3480156103e657600080fd5b50610336610d3a565b3480156103fb57600080fd5b5061033661040a366004614faf565b610d8a565b34801561041b57600080fd5b506103ac61042a366004614faf565b610d9c565b34801561043b57600080fd5b5061033661044a366004614f7f565b610db2565b34801561045b57600080fd5b5061033661046a366004614ff4565b610e4c565b34801561047b57600080fd5b50610336610f31565b34801561049057600080fd5b5061033661049f366004614f7f565b610f43565b3480156104b057600080fd5b506103366104bf3660046150a4565b611008565b3480156104d057600080fd5b506103ac6104df366004615186565b60066020526000908152604090205481565b3480156104fd57600080fd5b506103ac61050c366004615186565b6001600160a01b031660009081526002602052604090205490565b34801561053357600080fd5b5061055d610542366004615186565b6008602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161030d565b34801561058157600080fd5b50600054600160a01b900460ff16610301565b6103366105a23660046151e8565b611031565b3480156105b357600080fd5b506103016105c2366004615186565b6001600160a01b0316600090815260096020526040902054610100900460ff1690565b3480156105f157600080fd5b506103ac7f2008a1ab898fdaa2d8f178bc39e807035d2d6e330dac5e42e913ca727ab5603881565b34801561062557600080fd5b506103ac7f0bc3075778b80a2341ce445063e81924b88d61eb5f21c815e8f9cc824af096d081565b34801561065957600080fd5b506103ac6106683660046152b1565b6111f4565b34801561067957600080fd5b50610336611223565b34801561068e57600080fd5b506103ac7f126520d0bca0cfa7e5852d004cc4335723ce67c638cbd55cd530fe992a089e7b81565b3480156106c257600080fd5b506103016106d1366004614f7f565b60009182526004602090815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561070857600080fd5b506103ac610717366004614faf565b611235565b34801561072857600080fd5b506103ac7fd3f4273db8ff5262b6bc5f6ee07d139463b4f826cce90c05165f63062f3686dc81565b34801561075c57600080fd5b5061030161076b366004614f7f565b60009182526003602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6103366107a43660046155fe565b61124b565b3480156107b557600080fd5b5061033661127c565b3480156107ca57600080fd5b506000546001600160a01b031661055d565b3480156107e857600080fd5b506103366107f7366004614f7f565b61128c565b61033661080a36600461574e565b61132a565b61033661081d366004615801565b61166c565b34801561082e57600080fd5b5061033661083d366004614f7f565b61199c565b34801561084e57600080fd5b506103ac61271081565b34801561086457600080fd5b50610976610873366004614fdb565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250600090815260056020908152604091829020825161012081018452905460ff80821615158352610100808304821615159484019490945262010000820481161515948301949094526301000000810484161515606083015264010000000081048416151560808301526501000000000081048416151560a083015266010000000000008104909316151560c0820152600160381b830463ffffffff1660e0820152600160581b9092046001600160a01b03169082015290565b60405161030d9190615878565b34801561098f57600080fd5b506103ac600081565b3480156109a457600080fd5b506103366109b3366004615927565b6119d1565b3480156109c457600080fd5b506103ac611a3e565b3480156109d957600080fd5b506103016109e8366004614faf565b6001600160a01b03919091166000908152600a602090815260408083209383529290522054610100900460ff1690565b348015610a2457600080fd5b50610336610a33366004615186565b611a4d565b60006001600160e01b0319821663306d7a2160e11b1480610a6957506301ffc9a760e01b6001600160e01b03198316145b92915050565b610a7885611ac8565b828114610a985760405163b62503e360e01b815260040160405180910390fd5b82610ab65760405163db560cb560e01b815260040160405180910390fd5b6001600160a01b0385166000908152600a6020526040812090805b85811015610c1557868682818110610aeb57610aeb615955565b9050602002013591506000858583818110610b0857610b08615955565b905060800201803603810190610b1e919061596b565b600084815260208690526040902054909150610100900460ff1615610b565760405163793c666f60e01b815260040160405180910390fd5b806060015181604001511115610b7f5760405163420a69a160e01b815260040160405180910390fd5b60008381526020858152604091829020835181548584015115156101000261ff00199215159290921661ffff199091161717815583830151600182018190556060850151600290920182905583519081529182015284916001600160a01b038c16917f38d88037c7f872f6e5d89332cdae804370cd604776bfcabf8da1f2e11945e271910160405180910390a350600101610ad1565b5050505050505050565b610c2882611c0f565b60008281526003602090815260408083206001600160a01b0385168452918290529091205460ff16610c6d5760405163a935ea0b60e01b815260040160405180910390fd5b6001600160a01b038216600081815260208390526040808220805460ff191690555185917f0aa5e1c56725fc01d0a61fc7302ff0201516b9af2b7261b4ecbea2f74611b5d191a3505050565b610cc282611ac8565b600154811115610ce557604051631797d38360e21b815260040160405180910390fd5b6001600160a01b038216600081815260026020526040808220849055518392917f8a2e423ccab4754dc61747d26d19bc14c55577d5fcc54b4a67d9b82a016b61df91a35050565b610d37816000611c56565b50565b3360008181526006602052604080822054905190917fb06d2760711c1c15c05bc011b1009a36c0713c6d63567c267678c3a382188b6191a333600090815260066020526040902080546001019055565b610d978233836001611ce0565b505050565b600080610da98484611e0f565b95945050505050565b610dbb82611c0f565b60008281526004602090815260408083206001600160a01b0385168452918290529091205460ff16610e005760405163ced71fff60e01b815260040160405180910390fd5b6001600160a01b038216600081815260208390526040808220805460ff191690555185917f24dced5d5e85a1733ad613a53ada041ecc410cca5ee598e3115b67d4a2525e3891a3505050565b610e5582611ac8565b6001600160a01b038216600090815260096020526040902054610100900460ff1615610e945760405163793c666f60e01b815260040160405180910390fd5b806060013581604001351115610ebd5760405163420a69a160e01b815260040160405180910390fd5b6001600160a01b03821660009081526009602052604090208190610ee182826159ee565b505060408051818301358152606083013560208201526001600160a01b038416917fdd61e240b8302b21ad48e3bec0f6e9538c9e4cfffdfde6d604963069d7e23c34910160405180910390a25050565b610f39611f06565b610f41611f60565b565b610f4c82611c0f565b6001600160a01b038116610f7357604051637a79ae6b60e11b815260040160405180910390fd5b60008281526003602090815260408083206001600160a01b0385168452918290529091205460ff1615610fb95760405163467d57a760e11b815260040160405180910390fd5b6001600160a01b038216600081815260208390526040808220805460ff191660011790555185917f3286c4e8704920b56173a2f9884345d5f5b90893a15dce75abc157df4081af5f91a3505050565b6110118b611c0f565b6110248b8b8b8b8b8b8b8b8b8b8b611fb5565b5050505050505050505050565b61103961219c565b84831415806110485750848114155b156110665760405163b62503e360e01b815260040160405180910390fd5b846110845760405163db560cb560e01b815260040160405180910390fd5b3461108d614d56565b6040805160608082018352600080835260208084018290528385018290528451928301855281835282018190529281018390529091805b8a8110156111d4578b8b828181106110de576110de615955565b905061028002018036038101906110f59190615a49565b945089898281811061110957611109615955565b90506060020180360381019061111f9190615a66565b935087878281811061113357611133615955565b9050606002018036038101906111499190615a66565b6060860151909350600092506001600160a01b03166111be57846101e0015191508186101561118b5760405163386ad99760e11b815260040160405180910390fd5b818603955061119c828686866121f6565b6111b95760405163f40863ff60e01b815260040160405180910390fd5b6111cc565b6111ca828686866121f6565b505b6001016110c4565b508415611024576040516315a53e4560e31b815260040160405180910390fd5b60018054810190819055600090611214818d8d8d8d8d8d8d8d8d8d611fb5565b9b9a5050505050505050505050565b61122b611f06565b610f4160006128e6565b6000806112428484611e0f565b50949350505050565b61125361219c565b61125f348484846121f6565b610d975760405163f40863ff60e01b815260040160405180910390fd5b611284611f06565b610f41612943565b61129582611c0f565b60008281526004602090815260408083206001600160a01b0385168452918290529091205460ff16156112db57604051637f622a5960e01b815260040160405180910390fd5b6001600160a01b038216600081815260208390526040808220805460ff191660011790555185917fbb1b20966aa1c5d6ce073b9c8bf92e61bc7637cfa60464b83d2be54b7fe11eb391a3505050565b61133261219c565b806113505760405163db560cb560e01b815260040160405180910390fd5b82516040908101516001600160a01b0316600090815260026020908152828220548083526005825283832084516001808252818701909652919490939282015b604080516060810182526000808252602080830182905292820152825260001990920191018161139057905050905087816000815181106113d3576113d3615955565b60200260200101819052506000806114416000858a8a8a808060200260200160405190810160405280939291908181526020016000905b828210156114365761142760e08302860136819003810190615a82565b8152602001906001019061140a565b505050505087612986565b9150915061145685858a60000151858d6132a0565b6040805160a08082019092528554600160381b900463ffffffff1681528951909101516000916115249160208201906001600160a01b03161561149e578b5160a001516114a5565b8b51608001515b6001600160a01b0390811682528c516020908101518216818401528d51015160409092019116156114d8576135a56114dc565b6135b15b67ffffffffffffffff16815260200160018c5151600181111561150157611501615b1a565b1461150e576135bc611512565b61363c5b67ffffffffffffffff16905283613692565b90506001895151600181111561153c5761153c615b1a565b14156115d6578860000151602001516001600160a01b03168960000151604001516001600160a01b03168a6000015160c001516001600160a01b03167f4b761d38cae19a364a5d44d2c4a5cdd41113f9e4d64ae2e21b766d072705b9318c60000151608001518d602001518689600001518a602001518b604001516040516115c996959493929190615b9d565b60405180910390a4611024565b8860000151602001516001600160a01b03168960000151604001516001600160a01b03168a6000015160c001516001600160a01b03167ff5960c81abf2cbc811a3b86b2b2c0338bfd5c47ad8815c941f9d59665a8d458b8c60000151608001518d602001518689600001518a60400151604051611657959493929190615c10565b60405180910390a45050505050505050505050565b61167461219c565b8281146116945760405163b62503e360e01b815260040160405180910390fd5b826116b25760405163db560cb560e01b815260040160405180910390fd5b6000806116e787604001516001600160a01b031660009081526002602090815260408083205480845260059092529091209091565b915091506000806117cc60018460405180608001604052808d815260200160006001600160a01b031681526020016000815260200160008152508b8b808060200260200160405190810160405280939291908181526020016000905b8282101561176f5761176060e08302860136819003810190615a82565b81526020019060010190611743565b50505050508a8a808060200260200160405190810160405280939291908181526020016000905b828210156117c2576117b360608302860136819003810190615a66565b81526020019060010190611796565b5050505050612986565b915091506117dd84848b858e6132a0565b6040805160a08082019092528454600160381b900463ffffffff168152908a01516000916118979160208201906001600160a01b031615611822578c60a00151611828565b8c608001515b6001600160a01b031681526020018c602001516001600160a01b0316815260200160006001600160a01b03168d602001516001600160a01b03161461186f576135a5611873565b6135b15b67ffffffffffffffff16815260200160018d51600181111561150157611501615b1a565b905060018a5160018111156118ae576118ae615b1a565b141561192b5789602001516001600160a01b03168a604001516001600160a01b03168b60c001516001600160a01b03167f35cd37c73a78d0322074e1324a7d5d4cf5c7ff21f3265d03f4d085c532c6f0198d6080015185886080015189600001518a602001518b604001516040516115c996959493929190615ca7565b89602001516001600160a01b03168a604001516001600160a01b03168b60c001516001600160a01b03167f8435e05433e0d3a3fe612b10c36f6623deec79239f76721a154687fef0ca46a18d6080015185886080015189600001518a60400151604051611657959493929190615cef565b6001600160a01b0381166119c357604051632949de9560e01b815260040160405180910390fd5b6119cd8282611c56565b5050565b6119da82611ac8565b6001600160a01b03828116600081815260086020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169486169485179055517f53ab061e9517daf6849d4bde07950e3d199f73115c2e4842a8b20a62e83abd1c9190a35050565b6000611a48613a10565b905090565b611a55611f06565b6001600160a01b038116611abf5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b610d37816128e6565b336001600160a01b0382161480611bf157816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b1257600080fd5b505afa925050508015611b42575060408051601f3d908101601f19168201909252611b3f91810190615d37565b60015b611b4b57611b59565b6001600160a01b0316331490505b80611bf1576001600160a01b0382166391d148546000336040516001600160e01b031960e085901b16815260048101929092526001600160a01b0316602482015260440160206040518083038186803b158015611bb557600080fd5b505afa925050508015611be5575060408051601f3d908101601f19168201909252611be291810190615d54565b60015b611bee57611bf1565b90505b806119cd576040516380a6c4af60e01b815260040160405180910390fd5b600081815260056020526040902054600160581b90046001600160a01b0316336001600160a01b031614610d3757604051638d1a2f3760e01b815260040160405180910390fd5b611c5f82611c0f565b60008281526005602052604080822080546001600160a01b03858116600160581b8181027fff0000000000000000000000000000000000000000ffffffffffffffffffffff851617855594519395949092041692909183917f195d9a13f822aeb682fa730ba46c3e3e6103134a536f98e5c40c81cc004f0a8491a350505050565b6040516bffffffffffffffffffffffff19606086811b8216602084015285901b16603482015260009081906007908290604801604051602081830303815290604052805190602001208152602001908152602001600020905060006101008581611d4c57611d4c615d71565b0460008181526020849052604090205490915060ff861690600181831c81161415611d8a5760405163015236d560e61b815260040160405180910390fd5b60009283526020849052604092839020600190921b179055516001600160a01b03808816919087169086907f61b992b9cb8061087d0e50532a8ba94e22379c7edd39cdb465536ef827dc1be790611de690881515815260200190565b60405180910390a4505050506001600160a01b0316600090815260066020526040902054919050565b6001600160a01b0382166000908152600a6020908152604080832084845282528083208151608081018352815460ff8082161580158452610100909204161515948201949094526001820154928101929092526002015460608201528291611e8557806040015181606001519250925050611eff565b6001600160a01b0385166000908152600960209081526040918290208251608081018452815460ff808216158015845261010090920416151593820193909352600182015493810193909352600201546060830152611ef35780604001518160600151935093505050611eff565b50600060001992509250505b9250929050565b6000546001600160a01b03163314610f415760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611ab6565b611f68613afe565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6040518061012001604052808b151581526020018a15158152602001891515815260200188151581526020018715158152602001861515815260200185151581526020018463ffffffff16815260200161200c3390565b6001600160a01b0390811690915260008d8152600560209081526040918290208451815492860151868501516060880151608089015160a08a015160c08b015160e08c01516101009c8d015161ffff19909a1697151561ff00191697909717951515909b029490941763ffff00001916620100009315159390930263ff0000001916929092176301000000911515919091021765ffff0000000019166401000000009115159190910265ff00000000001916176501000000000091151591909102176affffffffff00000000000019166601000000000000961515969096026affffffff00000000000000191695909517600160381b63ffffffff90961695909502949094177fff0000000000000000000000000000000000000000ffffffffffffffffffffff16600160581b919093160291909117909155518b907ffa0f19ecb97e973eefa78c4ef4f6be467d4e0d320b88fa6b3e785f09df7089f690612187908d908d908d908d908d908d908d908d908d908d90615d87565b60405180910390a25050505050505050505050565b600054600160a01b900460ff1615610f415760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401611ab6565b6080808401516001600160a01b0390811660009081526002602090815260408083205480845260058352818420825161012081018452905460ff80821615158352610100808304821615159684019690965262010000820481161515948301949094526301000000810484161515606080840191909152640100000000820485161515988301989098526501000000000081048416151560a083015266010000000000008104909316151560c082015263ffffffff600160381b84041660e0820152600160581b90920485169282019290925293870151919390929091166123395786866101e00151146122fd57604051630db5f82b60e21b815260040160405180910390fd5b855180612316575060a08601516001600160a01b031632145b1561233457604051632d8457d960e21b815260040160405180910390fd5b612375565b861561235857604051635d6c7e8160e01b815260040160405180910390fd5b612375828260200151836040015189608001518a60600151613b57565b60018660400151600181111561238d5761238d615b1a565b14156123bb576102608601516123b6576040516326db27f160e01b815260040160405180910390fd5b6123e1565b6001866102600151146123e157604051636d9e53cd60e11b815260040160405180910390fd5b8561020001514211156124075760405163099465a960e41b815260040160405180910390fd5b85610220015142111561242d5760405163026de79960e21b815260040160405180910390fd5b856101c00151866101e00151101561245857604051636769dcf160e11b815260040160405180910390fd5b6127108661016001518761014001516124719190615e1e565b1115612490576040516332a7479560e21b815260040160405180910390fd5b60c08601516001600160a01b031615612500578560c001516001600160a01b03168660e001516001600160a01b0316146124dd5760405163185ff71160e21b815260040160405180910390fd5b8060600151156125005760405163646c1dcd60e11b815260040160405180910390fd5b6101008601516001600160a01b03161561256e576101008601516001600160a01b0316336001600160a01b03161461254b576040516390158e4760e01b815260040160405180910390fd5b80608001511561256e576040516358f8e8a560e01b815260040160405180910390fd5b8060a00151156125d25760a08601516001600160a01b03163b156125a55760405163321e0c1560e11b815260040160405180910390fd5b60e08601516001600160a01b03163b156125d25760405163321e0c1560e11b815260040160405180910390fd5b8051156126635733321461261f57600082815260036020908152604080832033845290915290205460ff1661261a576040516329837f1160e21b815260040160405180910390fd5b612663565b8060c001511561266357600082815260036020908152604080832033845290915290205460ff1661266357604051631d4ca04b60e11b815260040160405180910390fd5b8060400151156126dc5760608601516001600160a01b03166126bd5760808601516001600160a01b0390811660009081526008602052604090205416156126bd576040516305a3b2ed60e41b815260040160405180910390fd5b6126dc8660800151876102400151886102600151896101e00151613be8565b6126e68686613c52565b8560200151156126ff576126fa8685613e48565b612709565b6127098685613fef565b604080516001808252818301909252600091816020015b612728614d56565b815260200190600190039081612720579050509050868160008151811061275157612751615955565b602002602001018190525060006128066040518060a001604052808560e0015163ffffffff16815260200160006001600160a01b03168b61010001516001600160a01b0316146127a6578a61010001516127ac565b8a60e001515b6001600160a01b03908116825260608c018051821660208401525160409092019116156127db576135a56127df565b6135b15b67ffffffffffffffff16815260200160018b60400151600181111561150157611501615b1a565b90508060008151811061281b5761281b615955565b602002602001015115945084156128da5787606001516001600160a01b031688608001516001600160a01b03168961012001516001600160a01b03167f7ed668b30822ae5c7db7b4a32f84e6645250bb6db0d1fc73eeb484c5b34b1d1b8b60e001518c60a001518d61024001518e61026001518f6101e001516040516128d19594939291906001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60405180910390a45b50505050949350505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61294b61219c565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611f983390565b6129bf6040518060c001604052806060815260200160608152602001606081526020016060815260200160608152602001600081525090565b6060835167ffffffffffffffff8111156129db576129db61538c565b604051908082528060200260200182016040528015612a1457816020015b612a01614d56565b8152602001906001900390816129f95790505b5090506040518060c00160405280855167ffffffffffffffff811115612a3c57612a3c61538c565b604051908082528060200260200182016040528015612a65578160200160208202803683370190505b508152602001855167ffffffffffffffff811115612a8557612a8561538c565b604051908082528060200260200182016040528015612aae578160200160208202803683370190505b508152602001855167ffffffffffffffff811115612ace57612ace61538c565b604051908082528060200260200182016040528015612af7578160200160208202803683370190505b508152602001855167ffffffffffffffff811115612b1757612b1761538c565b604051908082528060200260200182016040528015612b40578160200160208202803683370190505b508152602001855167ffffffffffffffff811115612b6057612b6061538c565b604051908082528060200260200182016040528015612b89578160200160208202803683370190505b5081526020016000815250915060005b84518110156130c8576020860151604087015160608801518a15612c1857878481518110612bc957612bc9615955565b602002602001015160c001519250878481518110612be957612be9615955565b6020026020010151608001519150878481518110612c0957612c09615955565b602002602001015160a0015190505b60408051610280810182526000808252602082018190528b515190928201906001811115612c4857612c48615b1a565b81526020018b60000151602001516001600160a01b031681526020018b60000151604001516001600160a01b03168152602001856001600160a01b031681526020018b60000151606001516001600160a01b031681526020018b60000151608001516001600160a01b031681526020018b6000015160a001516001600160a01b031681526020018b6000015160c001516001600160a01b031681526020018b6000015160e0015181526020018a8781518110612d0657612d06615955565b60200260200101516040015181526020018481526020018b60000151610100015181526020018a8781518110612d3e57612d3e615955565b60200260200101516060015181526020018a8781518110612d6157612d61615955565b60200260200101516060015181526020018381526020018b60000151610140015181526020018a8781518110612d9957612d99615955565b60200260200101516000015181526020018a8781518110612dbc57612dbc615955565b602002602001015160200151815250905080868681518110612de057612de0615955565b602002602001018190525080610240015187600001518681518110612e0757612e07615955565b60200260200101818152505080610260015187602001518681518110612e2f57612e2f615955565b602002602001018181525050806101c0015187604001518681518110612e5757612e57615955565b60200260200101818152505080610160015187606001518681518110612e7f57612e7f615955565b6020026020010181815250508060a0015187608001518681518110612ea657612ea6615955565b60200260200101906001600160a01b031690816001600160a01b031681525050806101c001518760a001818151612edd9190615e1e565b905250600181604001516001811115612ef857612ef8615b1a565b1415612f2657610260810151612f21576040516326db27f160e01b815260040160405180910390fd5b612f4c565b600181610260015114612f4c57604051636d9e53cd60e11b815260040160405180910390fd5b612710816101600151826101400151612f659190615e1e565b1115612f84576040516332a7479560e21b815260040160405180910390fd5b8a5462010000900460ff1615612fb357612fb38160800151826102400151836102600151846101e00151613be8565b8b156130b957806102000151421115612fdf5760405163099465a960e41b815260040160405180910390fd5b60c08101516001600160a01b031615613056578060c001516001600160a01b03168160e001516001600160a01b03161461302c5760405163185ff71160e21b815260040160405180910390fd5b8a546301000000900460ff16156130565760405163646c1dcd60e11b815260040160405180910390fd5b8a5465010000000000900460ff16156130965760a08101516001600160a01b03163b156130965760405163321e0c1560e11b815260040160405180910390fd5b6130b9818987815181106130ac576130ac615955565b6020026020010151613c52565b84600101945050505050612b99565b50866132965784606001514211156130f35760405163099465a960e41b815260040160405180910390fd5b8451606001516001600160a01b03161561316957845160608101516080909101516001600160a01b0390811691161461313f5760405163185ff71160e21b815260040160405180910390fd5b85546301000000900460ff16156131695760405163646c1dcd60e11b815260040160405180910390fd5b855465010000000000900460ff16156131a95760208501516001600160a01b03163b156131a95760405163321e0c1560e11b815260040160405180910390fd5b613296604051806080016040528084600001516040516020016131cc9190615e36565b60405160208183030381529060405280519060200120815260200184602001516040516020016131fc9190615e36565b604051602081830303815290604052805190602001208152602001846060015160405160200161322c9190615e36565b604051602081830303815290604052805190602001208152602001846040015160405160200161325c9190615e36565b60405160208183030381529060405280519060200120815250868560008151811061328957613289615955565b60200260200101516140c9565b9550959350505050565b60208301516001600160a01b0316156133015734156132d257604051635d6c7e8160e01b815260040160405180910390fd5b8354604084015160208501516132fc92889260ff6101008304811693620100009093041691613b57565b613375565b826101200151341461332657604051630db5f82b60e21b815260040160405180910390fd5b835462010000900460ff1615613375576040808401516001600160a01b039081166000908152600860205291909120541615613375576040516305a3b2ed60e41b815260040160405180910390fd5b82610140015142111561339b5760405163026de79960e21b815260040160405180910390fd5b60a08301516001600160a01b03161561340f5760a08301516001600160a01b0316336001600160a01b0316146133e4576040516390158e4760e01b815260040160405180910390fd5b8354640100000000900460ff161561340f576040516358f8e8a560e01b815260040160405180910390fd5b835465010000000000900460ff161561344f5760808301516001600160a01b03163b1561344f5760405163321e0c1560e11b815260040160405180910390fd5b835460ff16156134ed5733321461349f57600085815260036020908152604080832033845290915290205460ff1661349a576040516329837f1160e21b815260040160405180910390fd5b6134ed565b83546601000000000000900460ff16156134ed57600085815260036020908152604080832033845290915290205460ff166134ed57604051631d4ca04b60e11b815260040160405180910390fd5b8261012001518260a001511461351657604051637867d96760e11b815260040160405180910390fd5b815160405161359e9161352b91602001615e36565b6040516020818303038152906040528051906020012083602001516040516020016135569190615e36565b6040516020818303038152906040528051906020012084604001516040516020016135819190615e36565b604051602081830303815290604052805190602001208685614282565b5050505050565b61359e83858785614436565b61359e8583836144a5565b6040516323b872dd60e01b81526001600160a01b038681166004830152858116602483015260448201849052600091908516906323b872dd906064015b600060405180830381600087803b15801561361357600080fd5b505af1925050508015613624575060015b61363057506000610da9565b50600195945050505050565b604051637921219560e11b81526001600160a01b0386811660048301528581166024830152604482018490526064820183905260a06084830152600060a48301819052919085169063f242432a9060c4016135f9565b6060815167ffffffffffffffff8111156136ae576136ae61538c565b6040519080825280602002602001820160405280156136d7578160200160208202803683370190505b506040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081018290529192505b835181101561396f57600084828151811061372a5761372a615955565b6020026020010151905060006137618260a001518360e0015184608001518561024001518661026001518c6080015163ffffffff16565b9050806137bc5760408701516001600160a01b03166137935760405163f40863ff60e01b815260040160405180910390fd5b60018584815181106137a7576137a7615955565b91151560209283029190910190910152613965565b60006137e9836101e0015184608001518561024001518661012001518761014001518861016001516144d1565b905084604001516001600160a01b031681600001516001600160a01b0316146138575760a08501511561383f5761383f856040015189602001518a604001518860a001518c600001518d6060015163ffffffff16565b80516001600160a01b03166040860152600060a08601525b84602001516001600160a01b03168361012001516001600160a01b0316146138c8576080850151156138ac576138ac856020015189602001518a6040015188608001518c600001518d6060015163ffffffff16565b6101208301516001600160a01b03166020860152600060808601525b84600001516001600160a01b03168360a001516001600160a01b0316146139345760608501511561391c5761391c856000015189602001518a6040015188606001518c600001518d6060015163ffffffff16565b60a08301516001600160a01b03168552600060608601525b602081015160a086018051909101905260408101516080860180519091019052606090810151908501805190910190525b505060010161370d565b5060a0810151156139a3576139a38160400151856020015186604001518460a001518860000151896060015163ffffffff16565b6080810151156139d6576139d681602001518560200151866040015184608001518860000151896060015163ffffffff16565b606081015115613a0957613a0981600001518560200151866040015184606001518860000151896060015163ffffffff16565b5092915050565b6000306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148015613a6957507f000000000000000000000000000000000000000000000000000000000000000046145b15613a9357507f000000000000000000000000000000000000000000000000000000000000000090565b611a487f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000614681565b600054600160a01b900460ff16610f415760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401611ab6565b8215613b9f576001600160a01b03828116600090815260086020526040902054811690821614613b9a576040516355ce006f60e11b815260040160405180910390fd5b61359e565b831561359e5760008581526004602090815260408083206001600160a01b038516845290915290205460ff1661359e576040516355ce006f60e11b815260040160405180910390fd5b6000613bf48383615e6c565b9050600080613c038787611e0f565b9150915081831015613c285760405163024c625160e61b815260040160405180910390fd5b80831115613c4957604051639837ddd760e01b815260040160405180910390fd5b50505050505050565b6000613dd57fd3f4273db8ff5262b6bc5f6ee07d139463b4f826cce90c05165f63062f3686dc60001b84604001516001811115613c9157613c91615b1a565b855161012087015161014088015161016089015160c08a0151604051613cfa979695949392919060200196875260ff95909516602087015292151560408601526001600160a01b039182166060860152608085015260a08401919091521660c082015260e00190565b60408051601f1981840301815291905260a085015160808601516102408701516102608801516101c08901516102008a01516101808b01516101208c0151613d459088836000611ce0565b6060808e0151604080516001600160a01b039b8c166020820152998b16908a015290880196909652608087019490945260a086019290925260c085015260e084015261010083015291909116610120820152610140015b60408051601f1981840301815290829052613dba9291602001615eba565b604051602081830303815290604052805190602001206146cb565b60a08401519091506001600160a01b03163b15613dfb57610d978360a001518284614719565b613e1381836000015184602001518560400151614833565b6001600160a01b03168360a001516001600160a01b031614610d97576040516312a0f2db60e11b815260040160405180910390fd5b6000613f7c7f0bc3075778b80a2341ce445063e81924b88d61eb5f21c815e8f9cc824af096d060001b84604001516001811115613e8757613e87615b1a565b6020808701516101208801516101408901516101008a015160e08b015160808c01516102608d01516101e08e0151604051613f159b9a9901998a5260ff9890981660208a015295151560408901526001600160a01b039485166060890152608088019390935290831660a0870152821660c08601521660e08401526101008301526101208201526101400190565b604051602081830303815290604052846102200151856101a00151613f4b8761012001518860e00151896101a001516000611ce0565b6060808901516040805160208101969096528501939093528301526001600160a01b0316608082015260a001613d9c565b60e08401519091506001600160a01b03163b15613fa257610d978360e001518284614719565b613fba81836000015184602001518560400151614833565b6001600160a01b03168360e001516001600160a01b031614610d97576040516320af217960e01b815260040160405180910390fd5b6000613f7c7f2008a1ab898fdaa2d8f178bc39e807035d2d6e330dac5e42e913ca727ab5603860001b8460400151600181111561402e5761402e615b1a565b8561012001518661014001518761010001518860e0015189608001518a61024001518b61026001518c6101e00151604051602001613f159a99989796959493929190998a5260ff9890981660208a01526001600160a01b0396871660408a01526060890195909552928516608088015290841660a087015290921660c085015260e08401919091526101008301526101208201526101400190565b815151600090614204907f80244acca7a02d7199149a3038653fc8cb10ca984341ec429a626fab631e166290600181111561410657614106615b1a565b855160c081015160e082015160608301516020808b0151604095860151955161416e98979691920196875260ff9590951660208701526001600160a01b039384166040870152606086019290925282166080850152811660a08401521660c082015260e00190565b60408051601f19818403018152918152606086015190860151865160c00151602088015161419f9190836000611ce0565b87516020908101518a518b8301516040808e015160608f01519151613d9c9998979691929101978852602088019690965260408701949094526001600160a01b03929092166060860152608085015260a084015260c083015260e08201526101000190565b60208401519091506001600160a01b03163b1561422f5761422a83602001518284614719565b61427c565b61424781836000015184602001518560400151614833565b6001600160a01b031683602001516001600160a01b03161461427c576040516312a0f2db60e11b815260040160405180910390fd5b50505050565b81516000906143b6907f126520d0bca0cfa7e5852d004cc4335723ce67c638cbd55cd530fe992a089e7b9060018111156142be576142be615b1a565b8560c001518660e001518760a00151886080015189604001518a610120015160405160200161433698979695949392919097885260ff9690961660208801526001600160a01b03948516604088015260608701939093529083166080860152821660a08501521660c083015260e08201526101000190565b60405160208183030381529060405284610140015185610100015161436b8760c0015188608001518961010001516000611ce0565b60208881015160408051928301959095529381019290925260608201526001600160a01b03909116608082015260a0810189905260c0810188905260e0810187905261010001613d9c565b60808401519091506001600160a01b03163b156143e1576143dc83608001518284614719565b61442e565b6143f981836000015184602001518560400151614833565b6001600160a01b031683608001516001600160a01b03161461442e576040516320af217960e01b815260040160405180910390fd5b505050505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166323b872dd60e01b17905261427c90859061485b565b6000806000806000868887f190508061427c5760405163364cc69f60e11b815260040160405180910390fd5b614505604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6060810187905260405163152a902d60e11b815260048101869052602481018890526001600160a01b03871690632a55205a90604401604080518083038186803b15801561455257600080fd5b505afa925050508015614582575060408051601f3d908101601f1916820190925261457f91810190615ee9565b60015b6145bc573d8080156145b0576040519150601f19603f3d011682016040523d82523d6000602084013e6145b5565b606091505b505061462d565b6001600160a01b0382166145ce575060005b801561462a576127106145e1858b615f17565b6145eb9190615e6c565b81111561460b576040516306f6f23d60e21b815260040160405180910390fd5b6001600160a01b03821683526020830181905260608301805182900390525b50505b6001600160a01b038416614642576000614659565b61271061464f8489615f17565b6146599190615e6c565b60408201819052156146775760408101516060820180519190910390525b9695505050505050565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090505b9392505050565b6000610a696146d8613a10565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000836001600160a01b0316631626ba7e8484602001518560400151866000015160405160200161478293929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016147ae929190615f62565b60206040518083038186803b1580156147c657600080fd5b505afa9250505080156147f6575060408051601f3d908101601f191682019092526147f391810190615f7b565b60015b6147ff57614815565b6001600160e01b031916630b135d3f60e11b1490505b8061427c576040516307c1d80160e51b815260040160405180910390fd5b60008060006148448787878761492d565b9150915061485181614a1a565b5095945050505050565b60006148b0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614bd59092919063ffffffff16565b805190915015610d9757808060200190518101906148ce9190615d54565b610d975760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611ab6565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156149645750600090506003614a11565b8460ff16601b1415801561497c57508460ff16601c14155b1561498d5750600090506004614a11565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156149e1573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116614a0a57600060019250925050614a11565b9150600090505b94509492505050565b6000816004811115614a2e57614a2e615b1a565b1415614a375750565b6001816004811115614a4b57614a4b615b1a565b1415614a995760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401611ab6565b6002816004811115614aad57614aad615b1a565b1415614afb5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611ab6565b6003816004811115614b0f57614b0f615b1a565b1415614b685760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401611ab6565b6004816004811115614b7c57614b7c615b1a565b1415610d375760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401611ab6565b6060614be48484600085614bec565b949350505050565b606082471015614c4d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611ab6565b6001600160a01b0385163b614ca45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611ab6565b600080866001600160a01b03168587604051614cc09190615f98565b60006040518083038185875af1925050503d8060008114614cfd576040519150601f19603f3d011682016040523d82523d6000602084013e614d02565b606091505b5091509150614d12828286614d1d565b979650505050505050565b60608315614d2c5750816146c4565b825115614d3c5782518084602001fd5b8160405162461bcd60e51b8152600401611ab69190615fb4565b60408051610280810182526000808252602082018190529091820190815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160e01b031981168114610d3757600080fd5b600060208284031215614e5657600080fd5b81356146c481614e2e565b6001600160a01b0381168114610d3757600080fd5b8035614e8181614e61565b919050565b60008083601f840112614e9857600080fd5b50813567ffffffffffffffff811115614eb057600080fd5b6020830191508360208260071b8501011115611eff57600080fd5b600080600080600060608688031215614ee357600080fd5b8535614eee81614e61565b9450602086013567ffffffffffffffff80821115614f0b57600080fd5b818801915088601f830112614f1f57600080fd5b813581811115614f2e57600080fd5b8960208260051b8501011115614f4357600080fd5b602083019650809550506040880135915080821115614f6157600080fd5b50614f6e88828901614e86565b969995985093965092949392505050565b60008060408385031215614f9257600080fd5b823591506020830135614fa481614e61565b809150509250929050565b60008060408385031215614fc257600080fd5b8235614fcd81614e61565b946020939093013593505050565b600060208284031215614fed57600080fd5b5035919050565b60008082840360a081121561500857600080fd5b833561501381614e61565b92506080601f198201121561502757600080fd5b506020830190509250929050565b8015158114610d3757600080fd5b8035614e8181615035565b803563ffffffff81168114614e8157600080fd5b60008083601f84011261507457600080fd5b50813567ffffffffffffffff81111561508c57600080fd5b602083019150836020828501011115611eff57600080fd5b60008060008060008060008060008060006101408c8e0312156150c657600080fd5b8b359a5060208c01356150d881615035565b995060408c01356150e881615035565b985060608c01356150f881615035565b975060808c013561510881615035565b965060a08c013561511881615035565b955061512660c08d01615043565b945061513460e08d01615043565b93506151436101008d0161504e565b92506101208c013567ffffffffffffffff81111561516057600080fd5b61516c8e828f01615062565b915080935050809150509295989b509295989b9093969950565b60006020828403121561519857600080fd5b81356146c481614e61565b60008083601f8401126151b557600080fd5b50813567ffffffffffffffff8111156151cd57600080fd5b602083019150836020606083028501011115611eff57600080fd5b6000806000806000806060878903121561520157600080fd5b863567ffffffffffffffff8082111561521957600080fd5b818901915089601f83011261522d57600080fd5b81358181111561523c57600080fd5b8a60206102808302850101111561525257600080fd5b60209283019850965090880135908082111561526d57600080fd5b6152798a838b016151a3565b9096509450604089013591508082111561529257600080fd5b5061529f89828a016151a3565b979a9699509497509295939492505050565b6000806000806000806000806000806101208b8d0312156152d157600080fd5b8a356152dc81615035565b995060208b01356152ec81615035565b985060408b01356152fc81615035565b975060608b013561530c81615035565b965060808b013561531c81615035565b955060a08b013561532c81615035565b945060c08b013561533c81615035565b935061534a60e08c0161504e565b92506101008b013567ffffffffffffffff81111561536757600080fd5b6153738d828e01615062565b915080935050809150509295989b9194979a5092959850565b634e487b7160e01b600052604160045260246000fd5b604051610280810167ffffffffffffffff811182821017156153d457634e487b7160e01b600052604160045260246000fd5b60405290565b604051610160810167ffffffffffffffff811182821017156153d457634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff811182821017156153d457634e487b7160e01b600052604160045260246000fd5b803560028110614e8157600080fd5b6000610280828403121561545f57600080fd5b6154676153a2565b905061547282615043565b815261548060208301615043565b60208201526154916040830161543d565b60408201526154a260608301614e76565b60608201526154b360808301614e76565b60808201526154c460a08301614e76565b60a08201526154d560c08301614e76565b60c08201526154e660e08301614e76565b60e08201526101006154f9818401614e76565b9082015261012061550b838201614e76565b908201526101408281013590820152610160808301359082015261018080830135908201526101a080830135908201526101c080830135908201526101e080830135908201526102008083013590820152610220808301359082015261024080830135908201526102609182013591810191909152919050565b60006060828403121561559757600080fd5b6040516060810181811067ffffffffffffffff821117156155c857634e487b7160e01b600052604160045260246000fd5b604052905080823560ff811681146155df57600080fd5b8082525060208301356020820152604083013560408201525092915050565b6000806000610340848603121561561457600080fd5b61561e858561544c565b925061562e856102808601615585565b915061563e856102e08601615585565b90509250925092565b6000610160828403121561565a57600080fd5b6156626153da565b905061566d8261543d565b815261567b60208301614e76565b602082015261568c60408301614e76565b604082015261569d60608301614e76565b60608201526156ae60808301614e76565b60808201526156bf60a08301614e76565b60a08201526156d060c08301614e76565b60c082015260e082013560e082015261010080830135818301525061012080830135818301525061014080830135818301525092915050565b60008083601f84011261571b57600080fd5b50813567ffffffffffffffff81111561573357600080fd5b60208301915083602060e083028501011115611eff57600080fd5b60008060008060008587036102a081121561576857600080fd5b6157728888615585565b95506157818860608901615585565b94506101c060bf198201121561579657600080fd5b5061579f61540c565b6157ac8860c08901615647565b81526102208701356157bd81614e61565b602082015261024087013560408201526102608701356060820152925061028086013567ffffffffffffffff8111156157f557600080fd5b614f6e88828901615709565b600080600080600080610200878903121561581b57600080fd5b6158258888615585565b95506158348860608901615647565b94506101c087013567ffffffffffffffff8082111561585257600080fd5b61585e8a838b01615709565b90965094506101e089013591508082111561529257600080fd5b60006101208201905082511515825260208301511515602083015260408301516158a6604084018215159052565b5060608301516158ba606084018215159052565b5060808301516158ce608084018215159052565b5060a08301516158e260a084018215159052565b5060c08301516158f660c084018215159052565b5060e083015161590e60e084018263ffffffff169052565b50610100928301516001600160a01b0316919092015290565b6000806040838503121561593a57600080fd5b823561594581614e61565b91506020830135614fa481614e61565b634e487b7160e01b600052603260045260246000fd5b60006080828403121561597d57600080fd5b6040516080810181811067ffffffffffffffff821117156159ae57634e487b7160e01b600052604160045260246000fd5b60405282356159bc81615035565b815260208301356159cc81615035565b6020820152604083810135908201526060928301359281019290925250919050565b81356159f981615035565b815460ff19811691151560ff1691821783556020840135615a1981615035565b61ffff199190911690911790151560081b61ff001617815560408201356001820155606090910135600290910155565b60006102808284031215615a5c57600080fd5b6146c4838361544c565b600060608284031215615a7857600080fd5b6146c48383615585565b600060e08284031215615a9457600080fd5b60405160e0810181811067ffffffffffffffff82111715615ac557634e487b7160e01b600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c0830135615b0e81614e61565b60c08201529392505050565b634e487b7160e01b600052602160045260246000fd5b600081518084526020808501945080840160005b83811015615b62578151151587529582019590820190600101615b44565b509495945050505050565b600081518084526020808501945080840160005b83811015615b6257815187529582019590820190600101615b81565b60006001600160a01b03808916835280881660208401525060c06040830152615bc960c0830187615b30565b8281036060840152615bdb8187615b6d565b90508281036080840152615bef8186615b6d565b905082810360a0840152615c038185615b6d565b9998505050505050505050565b60006001600160a01b03808816835280871660208401525060a06040830152615c3c60a0830186615b30565b8281036060840152615c4e8186615b6d565b90508281036080840152615c628185615b6d565b98975050505050505050565b600081518084526020808501945080840160005b83811015615b625781516001600160a01b031687529582019590820190600101615c82565b6001600160a01b038716815260c060208201526000615cc960c0830188615b30565b8281036040840152615cdb8188615c6e565b90508281036060840152615bdb8187615b6d565b6001600160a01b038616815260a060208201526000615d1160a0830187615b30565b8281036040840152615d238187615c6e565b90508281036060840152615c4e8186615b6d565b600060208284031215615d4957600080fd5b81516146c481614e61565b600060208284031215615d6657600080fd5b81516146c481615035565b634e487b7160e01b600052601260045260246000fd5b60006101208c151583528b151560208401528a151560408401528915156060840152881515608084015287151560a084015286151560c084015263ffffffff861660e0840152806101008401528381840152506101408385828501376000838501820152601f909301601f19169091019091019a9950505050505050505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115615e3157615e31615e08565b500190565b815160009082906020808601845b83811015615e6057815185529382019390820190600101615e44565b50929695505050505050565b600082615e8957634e487b7160e01b600052601260045260246000fd5b500490565b60005b83811015615ea9578181015183820152602001615e91565b8381111561427c5750506000910152565b60008351615ecc818460208801615e8e565b835190830190615ee0818360208801615e8e565b01949350505050565b60008060408385031215615efc57600080fd5b8251615f0781614e61565b6020939093015192949293505050565b6000816000190483118215151615615f3157615f31615e08565b500290565b60008151808452615f4e816020860160208601615e8e565b601f01601f19169290920160200192915050565b828152604060208201526000614be46040830184615f36565b600060208284031215615f8d57600080fd5b81516146c481614e2e565b60008251615faa818460208701615e8e565b9190910192915050565b6020815260006146c46020830184615f3656fea2646970667358221220208eba2a424cf9d450353832333fa1255369096c9b3808d5d1a44f0d6978725064736f6c63430008090033000000000000000000000000f0e41a1f6e417c0666e3577422297b71ce5455770000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063
Deployed Bytecode
0x6080604052600436106102dc5760003560e01c80636c2be897116101845780639627a039116100d6578063dbcbf11b1161008a578063ed24911d11610064578063ed24911d146109b8578063f2e69c42146109cd578063f2fde38b14610a1857600080fd5b8063dbcbf11b14610858578063e67feac814610983578063ec72573f1461099857600080fd5b8063d3055dde116100bb578063d3055dde1461080f578063d3a5e4a114610822578063d73792a91461084257600080fd5b80639627a039146107dc578063c519e3d7146107fc57600080fd5b80637996eef0116101385780637d26279c116101125780637d26279c146107965780638456cb59146107a95780638da5cb5b146107be57600080fd5b80637996eef0146106fc5780637a2170d51461071c5780637d22c35c1461075057600080fd5b8063715018a611610169578063715018a61461066d578063753d130914610682578063755205e8146106b657600080fd5b80636c2be897146106195780636e80a2591461064d57600080fd5b80632ff3449f1161023d5780634faee3fe116101f15780635ed1f9bb116101cb5780635ed1f9bb146105945780635f3e9f42146105a7578063666c2334146105e557600080fd5b80634faee3fe146104f15780635731737c146105275780635c975abb1461057557600080fd5b8063414ab72711610222578063414ab72714610484578063420dab43146104a457806345253c53146104c457600080fd5b80632ff3449f1461044f5780633f4ba83a1461046f57600080fd5b80631af161cb1161029457806326c6ac301161027957806326c6ac30146103ef57806326ed4aa11461040f5780632f3ba8021461042f57600080fd5b80631af161cb146103ba578063226d4adb146103da57600080fd5b8063138315a3116102c5578063138315a31461033857806316ea5ca8146103585780631a2125cf1461037857600080fd5b806301ffc9a7146102e1578063096ff95d14610316575b600080fd5b3480156102ed57600080fd5b506103016102fc366004614e44565b610a38565b60405190151581526020015b60405180910390f35b34801561032257600080fd5b50610336610331366004614ecb565b610a6f565b005b34801561034457600080fd5b50610336610353366004614f7f565b610c1f565b34801561036457600080fd5b50610336610373366004614faf565b610cb9565b34801561038457600080fd5b506103ac7f80244acca7a02d7199149a3038653fc8cb10ca984341ec429a626fab631e166281565b60405190815260200161030d565b3480156103c657600080fd5b506103366103d5366004614fdb565b610d2c565b3480156103e657600080fd5b50610336610d3a565b3480156103fb57600080fd5b5061033661040a366004614faf565b610d8a565b34801561041b57600080fd5b506103ac61042a366004614faf565b610d9c565b34801561043b57600080fd5b5061033661044a366004614f7f565b610db2565b34801561045b57600080fd5b5061033661046a366004614ff4565b610e4c565b34801561047b57600080fd5b50610336610f31565b34801561049057600080fd5b5061033661049f366004614f7f565b610f43565b3480156104b057600080fd5b506103366104bf3660046150a4565b611008565b3480156104d057600080fd5b506103ac6104df366004615186565b60066020526000908152604090205481565b3480156104fd57600080fd5b506103ac61050c366004615186565b6001600160a01b031660009081526002602052604090205490565b34801561053357600080fd5b5061055d610542366004615186565b6008602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161030d565b34801561058157600080fd5b50600054600160a01b900460ff16610301565b6103366105a23660046151e8565b611031565b3480156105b357600080fd5b506103016105c2366004615186565b6001600160a01b0316600090815260096020526040902054610100900460ff1690565b3480156105f157600080fd5b506103ac7f2008a1ab898fdaa2d8f178bc39e807035d2d6e330dac5e42e913ca727ab5603881565b34801561062557600080fd5b506103ac7f0bc3075778b80a2341ce445063e81924b88d61eb5f21c815e8f9cc824af096d081565b34801561065957600080fd5b506103ac6106683660046152b1565b6111f4565b34801561067957600080fd5b50610336611223565b34801561068e57600080fd5b506103ac7f126520d0bca0cfa7e5852d004cc4335723ce67c638cbd55cd530fe992a089e7b81565b3480156106c257600080fd5b506103016106d1366004614f7f565b60009182526004602090815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561070857600080fd5b506103ac610717366004614faf565b611235565b34801561072857600080fd5b506103ac7fd3f4273db8ff5262b6bc5f6ee07d139463b4f826cce90c05165f63062f3686dc81565b34801561075c57600080fd5b5061030161076b366004614f7f565b60009182526003602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6103366107a43660046155fe565b61124b565b3480156107b557600080fd5b5061033661127c565b3480156107ca57600080fd5b506000546001600160a01b031661055d565b3480156107e857600080fd5b506103366107f7366004614f7f565b61128c565b61033661080a36600461574e565b61132a565b61033661081d366004615801565b61166c565b34801561082e57600080fd5b5061033661083d366004614f7f565b61199c565b34801561084e57600080fd5b506103ac61271081565b34801561086457600080fd5b50610976610873366004614fdb565b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081019190915250600090815260056020908152604091829020825161012081018452905460ff80821615158352610100808304821615159484019490945262010000820481161515948301949094526301000000810484161515606083015264010000000081048416151560808301526501000000000081048416151560a083015266010000000000008104909316151560c0820152600160381b830463ffffffff1660e0820152600160581b9092046001600160a01b03169082015290565b60405161030d9190615878565b34801561098f57600080fd5b506103ac600081565b3480156109a457600080fd5b506103366109b3366004615927565b6119d1565b3480156109c457600080fd5b506103ac611a3e565b3480156109d957600080fd5b506103016109e8366004614faf565b6001600160a01b03919091166000908152600a602090815260408083209383529290522054610100900460ff1690565b348015610a2457600080fd5b50610336610a33366004615186565b611a4d565b60006001600160e01b0319821663306d7a2160e11b1480610a6957506301ffc9a760e01b6001600160e01b03198316145b92915050565b610a7885611ac8565b828114610a985760405163b62503e360e01b815260040160405180910390fd5b82610ab65760405163db560cb560e01b815260040160405180910390fd5b6001600160a01b0385166000908152600a6020526040812090805b85811015610c1557868682818110610aeb57610aeb615955565b9050602002013591506000858583818110610b0857610b08615955565b905060800201803603810190610b1e919061596b565b600084815260208690526040902054909150610100900460ff1615610b565760405163793c666f60e01b815260040160405180910390fd5b806060015181604001511115610b7f5760405163420a69a160e01b815260040160405180910390fd5b60008381526020858152604091829020835181548584015115156101000261ff00199215159290921661ffff199091161717815583830151600182018190556060850151600290920182905583519081529182015284916001600160a01b038c16917f38d88037c7f872f6e5d89332cdae804370cd604776bfcabf8da1f2e11945e271910160405180910390a350600101610ad1565b5050505050505050565b610c2882611c0f565b60008281526003602090815260408083206001600160a01b0385168452918290529091205460ff16610c6d5760405163a935ea0b60e01b815260040160405180910390fd5b6001600160a01b038216600081815260208390526040808220805460ff191690555185917f0aa5e1c56725fc01d0a61fc7302ff0201516b9af2b7261b4ecbea2f74611b5d191a3505050565b610cc282611ac8565b600154811115610ce557604051631797d38360e21b815260040160405180910390fd5b6001600160a01b038216600081815260026020526040808220849055518392917f8a2e423ccab4754dc61747d26d19bc14c55577d5fcc54b4a67d9b82a016b61df91a35050565b610d37816000611c56565b50565b3360008181526006602052604080822054905190917fb06d2760711c1c15c05bc011b1009a36c0713c6d63567c267678c3a382188b6191a333600090815260066020526040902080546001019055565b610d978233836001611ce0565b505050565b600080610da98484611e0f565b95945050505050565b610dbb82611c0f565b60008281526004602090815260408083206001600160a01b0385168452918290529091205460ff16610e005760405163ced71fff60e01b815260040160405180910390fd5b6001600160a01b038216600081815260208390526040808220805460ff191690555185917f24dced5d5e85a1733ad613a53ada041ecc410cca5ee598e3115b67d4a2525e3891a3505050565b610e5582611ac8565b6001600160a01b038216600090815260096020526040902054610100900460ff1615610e945760405163793c666f60e01b815260040160405180910390fd5b806060013581604001351115610ebd5760405163420a69a160e01b815260040160405180910390fd5b6001600160a01b03821660009081526009602052604090208190610ee182826159ee565b505060408051818301358152606083013560208201526001600160a01b038416917fdd61e240b8302b21ad48e3bec0f6e9538c9e4cfffdfde6d604963069d7e23c34910160405180910390a25050565b610f39611f06565b610f41611f60565b565b610f4c82611c0f565b6001600160a01b038116610f7357604051637a79ae6b60e11b815260040160405180910390fd5b60008281526003602090815260408083206001600160a01b0385168452918290529091205460ff1615610fb95760405163467d57a760e11b815260040160405180910390fd5b6001600160a01b038216600081815260208390526040808220805460ff191660011790555185917f3286c4e8704920b56173a2f9884345d5f5b90893a15dce75abc157df4081af5f91a3505050565b6110118b611c0f565b6110248b8b8b8b8b8b8b8b8b8b8b611fb5565b5050505050505050505050565b61103961219c565b84831415806110485750848114155b156110665760405163b62503e360e01b815260040160405180910390fd5b846110845760405163db560cb560e01b815260040160405180910390fd5b3461108d614d56565b6040805160608082018352600080835260208084018290528385018290528451928301855281835282018190529281018390529091805b8a8110156111d4578b8b828181106110de576110de615955565b905061028002018036038101906110f59190615a49565b945089898281811061110957611109615955565b90506060020180360381019061111f9190615a66565b935087878281811061113357611133615955565b9050606002018036038101906111499190615a66565b6060860151909350600092506001600160a01b03166111be57846101e0015191508186101561118b5760405163386ad99760e11b815260040160405180910390fd5b818603955061119c828686866121f6565b6111b95760405163f40863ff60e01b815260040160405180910390fd5b6111cc565b6111ca828686866121f6565b505b6001016110c4565b508415611024576040516315a53e4560e31b815260040160405180910390fd5b60018054810190819055600090611214818d8d8d8d8d8d8d8d8d8d611fb5565b9b9a5050505050505050505050565b61122b611f06565b610f4160006128e6565b6000806112428484611e0f565b50949350505050565b61125361219c565b61125f348484846121f6565b610d975760405163f40863ff60e01b815260040160405180910390fd5b611284611f06565b610f41612943565b61129582611c0f565b60008281526004602090815260408083206001600160a01b0385168452918290529091205460ff16156112db57604051637f622a5960e01b815260040160405180910390fd5b6001600160a01b038216600081815260208390526040808220805460ff191660011790555185917fbb1b20966aa1c5d6ce073b9c8bf92e61bc7637cfa60464b83d2be54b7fe11eb391a3505050565b61133261219c565b806113505760405163db560cb560e01b815260040160405180910390fd5b82516040908101516001600160a01b0316600090815260026020908152828220548083526005825283832084516001808252818701909652919490939282015b604080516060810182526000808252602080830182905292820152825260001990920191018161139057905050905087816000815181106113d3576113d3615955565b60200260200101819052506000806114416000858a8a8a808060200260200160405190810160405280939291908181526020016000905b828210156114365761142760e08302860136819003810190615a82565b8152602001906001019061140a565b505050505087612986565b9150915061145685858a60000151858d6132a0565b6040805160a08082019092528554600160381b900463ffffffff1681528951909101516000916115249160208201906001600160a01b03161561149e578b5160a001516114a5565b8b51608001515b6001600160a01b0390811682528c516020908101518216818401528d51015160409092019116156114d8576135a56114dc565b6135b15b67ffffffffffffffff16815260200160018c5151600181111561150157611501615b1a565b1461150e576135bc611512565b61363c5b67ffffffffffffffff16905283613692565b90506001895151600181111561153c5761153c615b1a565b14156115d6578860000151602001516001600160a01b03168960000151604001516001600160a01b03168a6000015160c001516001600160a01b03167f4b761d38cae19a364a5d44d2c4a5cdd41113f9e4d64ae2e21b766d072705b9318c60000151608001518d602001518689600001518a602001518b604001516040516115c996959493929190615b9d565b60405180910390a4611024565b8860000151602001516001600160a01b03168960000151604001516001600160a01b03168a6000015160c001516001600160a01b03167ff5960c81abf2cbc811a3b86b2b2c0338bfd5c47ad8815c941f9d59665a8d458b8c60000151608001518d602001518689600001518a60400151604051611657959493929190615c10565b60405180910390a45050505050505050505050565b61167461219c565b8281146116945760405163b62503e360e01b815260040160405180910390fd5b826116b25760405163db560cb560e01b815260040160405180910390fd5b6000806116e787604001516001600160a01b031660009081526002602090815260408083205480845260059092529091209091565b915091506000806117cc60018460405180608001604052808d815260200160006001600160a01b031681526020016000815260200160008152508b8b808060200260200160405190810160405280939291908181526020016000905b8282101561176f5761176060e08302860136819003810190615a82565b81526020019060010190611743565b50505050508a8a808060200260200160405190810160405280939291908181526020016000905b828210156117c2576117b360608302860136819003810190615a66565b81526020019060010190611796565b5050505050612986565b915091506117dd84848b858e6132a0565b6040805160a08082019092528454600160381b900463ffffffff168152908a01516000916118979160208201906001600160a01b031615611822578c60a00151611828565b8c608001515b6001600160a01b031681526020018c602001516001600160a01b0316815260200160006001600160a01b03168d602001516001600160a01b03161461186f576135a5611873565b6135b15b67ffffffffffffffff16815260200160018d51600181111561150157611501615b1a565b905060018a5160018111156118ae576118ae615b1a565b141561192b5789602001516001600160a01b03168a604001516001600160a01b03168b60c001516001600160a01b03167f35cd37c73a78d0322074e1324a7d5d4cf5c7ff21f3265d03f4d085c532c6f0198d6080015185886080015189600001518a602001518b604001516040516115c996959493929190615ca7565b89602001516001600160a01b03168a604001516001600160a01b03168b60c001516001600160a01b03167f8435e05433e0d3a3fe612b10c36f6623deec79239f76721a154687fef0ca46a18d6080015185886080015189600001518a60400151604051611657959493929190615cef565b6001600160a01b0381166119c357604051632949de9560e01b815260040160405180910390fd5b6119cd8282611c56565b5050565b6119da82611ac8565b6001600160a01b03828116600081815260086020526040808220805473ffffffffffffffffffffffffffffffffffffffff19169486169485179055517f53ab061e9517daf6849d4bde07950e3d199f73115c2e4842a8b20a62e83abd1c9190a35050565b6000611a48613a10565b905090565b611a55611f06565b6001600160a01b038116611abf5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b610d37816128e6565b336001600160a01b0382161480611bf157816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b1257600080fd5b505afa925050508015611b42575060408051601f3d908101601f19168201909252611b3f91810190615d37565b60015b611b4b57611b59565b6001600160a01b0316331490505b80611bf1576001600160a01b0382166391d148546000336040516001600160e01b031960e085901b16815260048101929092526001600160a01b0316602482015260440160206040518083038186803b158015611bb557600080fd5b505afa925050508015611be5575060408051601f3d908101601f19168201909252611be291810190615d54565b60015b611bee57611bf1565b90505b806119cd576040516380a6c4af60e01b815260040160405180910390fd5b600081815260056020526040902054600160581b90046001600160a01b0316336001600160a01b031614610d3757604051638d1a2f3760e01b815260040160405180910390fd5b611c5f82611c0f565b60008281526005602052604080822080546001600160a01b03858116600160581b8181027fff0000000000000000000000000000000000000000ffffffffffffffffffffff851617855594519395949092041692909183917f195d9a13f822aeb682fa730ba46c3e3e6103134a536f98e5c40c81cc004f0a8491a350505050565b6040516bffffffffffffffffffffffff19606086811b8216602084015285901b16603482015260009081906007908290604801604051602081830303815290604052805190602001208152602001908152602001600020905060006101008581611d4c57611d4c615d71565b0460008181526020849052604090205490915060ff861690600181831c81161415611d8a5760405163015236d560e61b815260040160405180910390fd5b60009283526020849052604092839020600190921b179055516001600160a01b03808816919087169086907f61b992b9cb8061087d0e50532a8ba94e22379c7edd39cdb465536ef827dc1be790611de690881515815260200190565b60405180910390a4505050506001600160a01b0316600090815260066020526040902054919050565b6001600160a01b0382166000908152600a6020908152604080832084845282528083208151608081018352815460ff8082161580158452610100909204161515948201949094526001820154928101929092526002015460608201528291611e8557806040015181606001519250925050611eff565b6001600160a01b0385166000908152600960209081526040918290208251608081018452815460ff808216158015845261010090920416151593820193909352600182015493810193909352600201546060830152611ef35780604001518160600151935093505050611eff565b50600060001992509250505b9250929050565b6000546001600160a01b03163314610f415760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611ab6565b611f68613afe565b6000805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6040518061012001604052808b151581526020018a15158152602001891515815260200188151581526020018715158152602001861515815260200185151581526020018463ffffffff16815260200161200c3390565b6001600160a01b0390811690915260008d8152600560209081526040918290208451815492860151868501516060880151608089015160a08a015160c08b015160e08c01516101009c8d015161ffff19909a1697151561ff00191697909717951515909b029490941763ffff00001916620100009315159390930263ff0000001916929092176301000000911515919091021765ffff0000000019166401000000009115159190910265ff00000000001916176501000000000091151591909102176affffffffff00000000000019166601000000000000961515969096026affffffff00000000000000191695909517600160381b63ffffffff90961695909502949094177fff0000000000000000000000000000000000000000ffffffffffffffffffffff16600160581b919093160291909117909155518b907ffa0f19ecb97e973eefa78c4ef4f6be467d4e0d320b88fa6b3e785f09df7089f690612187908d908d908d908d908d908d908d908d908d908d90615d87565b60405180910390a25050505050505050505050565b600054600160a01b900460ff1615610f415760405162461bcd60e51b815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152606401611ab6565b6080808401516001600160a01b0390811660009081526002602090815260408083205480845260058352818420825161012081018452905460ff80821615158352610100808304821615159684019690965262010000820481161515948301949094526301000000810484161515606080840191909152640100000000820485161515988301989098526501000000000081048416151560a083015266010000000000008104909316151560c082015263ffffffff600160381b84041660e0820152600160581b90920485169282019290925293870151919390929091166123395786866101e00151146122fd57604051630db5f82b60e21b815260040160405180910390fd5b855180612316575060a08601516001600160a01b031632145b1561233457604051632d8457d960e21b815260040160405180910390fd5b612375565b861561235857604051635d6c7e8160e01b815260040160405180910390fd5b612375828260200151836040015189608001518a60600151613b57565b60018660400151600181111561238d5761238d615b1a565b14156123bb576102608601516123b6576040516326db27f160e01b815260040160405180910390fd5b6123e1565b6001866102600151146123e157604051636d9e53cd60e11b815260040160405180910390fd5b8561020001514211156124075760405163099465a960e41b815260040160405180910390fd5b85610220015142111561242d5760405163026de79960e21b815260040160405180910390fd5b856101c00151866101e00151101561245857604051636769dcf160e11b815260040160405180910390fd5b6127108661016001518761014001516124719190615e1e565b1115612490576040516332a7479560e21b815260040160405180910390fd5b60c08601516001600160a01b031615612500578560c001516001600160a01b03168660e001516001600160a01b0316146124dd5760405163185ff71160e21b815260040160405180910390fd5b8060600151156125005760405163646c1dcd60e11b815260040160405180910390fd5b6101008601516001600160a01b03161561256e576101008601516001600160a01b0316336001600160a01b03161461254b576040516390158e4760e01b815260040160405180910390fd5b80608001511561256e576040516358f8e8a560e01b815260040160405180910390fd5b8060a00151156125d25760a08601516001600160a01b03163b156125a55760405163321e0c1560e11b815260040160405180910390fd5b60e08601516001600160a01b03163b156125d25760405163321e0c1560e11b815260040160405180910390fd5b8051156126635733321461261f57600082815260036020908152604080832033845290915290205460ff1661261a576040516329837f1160e21b815260040160405180910390fd5b612663565b8060c001511561266357600082815260036020908152604080832033845290915290205460ff1661266357604051631d4ca04b60e11b815260040160405180910390fd5b8060400151156126dc5760608601516001600160a01b03166126bd5760808601516001600160a01b0390811660009081526008602052604090205416156126bd576040516305a3b2ed60e41b815260040160405180910390fd5b6126dc8660800151876102400151886102600151896101e00151613be8565b6126e68686613c52565b8560200151156126ff576126fa8685613e48565b612709565b6127098685613fef565b604080516001808252818301909252600091816020015b612728614d56565b815260200190600190039081612720579050509050868160008151811061275157612751615955565b602002602001018190525060006128066040518060a001604052808560e0015163ffffffff16815260200160006001600160a01b03168b61010001516001600160a01b0316146127a6578a61010001516127ac565b8a60e001515b6001600160a01b03908116825260608c018051821660208401525160409092019116156127db576135a56127df565b6135b15b67ffffffffffffffff16815260200160018b60400151600181111561150157611501615b1a565b90508060008151811061281b5761281b615955565b602002602001015115945084156128da5787606001516001600160a01b031688608001516001600160a01b03168961012001516001600160a01b03167f7ed668b30822ae5c7db7b4a32f84e6645250bb6db0d1fc73eeb484c5b34b1d1b8b60e001518c60a001518d61024001518e61026001518f6101e001516040516128d19594939291906001600160a01b03958616815293909416602084015260408301919091526060820152608081019190915260a00190565b60405180910390a45b50505050949350505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b61294b61219c565b6000805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258611f983390565b6129bf6040518060c001604052806060815260200160608152602001606081526020016060815260200160608152602001600081525090565b6060835167ffffffffffffffff8111156129db576129db61538c565b604051908082528060200260200182016040528015612a1457816020015b612a01614d56565b8152602001906001900390816129f95790505b5090506040518060c00160405280855167ffffffffffffffff811115612a3c57612a3c61538c565b604051908082528060200260200182016040528015612a65578160200160208202803683370190505b508152602001855167ffffffffffffffff811115612a8557612a8561538c565b604051908082528060200260200182016040528015612aae578160200160208202803683370190505b508152602001855167ffffffffffffffff811115612ace57612ace61538c565b604051908082528060200260200182016040528015612af7578160200160208202803683370190505b508152602001855167ffffffffffffffff811115612b1757612b1761538c565b604051908082528060200260200182016040528015612b40578160200160208202803683370190505b508152602001855167ffffffffffffffff811115612b6057612b6061538c565b604051908082528060200260200182016040528015612b89578160200160208202803683370190505b5081526020016000815250915060005b84518110156130c8576020860151604087015160608801518a15612c1857878481518110612bc957612bc9615955565b602002602001015160c001519250878481518110612be957612be9615955565b6020026020010151608001519150878481518110612c0957612c09615955565b602002602001015160a0015190505b60408051610280810182526000808252602082018190528b515190928201906001811115612c4857612c48615b1a565b81526020018b60000151602001516001600160a01b031681526020018b60000151604001516001600160a01b03168152602001856001600160a01b031681526020018b60000151606001516001600160a01b031681526020018b60000151608001516001600160a01b031681526020018b6000015160a001516001600160a01b031681526020018b6000015160c001516001600160a01b031681526020018b6000015160e0015181526020018a8781518110612d0657612d06615955565b60200260200101516040015181526020018481526020018b60000151610100015181526020018a8781518110612d3e57612d3e615955565b60200260200101516060015181526020018a8781518110612d6157612d61615955565b60200260200101516060015181526020018381526020018b60000151610140015181526020018a8781518110612d9957612d99615955565b60200260200101516000015181526020018a8781518110612dbc57612dbc615955565b602002602001015160200151815250905080868681518110612de057612de0615955565b602002602001018190525080610240015187600001518681518110612e0757612e07615955565b60200260200101818152505080610260015187602001518681518110612e2f57612e2f615955565b602002602001018181525050806101c0015187604001518681518110612e5757612e57615955565b60200260200101818152505080610160015187606001518681518110612e7f57612e7f615955565b6020026020010181815250508060a0015187608001518681518110612ea657612ea6615955565b60200260200101906001600160a01b031690816001600160a01b031681525050806101c001518760a001818151612edd9190615e1e565b905250600181604001516001811115612ef857612ef8615b1a565b1415612f2657610260810151612f21576040516326db27f160e01b815260040160405180910390fd5b612f4c565b600181610260015114612f4c57604051636d9e53cd60e11b815260040160405180910390fd5b612710816101600151826101400151612f659190615e1e565b1115612f84576040516332a7479560e21b815260040160405180910390fd5b8a5462010000900460ff1615612fb357612fb38160800151826102400151836102600151846101e00151613be8565b8b156130b957806102000151421115612fdf5760405163099465a960e41b815260040160405180910390fd5b60c08101516001600160a01b031615613056578060c001516001600160a01b03168160e001516001600160a01b03161461302c5760405163185ff71160e21b815260040160405180910390fd5b8a546301000000900460ff16156130565760405163646c1dcd60e11b815260040160405180910390fd5b8a5465010000000000900460ff16156130965760a08101516001600160a01b03163b156130965760405163321e0c1560e11b815260040160405180910390fd5b6130b9818987815181106130ac576130ac615955565b6020026020010151613c52565b84600101945050505050612b99565b50866132965784606001514211156130f35760405163099465a960e41b815260040160405180910390fd5b8451606001516001600160a01b03161561316957845160608101516080909101516001600160a01b0390811691161461313f5760405163185ff71160e21b815260040160405180910390fd5b85546301000000900460ff16156131695760405163646c1dcd60e11b815260040160405180910390fd5b855465010000000000900460ff16156131a95760208501516001600160a01b03163b156131a95760405163321e0c1560e11b815260040160405180910390fd5b613296604051806080016040528084600001516040516020016131cc9190615e36565b60405160208183030381529060405280519060200120815260200184602001516040516020016131fc9190615e36565b604051602081830303815290604052805190602001208152602001846060015160405160200161322c9190615e36565b604051602081830303815290604052805190602001208152602001846040015160405160200161325c9190615e36565b60405160208183030381529060405280519060200120815250868560008151811061328957613289615955565b60200260200101516140c9565b9550959350505050565b60208301516001600160a01b0316156133015734156132d257604051635d6c7e8160e01b815260040160405180910390fd5b8354604084015160208501516132fc92889260ff6101008304811693620100009093041691613b57565b613375565b826101200151341461332657604051630db5f82b60e21b815260040160405180910390fd5b835462010000900460ff1615613375576040808401516001600160a01b039081166000908152600860205291909120541615613375576040516305a3b2ed60e41b815260040160405180910390fd5b82610140015142111561339b5760405163026de79960e21b815260040160405180910390fd5b60a08301516001600160a01b03161561340f5760a08301516001600160a01b0316336001600160a01b0316146133e4576040516390158e4760e01b815260040160405180910390fd5b8354640100000000900460ff161561340f576040516358f8e8a560e01b815260040160405180910390fd5b835465010000000000900460ff161561344f5760808301516001600160a01b03163b1561344f5760405163321e0c1560e11b815260040160405180910390fd5b835460ff16156134ed5733321461349f57600085815260036020908152604080832033845290915290205460ff1661349a576040516329837f1160e21b815260040160405180910390fd5b6134ed565b83546601000000000000900460ff16156134ed57600085815260036020908152604080832033845290915290205460ff166134ed57604051631d4ca04b60e11b815260040160405180910390fd5b8261012001518260a001511461351657604051637867d96760e11b815260040160405180910390fd5b815160405161359e9161352b91602001615e36565b6040516020818303038152906040528051906020012083602001516040516020016135569190615e36565b6040516020818303038152906040528051906020012084604001516040516020016135819190615e36565b604051602081830303815290604052805190602001208685614282565b5050505050565b61359e83858785614436565b61359e8583836144a5565b6040516323b872dd60e01b81526001600160a01b038681166004830152858116602483015260448201849052600091908516906323b872dd906064015b600060405180830381600087803b15801561361357600080fd5b505af1925050508015613624575060015b61363057506000610da9565b50600195945050505050565b604051637921219560e11b81526001600160a01b0386811660048301528581166024830152604482018490526064820183905260a06084830152600060a48301819052919085169063f242432a9060c4016135f9565b6060815167ffffffffffffffff8111156136ae576136ae61538c565b6040519080825280602002602001820160405280156136d7578160200160208202803683370190505b506040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081018290529192505b835181101561396f57600084828151811061372a5761372a615955565b6020026020010151905060006137618260a001518360e0015184608001518561024001518661026001518c6080015163ffffffff16565b9050806137bc5760408701516001600160a01b03166137935760405163f40863ff60e01b815260040160405180910390fd5b60018584815181106137a7576137a7615955565b91151560209283029190910190910152613965565b60006137e9836101e0015184608001518561024001518661012001518761014001518861016001516144d1565b905084604001516001600160a01b031681600001516001600160a01b0316146138575760a08501511561383f5761383f856040015189602001518a604001518860a001518c600001518d6060015163ffffffff16565b80516001600160a01b03166040860152600060a08601525b84602001516001600160a01b03168361012001516001600160a01b0316146138c8576080850151156138ac576138ac856020015189602001518a6040015188608001518c600001518d6060015163ffffffff16565b6101208301516001600160a01b03166020860152600060808601525b84600001516001600160a01b03168360a001516001600160a01b0316146139345760608501511561391c5761391c856000015189602001518a6040015188606001518c600001518d6060015163ffffffff16565b60a08301516001600160a01b03168552600060608601525b602081015160a086018051909101905260408101516080860180519091019052606090810151908501805190910190525b505060010161370d565b5060a0810151156139a3576139a38160400151856020015186604001518460a001518860000151896060015163ffffffff16565b6080810151156139d6576139d681602001518560200151866040015184608001518860000151896060015163ffffffff16565b606081015115613a0957613a0981600001518560200151866040015184606001518860000151896060015163ffffffff16565b5092915050565b6000306001600160a01b037f000000000000000000000000009a1d0fecd7d6475188082f3f542e93f5e07ff116148015613a6957507f000000000000000000000000000000000000000000000000000000000000008946145b15613a9357507faab6e2046a71a5ed4e951896e170a777a45a3187172ff2e829a45b9e3caf9ef590565b611a487f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f7fdab569368da3525b394950b18252b2a008851cf1162b59295579c87c377905267fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6614681565b600054600160a01b900460ff16610f415760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401611ab6565b8215613b9f576001600160a01b03828116600090815260086020526040902054811690821614613b9a576040516355ce006f60e11b815260040160405180910390fd5b61359e565b831561359e5760008581526004602090815260408083206001600160a01b038516845290915290205460ff1661359e576040516355ce006f60e11b815260040160405180910390fd5b6000613bf48383615e6c565b9050600080613c038787611e0f565b9150915081831015613c285760405163024c625160e61b815260040160405180910390fd5b80831115613c4957604051639837ddd760e01b815260040160405180910390fd5b50505050505050565b6000613dd57fd3f4273db8ff5262b6bc5f6ee07d139463b4f826cce90c05165f63062f3686dc60001b84604001516001811115613c9157613c91615b1a565b855161012087015161014088015161016089015160c08a0151604051613cfa979695949392919060200196875260ff95909516602087015292151560408601526001600160a01b039182166060860152608085015260a08401919091521660c082015260e00190565b60408051601f1981840301815291905260a085015160808601516102408701516102608801516101c08901516102008a01516101808b01516101208c0151613d459088836000611ce0565b6060808e0151604080516001600160a01b039b8c166020820152998b16908a015290880196909652608087019490945260a086019290925260c085015260e084015261010083015291909116610120820152610140015b60408051601f1981840301815290829052613dba9291602001615eba565b604051602081830303815290604052805190602001206146cb565b60a08401519091506001600160a01b03163b15613dfb57610d978360a001518284614719565b613e1381836000015184602001518560400151614833565b6001600160a01b03168360a001516001600160a01b031614610d97576040516312a0f2db60e11b815260040160405180910390fd5b6000613f7c7f0bc3075778b80a2341ce445063e81924b88d61eb5f21c815e8f9cc824af096d060001b84604001516001811115613e8757613e87615b1a565b6020808701516101208801516101408901516101008a015160e08b015160808c01516102608d01516101e08e0151604051613f159b9a9901998a5260ff9890981660208a015295151560408901526001600160a01b039485166060890152608088019390935290831660a0870152821660c08601521660e08401526101008301526101208201526101400190565b604051602081830303815290604052846102200151856101a00151613f4b8761012001518860e00151896101a001516000611ce0565b6060808901516040805160208101969096528501939093528301526001600160a01b0316608082015260a001613d9c565b60e08401519091506001600160a01b03163b15613fa257610d978360e001518284614719565b613fba81836000015184602001518560400151614833565b6001600160a01b03168360e001516001600160a01b031614610d97576040516320af217960e01b815260040160405180910390fd5b6000613f7c7f2008a1ab898fdaa2d8f178bc39e807035d2d6e330dac5e42e913ca727ab5603860001b8460400151600181111561402e5761402e615b1a565b8561012001518661014001518761010001518860e0015189608001518a61024001518b61026001518c6101e00151604051602001613f159a99989796959493929190998a5260ff9890981660208a01526001600160a01b0396871660408a01526060890195909552928516608088015290841660a087015290921660c085015260e08401919091526101008301526101208201526101400190565b815151600090614204907f80244acca7a02d7199149a3038653fc8cb10ca984341ec429a626fab631e166290600181111561410657614106615b1a565b855160c081015160e082015160608301516020808b0151604095860151955161416e98979691920196875260ff9590951660208701526001600160a01b039384166040870152606086019290925282166080850152811660a08401521660c082015260e00190565b60408051601f19818403018152918152606086015190860151865160c00151602088015161419f9190836000611ce0565b87516020908101518a518b8301516040808e015160608f01519151613d9c9998979691929101978852602088019690965260408701949094526001600160a01b03929092166060860152608085015260a084015260c083015260e08201526101000190565b60208401519091506001600160a01b03163b1561422f5761422a83602001518284614719565b61427c565b61424781836000015184602001518560400151614833565b6001600160a01b031683602001516001600160a01b03161461427c576040516312a0f2db60e11b815260040160405180910390fd5b50505050565b81516000906143b6907f126520d0bca0cfa7e5852d004cc4335723ce67c638cbd55cd530fe992a089e7b9060018111156142be576142be615b1a565b8560c001518660e001518760a00151886080015189604001518a610120015160405160200161433698979695949392919097885260ff9690961660208801526001600160a01b03948516604088015260608701939093529083166080860152821660a08501521660c083015260e08201526101000190565b60405160208183030381529060405284610140015185610100015161436b8760c0015188608001518961010001516000611ce0565b60208881015160408051928301959095529381019290925260608201526001600160a01b03909116608082015260a0810189905260c0810188905260e0810187905261010001613d9c565b60808401519091506001600160a01b03163b156143e1576143dc83608001518284614719565b61442e565b6143f981836000015184602001518560400151614833565b6001600160a01b031683608001516001600160a01b03161461442e576040516320af217960e01b815260040160405180910390fd5b505050505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166323b872dd60e01b17905261427c90859061485b565b6000806000806000868887f190508061427c5760405163364cc69f60e11b815260040160405180910390fd5b614505604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6060810187905260405163152a902d60e11b815260048101869052602481018890526001600160a01b03871690632a55205a90604401604080518083038186803b15801561455257600080fd5b505afa925050508015614582575060408051601f3d908101601f1916820190925261457f91810190615ee9565b60015b6145bc573d8080156145b0576040519150601f19603f3d011682016040523d82523d6000602084013e6145b5565b606091505b505061462d565b6001600160a01b0382166145ce575060005b801561462a576127106145e1858b615f17565b6145eb9190615e6c565b81111561460b576040516306f6f23d60e21b815260040160405180910390fd5b6001600160a01b03821683526020830181905260608301805182900390525b50505b6001600160a01b038416614642576000614659565b61271061464f8489615f17565b6146599190615e6c565b60408201819052156146775760408101516060820180519190910390525b9695505050505050565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090505b9392505050565b6000610a696146d8613a10565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6000836001600160a01b0316631626ba7e8484602001518560400151866000015160405160200161478293929190928352602083019190915260f81b7fff0000000000000000000000000000000000000000000000000000000000000016604082015260410190565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016147ae929190615f62565b60206040518083038186803b1580156147c657600080fd5b505afa9250505080156147f6575060408051601f3d908101601f191682019092526147f391810190615f7b565b60015b6147ff57614815565b6001600160e01b031916630b135d3f60e11b1490505b8061427c576040516307c1d80160e51b815260040160405180910390fd5b60008060006148448787878761492d565b9150915061485181614a1a565b5095945050505050565b60006148b0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614bd59092919063ffffffff16565b805190915015610d9757808060200190518101906148ce9190615d54565b610d975760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401611ab6565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156149645750600090506003614a11565b8460ff16601b1415801561497c57508460ff16601c14155b1561498d5750600090506004614a11565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156149e1573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116614a0a57600060019250925050614a11565b9150600090505b94509492505050565b6000816004811115614a2e57614a2e615b1a565b1415614a375750565b6001816004811115614a4b57614a4b615b1a565b1415614a995760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401611ab6565b6002816004811115614aad57614aad615b1a565b1415614afb5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401611ab6565b6003816004811115614b0f57614b0f615b1a565b1415614b685760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401611ab6565b6004816004811115614b7c57614b7c615b1a565b1415610d375760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401611ab6565b6060614be48484600085614bec565b949350505050565b606082471015614c4d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401611ab6565b6001600160a01b0385163b614ca45760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611ab6565b600080866001600160a01b03168587604051614cc09190615f98565b60006040518083038185875af1925050503d8060008114614cfd576040519150601f19603f3d011682016040523d82523d6000602084013e614d02565b606091505b5091509150614d12828286614d1d565b979650505050505050565b60608315614d2c5750816146c4565b825115614d3c5782518084602001fd5b8160405162461bcd60e51b8152600401611ab69190615fb4565b60408051610280810182526000808252602082018190529091820190815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160e01b031981168114610d3757600080fd5b600060208284031215614e5657600080fd5b81356146c481614e2e565b6001600160a01b0381168114610d3757600080fd5b8035614e8181614e61565b919050565b60008083601f840112614e9857600080fd5b50813567ffffffffffffffff811115614eb057600080fd5b6020830191508360208260071b8501011115611eff57600080fd5b600080600080600060608688031215614ee357600080fd5b8535614eee81614e61565b9450602086013567ffffffffffffffff80821115614f0b57600080fd5b818801915088601f830112614f1f57600080fd5b813581811115614f2e57600080fd5b8960208260051b8501011115614f4357600080fd5b602083019650809550506040880135915080821115614f6157600080fd5b50614f6e88828901614e86565b969995985093965092949392505050565b60008060408385031215614f9257600080fd5b823591506020830135614fa481614e61565b809150509250929050565b60008060408385031215614fc257600080fd5b8235614fcd81614e61565b946020939093013593505050565b600060208284031215614fed57600080fd5b5035919050565b60008082840360a081121561500857600080fd5b833561501381614e61565b92506080601f198201121561502757600080fd5b506020830190509250929050565b8015158114610d3757600080fd5b8035614e8181615035565b803563ffffffff81168114614e8157600080fd5b60008083601f84011261507457600080fd5b50813567ffffffffffffffff81111561508c57600080fd5b602083019150836020828501011115611eff57600080fd5b60008060008060008060008060008060006101408c8e0312156150c657600080fd5b8b359a5060208c01356150d881615035565b995060408c01356150e881615035565b985060608c01356150f881615035565b975060808c013561510881615035565b965060a08c013561511881615035565b955061512660c08d01615043565b945061513460e08d01615043565b93506151436101008d0161504e565b92506101208c013567ffffffffffffffff81111561516057600080fd5b61516c8e828f01615062565b915080935050809150509295989b509295989b9093969950565b60006020828403121561519857600080fd5b81356146c481614e61565b60008083601f8401126151b557600080fd5b50813567ffffffffffffffff8111156151cd57600080fd5b602083019150836020606083028501011115611eff57600080fd5b6000806000806000806060878903121561520157600080fd5b863567ffffffffffffffff8082111561521957600080fd5b818901915089601f83011261522d57600080fd5b81358181111561523c57600080fd5b8a60206102808302850101111561525257600080fd5b60209283019850965090880135908082111561526d57600080fd5b6152798a838b016151a3565b9096509450604089013591508082111561529257600080fd5b5061529f89828a016151a3565b979a9699509497509295939492505050565b6000806000806000806000806000806101208b8d0312156152d157600080fd5b8a356152dc81615035565b995060208b01356152ec81615035565b985060408b01356152fc81615035565b975060608b013561530c81615035565b965060808b013561531c81615035565b955060a08b013561532c81615035565b945060c08b013561533c81615035565b935061534a60e08c0161504e565b92506101008b013567ffffffffffffffff81111561536757600080fd5b6153738d828e01615062565b915080935050809150509295989b9194979a5092959850565b634e487b7160e01b600052604160045260246000fd5b604051610280810167ffffffffffffffff811182821017156153d457634e487b7160e01b600052604160045260246000fd5b60405290565b604051610160810167ffffffffffffffff811182821017156153d457634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff811182821017156153d457634e487b7160e01b600052604160045260246000fd5b803560028110614e8157600080fd5b6000610280828403121561545f57600080fd5b6154676153a2565b905061547282615043565b815261548060208301615043565b60208201526154916040830161543d565b60408201526154a260608301614e76565b60608201526154b360808301614e76565b60808201526154c460a08301614e76565b60a08201526154d560c08301614e76565b60c08201526154e660e08301614e76565b60e08201526101006154f9818401614e76565b9082015261012061550b838201614e76565b908201526101408281013590820152610160808301359082015261018080830135908201526101a080830135908201526101c080830135908201526101e080830135908201526102008083013590820152610220808301359082015261024080830135908201526102609182013591810191909152919050565b60006060828403121561559757600080fd5b6040516060810181811067ffffffffffffffff821117156155c857634e487b7160e01b600052604160045260246000fd5b604052905080823560ff811681146155df57600080fd5b8082525060208301356020820152604083013560408201525092915050565b6000806000610340848603121561561457600080fd5b61561e858561544c565b925061562e856102808601615585565b915061563e856102e08601615585565b90509250925092565b6000610160828403121561565a57600080fd5b6156626153da565b905061566d8261543d565b815261567b60208301614e76565b602082015261568c60408301614e76565b604082015261569d60608301614e76565b60608201526156ae60808301614e76565b60808201526156bf60a08301614e76565b60a08201526156d060c08301614e76565b60c082015260e082013560e082015261010080830135818301525061012080830135818301525061014080830135818301525092915050565b60008083601f84011261571b57600080fd5b50813567ffffffffffffffff81111561573357600080fd5b60208301915083602060e083028501011115611eff57600080fd5b60008060008060008587036102a081121561576857600080fd5b6157728888615585565b95506157818860608901615585565b94506101c060bf198201121561579657600080fd5b5061579f61540c565b6157ac8860c08901615647565b81526102208701356157bd81614e61565b602082015261024087013560408201526102608701356060820152925061028086013567ffffffffffffffff8111156157f557600080fd5b614f6e88828901615709565b600080600080600080610200878903121561581b57600080fd5b6158258888615585565b95506158348860608901615647565b94506101c087013567ffffffffffffffff8082111561585257600080fd5b61585e8a838b01615709565b90965094506101e089013591508082111561529257600080fd5b60006101208201905082511515825260208301511515602083015260408301516158a6604084018215159052565b5060608301516158ba606084018215159052565b5060808301516158ce608084018215159052565b5060a08301516158e260a084018215159052565b5060c08301516158f660c084018215159052565b5060e083015161590e60e084018263ffffffff169052565b50610100928301516001600160a01b0316919092015290565b6000806040838503121561593a57600080fd5b823561594581614e61565b91506020830135614fa481614e61565b634e487b7160e01b600052603260045260246000fd5b60006080828403121561597d57600080fd5b6040516080810181811067ffffffffffffffff821117156159ae57634e487b7160e01b600052604160045260246000fd5b60405282356159bc81615035565b815260208301356159cc81615035565b6020820152604083810135908201526060928301359281019290925250919050565b81356159f981615035565b815460ff19811691151560ff1691821783556020840135615a1981615035565b61ffff199190911690911790151560081b61ff001617815560408201356001820155606090910135600290910155565b60006102808284031215615a5c57600080fd5b6146c4838361544c565b600060608284031215615a7857600080fd5b6146c48383615585565b600060e08284031215615a9457600080fd5b60405160e0810181811067ffffffffffffffff82111715615ac557634e487b7160e01b600052604160045260246000fd5b8060405250823581526020830135602082015260408301356040820152606083013560608201526080830135608082015260a083013560a082015260c0830135615b0e81614e61565b60c08201529392505050565b634e487b7160e01b600052602160045260246000fd5b600081518084526020808501945080840160005b83811015615b62578151151587529582019590820190600101615b44565b509495945050505050565b600081518084526020808501945080840160005b83811015615b6257815187529582019590820190600101615b81565b60006001600160a01b03808916835280881660208401525060c06040830152615bc960c0830187615b30565b8281036060840152615bdb8187615b6d565b90508281036080840152615bef8186615b6d565b905082810360a0840152615c038185615b6d565b9998505050505050505050565b60006001600160a01b03808816835280871660208401525060a06040830152615c3c60a0830186615b30565b8281036060840152615c4e8186615b6d565b90508281036080840152615c628185615b6d565b98975050505050505050565b600081518084526020808501945080840160005b83811015615b625781516001600160a01b031687529582019590820190600101615c82565b6001600160a01b038716815260c060208201526000615cc960c0830188615b30565b8281036040840152615cdb8188615c6e565b90508281036060840152615bdb8187615b6d565b6001600160a01b038616815260a060208201526000615d1160a0830187615b30565b8281036040840152615d238187615c6e565b90508281036060840152615c4e8186615b6d565b600060208284031215615d4957600080fd5b81516146c481614e61565b600060208284031215615d6657600080fd5b81516146c481615035565b634e487b7160e01b600052601260045260246000fd5b60006101208c151583528b151560208401528a151560408401528915156060840152881515608084015287151560a084015286151560c084015263ffffffff861660e0840152806101008401528381840152506101408385828501376000838501820152601f909301601f19169091019091019a9950505050505050505050565b634e487b7160e01b600052601160045260246000fd5b60008219821115615e3157615e31615e08565b500190565b815160009082906020808601845b83811015615e6057815185529382019390820190600101615e44565b50929695505050505050565b600082615e8957634e487b7160e01b600052601260045260246000fd5b500490565b60005b83811015615ea9578181015183820152602001615e91565b8381111561427c5750506000910152565b60008351615ecc818460208801615e8e565b835190830190615ee0818360208801615e8e565b01949350505050565b60008060408385031215615efc57600080fd5b8251615f0781614e61565b6020939093015192949293505050565b6000816000190483118215151615615f3157615f31615e08565b500290565b60008151808452615f4e816020860160208601615e8e565b601f01601f19169290920160200192915050565b828152604060208201526000614be46040830184615f36565b600060208284031215615f8d57600080fd5b81516146c481614e2e565b60008251615faa818460208701615e8e565b9190910192915050565b6020815260006146c46020830184615f3656fea2646970667358221220208eba2a424cf9d450353832333fa1255369096c9b3808d5d1a44f0d6978725064736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000f0e41a1f6e417c0666e3577422297b71ce5455770000000000000000000000000000000000000000000000000000000000001f40000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063
-----Decoded View---------------
Arg [0] : defaultContractOwner_ (address): 0xf0e41a1f6e417c0666E3577422297b71cE545577
Arg [1] : defaultPushPaymentGasLimit_ (uint32): 8000
Arg [2] : defaultPaymentMethods (address[]): 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270,0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174,0xc2132D05D31c914a87C6611C10748AEb04B58e8F,0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000f0e41a1f6e417c0666e3577422297b71ce545577
Arg [1] : 0000000000000000000000000000000000000000000000000000000000001f40
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [4] : 0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf1270
Arg [5] : 0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa84174
Arg [6] : 000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f
Arg [7] : 0000000000000000000000008f3cf7ad23cd3cadbd9735aff958023239c6a063
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.