Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
RedeemableContractOfferer
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {ContractOffererInterface} from "seaport-types/src/interfaces/ContractOffererInterface.sol"; import {SeaportInterface} from "seaport-types/src/interfaces/SeaportInterface.sol"; import {ItemType, OrderType} from "seaport-types/src/lib/ConsiderationEnums.sol"; import { AdvancedOrder, CriteriaResolver, OrderParameters, OfferItem, ConsiderationItem, ReceivedItem, Schema, SpentItem } from "seaport-types/src/lib/ConsiderationStructs.sol"; import {ERC20} from "solady/src/tokens/ERC20.sol"; import {ERC721} from "solady/src/tokens/ERC721.sol"; import {ERC1155} from "solady/src/tokens/ERC1155.sol"; import {IERC721Receiver} from "seaport-types/src/interfaces/IERC721Receiver.sol"; import {IERC1155Receiver} from "./interfaces/IERC1155Receiver.sol"; import {IERC721RedemptionMintable} from "./interfaces/IERC721RedemptionMintable.sol"; import {IERC1155RedemptionMintable} from "./interfaces/IERC1155RedemptionMintable.sol"; import {SignedRedeemContractOfferer} from "./lib/SignedRedeemContractOfferer.sol"; import {RedeemableErrorsAndEvents} from "./lib/RedeemableErrorsAndEvents.sol"; import {CampaignParams} from "./lib/RedeemableStructs.sol"; /** * @title RedeemablesContractOfferer * @author ryanio, stephankmin * @notice A Seaport contract offerer that allows users to burn to redeem on chain redeemables. */ contract RedeemableContractOfferer is ContractOffererInterface, RedeemableErrorsAndEvents, SignedRedeemContractOfferer { /// @dev The Seaport address allowed to interact with this contract offerer. address internal immutable _SEAPORT; /// @dev The conduit address to allow as an operator for this contract for newly minted tokens. address internal immutable _CONDUIT; bytes32 internal immutable _CONDUIT_KEY; /// @dev Counter for next campaign id. uint256 private _nextCampaignId = 1; /// @dev The campaign parameters by campaign id. mapping(uint256 campaignId => CampaignParams params) private _campaignParams; /// @dev The campaign URIs by campaign id. mapping(uint256 campaignId => string campaignURI) private _campaignURIs; /// @dev The total current redemptions by campaign id. mapping(uint256 campaignId => uint256 count) private _totalRedemptions; constructor(address conduit, bytes32 conduitKey, address seaport) { _CONDUIT = conduit; _CONDUIT_KEY = conduitKey; _SEAPORT = seaport; } function createCampaign(CampaignParams calldata params, string calldata uri) external returns (uint256 campaignId) { // Revert if there are no consideration items, since the redemption should require at least something. if (params.consideration.length == 0) revert NoConsiderationItems(); // Revert if startTime is past endTime. if (params.startTime > params.endTime) revert InvalidTime(); // Revert if any of the consideration item recipients is the zero address. The 0xdead address should be used instead. for (uint256 i = 0; i < params.consideration.length;) { if (params.consideration[i].recipient == address(0)) { revert ConsiderationItemRecipientCannotBeZeroAddress(); } unchecked { ++i; } } // Check for and set token approvals for the campaign. _setTokenApprovals(params); // Set the campaign params for the next campaignId. _campaignParams[_nextCampaignId] = params; // Set the campaign URI for the next campaignId. _campaignURIs[_nextCampaignId] = uri; // Set the correct current campaignId to return before incrementing // the next campaignId. campaignId = _nextCampaignId; // Increment the next campaignId. _nextCampaignId++; emit CampaignUpdated(campaignId, params, _campaignURIs[campaignId]); } function updateCampaign(uint256 campaignId, CampaignParams calldata params, string calldata uri) external { // Revert if campaignId is invalid. if (campaignId == 0 || campaignId >= _nextCampaignId) { revert InvalidCampaignId(); } // Revert if there are no consideration items, since the redemption should require at least something. if (params.consideration.length == 0) revert NoConsiderationItems(); // Revert if startTime is past endTime. if (params.startTime > params.endTime) revert InvalidTime(); // Revert if msg.sender is not the manager. address existingManager = _campaignParams[campaignId].manager; if (params.manager != msg.sender && (existingManager != address(0) && existingManager != params.manager)) { revert NotManager(); } // Revert if any of the consideration item recipients is the zero address. The 0xdead address should be used instead. for (uint256 i = 0; i < params.consideration.length;) { if (params.consideration[i].recipient == address(0)) { revert ConsiderationItemRecipientCannotBeZeroAddress(); } unchecked { ++i; } } // Check for and set token approvals for the campaign. _setTokenApprovals(params); // Set the campaign params for the given campaignId. _campaignParams[campaignId] = params; // Update campaign uri if it was provided. if (bytes(uri).length != 0) { _campaignURIs[campaignId] = uri; } emit CampaignUpdated(campaignId, params, _campaignURIs[campaignId]); } function _setTokenApprovals(CampaignParams memory params) internal { // Allow Seaport and the conduit as operators on behalf of this contract for offer items to be minted and transferred. for (uint256 i = 0; i < params.offer.length;) { // Native items do not need to be approved. if (params.offer[i].itemType == ItemType.NATIVE) { revert InvalidNativeOfferItem(); } // ERC721 and ERC1155 have the same function signatures for isApprovedForAll and setApprovalForAll. else if (params.offer[i].itemType >= ItemType.ERC721) { if (!ERC721(params.offer[i].token).isApprovedForAll(_CONDUIT, address(this))) { ERC721(params.offer[i].token).setApprovalForAll(_CONDUIT, true); } // Set the maximum approval amount for ERC20 tokens. } else { ERC20(params.offer[i].token).approve(_CONDUIT, type(uint256).max); } unchecked { ++i; } } // Allow Seaport and the conduit as operators on behalf of this contract for consideration items to be transferred in the onReceived hooks. for (uint256 i = 0; i < params.consideration.length;) { // ERC721 and ERC1155 have the same function signatures for isApprovedForAll and setApprovalForAll. if (params.consideration[i].itemType >= ItemType.ERC721) { if (!ERC721(params.consideration[i].token).isApprovedForAll(_CONDUIT, address(this))) { ERC721(params.consideration[i].token).setApprovalForAll(_CONDUIT, true); } // Set the maximum approval amount for ERC20 tokens. } else if (params.consideration[i].itemType == ItemType.ERC20) { ERC20(params.consideration[i].token).approve(_CONDUIT, type(uint256).max); } unchecked { ++i; } } } function updateCampaignURI(uint256 campaignId, string calldata uri) external { CampaignParams storage params = _campaignParams[campaignId]; if (params.manager != msg.sender) revert NotManager(); _campaignURIs[campaignId] = uri; emit CampaignUpdated(campaignId, params, uri); } /** * @dev Generates an order with the specified minimum and maximum spent * items, and optional context (supplied as extraData). * * @param fulfiller The address of the fulfiller. * @param minimumReceived The minimum items that the caller must receive. * @param maximumSpent The maximum items the caller is willing to spend. * @param context Additional context of the order. * * @return offer A tuple containing the offer items. * @return consideration An array containing the consideration items. */ function generateOrder( address fulfiller, SpentItem[] calldata minimumReceived, SpentItem[] calldata maximumSpent, bytes calldata context // encoded based on the schemaID ) external override returns (SpentItem[] memory offer, ReceivedItem[] memory consideration) { // Derive the offer and consideration with effects. (offer, consideration) = _createOrder(fulfiller, minimumReceived, maximumSpent, context, true); } /** * @dev Ratifies an order with the specified offer, consideration, and * optional context (supplied as extraData). * * @custom:param offer The offer items. * @custom:param consideration The consideration items. * @custom:param context Additional context of the order. * @custom:param orderHashes The hashes to ratify. * @custom:param contractNonce The nonce of the contract. * * @return ratifyOrderMagicValue The magic value returned by the contract * offerer. */ function ratifyOrder( SpentItem[] calldata, /* offer */ ReceivedItem[] calldata, /* consideration */ bytes calldata, /* context */ // encoded based on the schemaID bytes32[] calldata, /* orderHashes */ uint256 /* contractNonce */ ) external pure override returns (bytes4) { assembly { // Return the RatifyOrder magic value. mstore(0, 0xf4dd92ce) return(0x1c, 32) } } /** * @dev View function to preview an order generated in response to a minimum * set of received items, maximum set of spent items, and context * (supplied as extraData). * * @custom:param caller The address of the caller (e.g. Seaport). * @param fulfiller The address of the fulfiller (e.g. the account * calling Seaport). * @param minimumReceived The minimum items that the caller is willing to * receive. * @param maximumSpent The maximum items caller is willing to spend. * @param context Additional context of the order. * * @return offer A tuple containing the offer items. * @return consideration A tuple containing the consideration items. */ function previewOrder( address, /* caller */ address fulfiller, SpentItem[] calldata minimumReceived, SpentItem[] calldata maximumSpent, bytes calldata context // encoded based on the schemaID ) external view override returns (SpentItem[] memory offer, ReceivedItem[] memory consideration) { // To avoid the solidity compiler complaining about calling a non-view // function here (_createOrder), we will cast it as a view and use it. // This is okay because we are not modifying any state when passing // withEffects=false. function( address, SpentItem[] memory, SpentItem[] memory, bytes calldata, bool ) internal view returns (SpentItem[] memory, ReceivedItem[] memory) fn; function( address, SpentItem[] memory, SpentItem[] memory, bytes calldata, bool ) internal returns ( SpentItem[] memory, ReceivedItem[] memory ) fn2 = _createOrder; assembly { fn := fn2 } // Derive the offer and consideration without effects. (offer, consideration) = fn(fulfiller, minimumReceived, maximumSpent, context, false); } /** * @dev Gets the metadata for this contract offerer. * * @return name The name of the contract offerer. * @return schemas The schemas supported by the contract offerer. */ function getSeaportMetadata() external pure override returns ( string memory name, Schema[] memory schemas // map to Seaport Improvement Proposal IDs ) { schemas = new Schema[](0); return ("RedeemablesContractOfferer", schemas); } function supportsInterface(bytes4 interfaceId) external view virtual returns (bool) { return interfaceId == type(ContractOffererInterface).interfaceId || interfaceId == type(IERC721Receiver).interfaceId || interfaceId == type(IERC1155Receiver).interfaceId; } function _createOrder( address fulfiller, SpentItem[] memory minimumReceived, SpentItem[] memory maximumSpent, bytes calldata context, bool withEffects ) internal returns (SpentItem[] memory offer, ReceivedItem[] memory consideration) { // Get the campaign. uint256 campaignId = uint256(bytes32(context[0:32])); CampaignParams storage params = _campaignParams[campaignId]; // Declare an error buffer; first check is that caller is Seaport or the token contract. uint256 errorBuffer = _cast(msg.sender != _SEAPORT && msg.sender != params.consideration[0].token); // Check the redemption is active. errorBuffer |= _cast(_isInactive(params.startTime, params.endTime)) << 1; // Check max total redemptions would not be exceeded. errorBuffer |= _cast(_totalRedemptions[campaignId] + maximumSpent.length > params.maxCampaignRedemptions) << 2; // Get the redemption hash. bytes32 redemptionHash = bytes32(context[32:64]); // Check the signature is valid if required. if (params.signer != address(0)) { uint256 salt = uint256(bytes32(context[64:96])); bytes memory signature = context[96:]; // _verifySignature will revert if the signature is invalid or digest is already used. _verifySignature(params.signer, fulfiller, maximumSpent, redemptionHash, salt, signature, withEffects); } if (errorBuffer > 0) { if (errorBuffer << 255 != 0) { revert InvalidCaller(msg.sender); } else if (errorBuffer << 254 != 0) { revert NotActive(block.timestamp, params.startTime, params.endTime); } else if (errorBuffer << 253 != 0) { revert MaxCampaignRedemptionsReached( _totalRedemptions[campaignId] + maximumSpent.length, params.maxCampaignRedemptions ); } else if (errorBuffer << 252 != 0) { revert InvalidConsiderationItem(maximumSpent[0].token, params.consideration[0].token); } else {} } // Set the offer from the params. offer = new SpentItem[](params.offer.length); for (uint256 i = 0; i < params.offer.length;) { OfferItem memory offerItem = params.offer[i]; if (params.offer.length > maximumSpent.length) {} uint256 tokenId = IERC721RedemptionMintable(offerItem.token).mintRedemption(address(this), maximumSpent); // Set the itemType without criteria. ItemType itemType = offerItem.itemType == ItemType.ERC721_WITH_CRITERIA ? ItemType.ERC721 : offerItem.itemType == ItemType.ERC1155_WITH_CRITERIA ? ItemType.ERC1155 : offerItem.itemType; offer[i] = SpentItem({ itemType: itemType, token: offerItem.token, identifier: tokenId, amount: offerItem.startAmount }); unchecked { ++i; } } // Set the consideration from the params. consideration = new ReceivedItem[](params.consideration.length); for (uint256 i = 0; i < params.consideration.length;) { ConsiderationItem memory considerationItem = params.consideration[i]; ItemType itemType; uint256 identifier; // If consideration item is wildcard criteria item, set itemType to ERC721 // and identifier to the maximumSpent item identifier. if ( (considerationItem.itemType == ItemType.ERC721_WITH_CRITERIA) && (considerationItem.identifierOrCriteria == 0) ) { itemType = ItemType.ERC721; identifier = maximumSpent[i].identifier; } else if ( (considerationItem.itemType == ItemType.ERC1155_WITH_CRITERIA) && (considerationItem.identifierOrCriteria == 0) ) { itemType = ItemType.ERC1155; identifier = maximumSpent[i].identifier; } else { itemType = considerationItem.itemType; identifier = considerationItem.identifierOrCriteria; } consideration[i] = ReceivedItem({ itemType: itemType, token: considerationItem.token, identifier: identifier, amount: considerationItem.startAmount, recipient: considerationItem.recipient }); unchecked { ++i; } } // If withEffects is true then make state changes. if (withEffects) { // Increment total redemptions. _totalRedemptions[campaignId] += maximumSpent.length; SpentItem[] memory spent = new SpentItem[](consideration.length); for (uint256 i = 0; i < consideration.length;) { spent[i] = SpentItem({ itemType: consideration[i].itemType, token: consideration[i].token, identifier: consideration[i].identifier, amount: consideration[i].amount }); unchecked { ++i; } } // Emit Redemption event. emit Redemption(campaignId, redemptionHash); } } function onERC721Received( address, /* operator */ address from, uint256 tokenId, bytes calldata data ) external returns (bytes4) { if (from == address(0)) { return IERC721Receiver.onERC721Received.selector; } // Get the campaign. uint256 campaignId = uint256(bytes32(data[0:32])); CampaignParams storage params = _campaignParams[campaignId]; OfferItem[] memory offer = new OfferItem[](1); offer[0] = OfferItem({ itemType: ItemType.ERC721_WITH_CRITERIA, token: params.offer[0].token, identifierOrCriteria: 0, startAmount: 1, endAmount: 1 }); ConsiderationItem[] memory consideration = new ConsiderationItem[](1); consideration[0] = ConsiderationItem({ itemType: ItemType.ERC721, token: msg.sender, identifierOrCriteria: tokenId, startAmount: 1, endAmount: 1, recipient: payable(address(0x000000000000000000000000000000000000dEaD)) }); OrderParameters memory parameters = OrderParameters({ offerer: address(this), zone: address(0), offer: offer, consideration: consideration, orderType: OrderType.CONTRACT, startTime: block.timestamp, endTime: block.timestamp + 10, zoneHash: bytes32(0), salt: uint256(0), conduitKey: _CONDUIT_KEY, totalOriginalConsiderationItems: consideration.length }); AdvancedOrder memory order = AdvancedOrder({parameters: parameters, numerator: 1, denominator: 1, signature: "", extraData: data}); SeaportInterface(_SEAPORT).fulfillAdvancedOrder(order, new CriteriaResolver[](0), _CONDUIT_KEY, from); return IERC721Receiver.onERC721Received.selector; } function onERC1155Received( address, /* operator */ address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4) { if (from == address(0)) { return IERC1155Receiver.onERC1155Received.selector; } // Get the campaign. uint256 campaignId = uint256(bytes32(data[0:32])); CampaignParams storage params = _campaignParams[campaignId]; SpentItem[] memory minimumReceived = new SpentItem[](1); minimumReceived[0] = SpentItem({ itemType: ItemType.ERC721, token: params.offer[0].token, identifier: params.offer[0].identifierOrCriteria, amount: params.offer[0].startAmount }); SpentItem[] memory maximumSpent = new SpentItem[](1); maximumSpent[0] = SpentItem({itemType: ItemType.ERC1155, token: msg.sender, identifier: id, amount: value}); // _createOrder will revert if any validations fail. _createOrder(from, minimumReceived, maximumSpent, data, true); // Transfer the token to the consideration item recipient. address recipient = _getConsiderationRecipient(params.consideration, msg.sender); ERC1155(msg.sender).safeTransferFrom(address(this), recipient, id, value, ""); // Transfer the newly minted token to the fulfiller. ERC721(params.offer[0].token).safeTransferFrom(address(this), from, id, ""); return IERC1155Receiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, /* operator */ address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4) { if (from == address(0)) { return IERC1155Receiver.onERC1155BatchReceived.selector; } if (ids.length != values.length) revert RedeemMismatchedLengths(); // Get the campaign. uint256 campaignId = uint256(bytes32(data[0:32])); CampaignParams storage params = _campaignParams[campaignId]; SpentItem[] memory minimumReceived = new SpentItem[](1); minimumReceived[0] = SpentItem({ itemType: ItemType.ERC721, token: params.offer[0].token, identifier: params.offer[0].identifierOrCriteria, amount: params.offer[0].startAmount }); SpentItem[] memory maximumSpent = new SpentItem[](ids.length); for (uint256 i = 0; i < ids.length;) { maximumSpent[i] = SpentItem({itemType: ItemType.ERC1155, token: msg.sender, identifier: ids[i], amount: values[i]}); unchecked { ++i; } } // _createOrder will revert if any validations fail. _createOrder(from, minimumReceived, maximumSpent, data, true); // Transfer the tokens to the consideration item recipient. address recipient = _getConsiderationRecipient(params.consideration, msg.sender); ERC1155(msg.sender).safeBatchTransferFrom(address(this), recipient, ids, values, ""); // Transfer the newly minted token to the fulfiller. ERC721(params.offer[0].token).safeTransferFrom(address(this), from, ids[0]); return IERC1155Receiver.onERC1155BatchReceived.selector; } function getCampaign(uint256 campaignId) external view returns (CampaignParams memory params, string memory uri, uint256 totalRedemptions) { if (campaignId >= _nextCampaignId) revert InvalidCampaignId(); params = _campaignParams[campaignId]; uri = _campaignURIs[campaignId]; totalRedemptions = _totalRedemptions[campaignId]; } function _getConsiderationRecipient(ConsiderationItem[] storage consideration, address token) internal view returns (address) { for (uint256 i = 0; i < consideration.length;) { if (consideration[i].token == token) { return consideration[i].recipient; } unchecked { ++i; } } revert ConsiderationRecipientNotFound(token); } function _isInactive(uint256 startTime, uint256 endTime) internal view returns (bool inactive) { // Using the same check for time boundary from Seaport. // startTime <= block.timestamp < endTime assembly { inactive := or(iszero(gt(endTime, timestamp())), gt(startTime, timestamp())) } } function _isValidTokenAddress(CampaignParams memory params, address token) internal pure returns (bool valid) { for (uint256 i = 0; i < params.consideration.length;) { if (params.consideration[i].token == token) { valid = true; break; } unchecked { ++i; } } } /** * @notice Internal utility function to remove a uint from a supplied * enumeration. * * @param toRemove The uint to remove. * @param enumeration The enumerated uints to parse. */ function _removeFromEnumeration(uint256 toRemove, uint256[] storage enumeration) internal { // Cache the length. uint256 enumerationLength = enumeration.length; for (uint256 i = 0; i < enumerationLength;) { // Check if the enumerated element is the one we are deleting. if (enumeration[i] == toRemove) { // Swap with the last element. enumeration[i] = enumeration[enumerationLength - 1]; // Delete the (now duplicated) last element. enumeration.pop(); // Exit the loop. break; } unchecked { ++i; } } } /** * @notice Internal utility function to cast uint types to address * to dedupe the need for multiple implementations of * `_removeFromEnumeration`. * * @param fnIn The fn with uint input. * * @return fnOut The fn with address input. */ function _asAddressArray(function(uint256, uint256[] storage) internal fnIn) internal pure returns (function(address, address[] storage) internal fnOut) { assembly { fnOut := fnIn } } /** * @dev Internal pure function to cast a `bool` value to a `uint256` value. * * @param b The `bool` value to cast. * * @return u The `uint256` value. */ function _cast(bool b) internal pure returns (uint256 u) { assembly { u := b } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {ReceivedItem, Schema, SpentItem} from "../lib/ConsiderationStructs.sol"; import {IERC165} from "../interfaces/IERC165.sol"; /** * @title ContractOffererInterface * @notice Contains the minimum interfaces needed to interact with a contract * offerer. */ interface ContractOffererInterface is IERC165 { /** * @dev Generates an order with the specified minimum and maximum spent * items, and optional context (supplied as extraData). * * @param fulfiller The address of the fulfiller. * @param minimumReceived The minimum items that the caller is willing to * receive. * @param maximumSpent The maximum items the caller is willing to spend. * @param context Additional context of the order. * * @return offer A tuple containing the offer items. * @return consideration A tuple containing the consideration items. */ function generateOrder( address fulfiller, SpentItem[] calldata minimumReceived, SpentItem[] calldata maximumSpent, bytes calldata context // encoded based on the schemaID ) external returns (SpentItem[] memory offer, ReceivedItem[] memory consideration); /** * @dev Ratifies an order with the specified offer, consideration, and * optional context (supplied as extraData). * * @param offer The offer items. * @param consideration The consideration items. * @param context Additional context of the order. * @param orderHashes The hashes to ratify. * @param contractNonce The nonce of the contract. * * @return ratifyOrderMagicValue The magic value returned by the contract * offerer. */ function ratifyOrder( SpentItem[] calldata offer, ReceivedItem[] calldata consideration, bytes calldata context, // encoded based on the schemaID bytes32[] calldata orderHashes, uint256 contractNonce ) external returns (bytes4 ratifyOrderMagicValue); /** * @dev View function to preview an order generated in response to a minimum * set of received items, maximum set of spent items, and context * (supplied as extraData). * * @param caller The address of the caller (e.g. Seaport). * @param fulfiller The address of the fulfiller (e.g. the account * calling Seaport). * @param minimumReceived The minimum items that the caller is willing to * receive. * @param maximumSpent The maximum items the caller is willing to spend. * @param context Additional context of the order. * * @return offer A tuple containing the offer items. * @return consideration A tuple containing the consideration items. */ function previewOrder( address caller, address fulfiller, SpentItem[] calldata minimumReceived, SpentItem[] calldata maximumSpent, bytes calldata context // encoded based on the schemaID ) external view returns (SpentItem[] memory offer, ReceivedItem[] memory consideration); /** * @dev Gets the metadata for this contract offerer. * * @return name The name of the contract offerer. * @return schemas The schemas supported by the contract offerer. */ function getSeaportMetadata() external view returns (string memory name, Schema[] memory schemas); // map to Seaport Improvement Proposal IDs function supportsInterface(bytes4 interfaceId) external view override returns (bool); // Additional functions and/or events based on implemented schemaIDs }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import { AdvancedOrder, BasicOrderParameters, CriteriaResolver, Execution, Fulfillment, FulfillmentComponent, Order, OrderComponents } from "../lib/ConsiderationStructs.sol"; /** * @title SeaportInterface * @author 0age * @custom:version 1.5 * @notice Seaport is a generalized native token/ERC20/ERC721/ERC1155 * marketplace. It minimizes external calls to the greatest extent * possible and provides lightweight methods for common routes as well * as more flexible methods for composing advanced orders. * * @dev SeaportInterface contains all external function interfaces for Seaport. */ interface SeaportInterface { /** * @notice Fulfill an order offering an ERC721 token by supplying Ether (or * the native token for the given chain) as consideration for the * order. An arbitrary number of "additional recipients" may also be * supplied which will each receive native tokens from the fulfiller * as consideration. * * @param parameters Additional information on the fulfilled order. Note * that the offerer must first approve this contract (or * their preferred conduit if indicated by the order) for * their offered ERC721 token to be transferred. * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillBasicOrder( BasicOrderParameters calldata parameters ) external payable returns (bool fulfilled); /** * @notice Fulfill an order with an arbitrary number of items for offer and * consideration. Note that this function does not support * criteria-based orders or partial filling of orders (though * filling the remainder of a partially-filled order is supported). * * @param order The order to fulfill. Note that both the * offerer and the fulfiller must first approve * this contract (or the corresponding conduit if * indicated) to transfer any relevant tokens on * their behalf and that contracts must implement * `onERC1155Received` to receive ERC1155 tokens * as consideration. * @param fulfillerConduitKey A bytes32 value indicating what conduit, if * any, to source the fulfiller's token approvals * from. The zero hash signifies that no conduit * should be used, with direct approvals set on * Seaport. * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillOrder( Order calldata order, bytes32 fulfillerConduitKey ) external payable returns (bool fulfilled); /** * @notice Fill an order, fully or partially, with an arbitrary number of * items for offer and consideration alongside criteria resolvers * containing specific token identifiers and associated proofs. * * @param advancedOrder The order to fulfill along with the fraction * of the order to attempt to fill. Note that * both the offerer and the fulfiller must first * approve this contract (or their preferred * conduit if indicated by the order) to transfer * any relevant tokens on their behalf and that * contracts must implement `onERC1155Received` * to receive ERC1155 tokens as consideration. * Also note that all offer and consideration * components must have no remainder after * multiplication of the respective amount with * the supplied fraction for the partial fill to * be considered valid. * @param criteriaResolvers An array where each element contains a * reference to a specific offer or * consideration, a token identifier, and a proof * that the supplied token identifier is * contained in the merkle root held by the item * in question's criteria element. Note that an * empty criteria indicates that any * (transferable) token identifier on the token * in question is valid and that no associated * proof needs to be supplied. * @param fulfillerConduitKey A bytes32 value indicating what conduit, if * any, to source the fulfiller's token approvals * from. The zero hash signifies that no conduit * should be used, with direct approvals set on * Seaport. * @param recipient The intended recipient for all received items, * with `address(0)` indicating that the caller * should receive the items. * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillAdvancedOrder( AdvancedOrder calldata advancedOrder, CriteriaResolver[] calldata criteriaResolvers, bytes32 fulfillerConduitKey, address recipient ) external payable returns (bool fulfilled); /** * @notice Attempt to fill a group of orders, each with an arbitrary number * of items for offer and consideration. Any order that is not * currently active, has already been fully filled, or has been * cancelled will be omitted. Remaining offer and consideration * items will then be aggregated where possible as indicated by the * supplied offer and consideration component arrays and aggregated * items will be transferred to the fulfiller or to each intended * recipient, respectively. Note that a failing item transfer or an * issue with order formatting will cause the entire batch to fail. * Note that this function does not support criteria-based orders or * partial filling of orders (though filling the remainder of a * partially-filled order is supported). * * @param orders The orders to fulfill. Note that both * the offerer and the fulfiller must first * approve this contract (or the * corresponding conduit if indicated) to * transfer any relevant tokens on their * behalf and that contracts must implement * `onERC1155Received` to receive ERC1155 * tokens as consideration. * @param offerFulfillments An array of FulfillmentComponent arrays * indicating which offer items to attempt * to aggregate when preparing executions. * @param considerationFulfillments An array of FulfillmentComponent arrays * indicating which consideration items to * attempt to aggregate when preparing * executions. * @param fulfillerConduitKey A bytes32 value indicating what conduit, * if any, to source the fulfiller's token * approvals from. The zero hash signifies * that no conduit should be used, with * direct approvals set on this contract. * @param maximumFulfilled The maximum number of orders to fulfill. * * @return availableOrders An array of booleans indicating if each order * with an index corresponding to the index of the * returned boolean was fulfillable or not. * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. Note that unspent offer item amounts or * native tokens will not be reflected as part of * this array. */ function fulfillAvailableOrders( Order[] calldata orders, FulfillmentComponent[][] calldata offerFulfillments, FulfillmentComponent[][] calldata considerationFulfillments, bytes32 fulfillerConduitKey, uint256 maximumFulfilled ) external payable returns (bool[] memory availableOrders, Execution[] memory executions); /** * @notice Attempt to fill a group of orders, fully or partially, with an * arbitrary number of items for offer and consideration per order * alongside criteria resolvers containing specific token * identifiers and associated proofs. Any order that is not * currently active, has already been fully filled, or has been * cancelled will be omitted. Remaining offer and consideration * items will then be aggregated where possible as indicated by the * supplied offer and consideration component arrays and aggregated * items will be transferred to the fulfiller or to each intended * recipient, respectively. Note that a failing item transfer or an * issue with order formatting will cause the entire batch to fail. * * @param advancedOrders The orders to fulfill along with the * fraction of those orders to attempt to * fill. Note that both the offerer and the * fulfiller must first approve this * contract (or their preferred conduit if * indicated by the order) to transfer any * relevant tokens on their behalf and that * contracts must implement * `onERC1155Received` to enable receipt of * ERC1155 tokens as consideration. Also * note that all offer and consideration * components must have no remainder after * multiplication of the respective amount * with the supplied fraction for an * order's partial fill amount to be * considered valid. * @param criteriaResolvers An array where each element contains a * reference to a specific offer or * consideration, a token identifier, and a * proof that the supplied token identifier * is contained in the merkle root held by * the item in question's criteria element. * Note that an empty criteria indicates * that any (transferable) token * identifier on the token in question is * valid and that no associated proof needs * to be supplied. * @param offerFulfillments An array of FulfillmentComponent arrays * indicating which offer items to attempt * to aggregate when preparing executions. * @param considerationFulfillments An array of FulfillmentComponent arrays * indicating which consideration items to * attempt to aggregate when preparing * executions. * @param fulfillerConduitKey A bytes32 value indicating what conduit, * if any, to source the fulfiller's token * approvals from. The zero hash signifies * that no conduit should be used, with * direct approvals set on this contract. * @param recipient The intended recipient for all received * items, with `address(0)` indicating that * the caller should receive the items. * @param maximumFulfilled The maximum number of orders to fulfill. * * @return availableOrders An array of booleans indicating if each order * with an index corresponding to the index of the * returned boolean was fulfillable or not. * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. Note that unspent offer item amounts or * native tokens will not be reflected as part of * this array. */ function fulfillAvailableAdvancedOrders( AdvancedOrder[] calldata advancedOrders, CriteriaResolver[] calldata criteriaResolvers, FulfillmentComponent[][] calldata offerFulfillments, FulfillmentComponent[][] calldata considerationFulfillments, bytes32 fulfillerConduitKey, address recipient, uint256 maximumFulfilled ) external payable returns (bool[] memory availableOrders, Execution[] memory executions); /** * @notice Match an arbitrary number of orders, each with an arbitrary * number of items for offer and consideration along with a set of * fulfillments allocating offer components to consideration * components. Note that this function does not support * criteria-based or partial filling of orders (though filling the * remainder of a partially-filled order is supported). Any unspent * offer item amounts or native tokens will be transferred to the * caller. * * @param orders The orders to match. Note that both the offerer and * fulfiller on each order must first approve this * contract (or their conduit if indicated by the order) * to transfer any relevant tokens on their behalf and * each consideration recipient must implement * `onERC1155Received` to enable ERC1155 token receipt. * @param fulfillments An array of elements allocating offer components to * consideration components. Note that each * consideration component must be fully met for the * match operation to be valid. * * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. Note that unspent offer item amounts or * native tokens will not be reflected as part of this * array. */ function matchOrders( Order[] calldata orders, Fulfillment[] calldata fulfillments ) external payable returns (Execution[] memory executions); /** * @notice Match an arbitrary number of full or partial orders, each with an * arbitrary number of items for offer and consideration, supplying * criteria resolvers containing specific token identifiers and * associated proofs as well as fulfillments allocating offer * components to consideration components. Any unspent offer item * amounts will be transferred to the designated recipient (with the * null address signifying to use the caller) and any unspent native * tokens will be returned to the caller. * * @param orders The advanced orders to match. Note that both the * offerer and fulfiller on each order must first * approve this contract (or a preferred conduit if * indicated by the order) to transfer any relevant * tokens on their behalf and each consideration * recipient must implement `onERC1155Received` in * order to receive ERC1155 tokens. Also note that * the offer and consideration components for each * order must have no remainder after multiplying * the respective amount with the supplied fraction * in order for the group of partial fills to be * considered valid. * @param criteriaResolvers An array where each element contains a reference * to a specific order as well as that order's * offer or consideration, a token identifier, and * a proof that the supplied token identifier is * contained in the order's merkle root. Note that * an empty root indicates that any (transferable) * token identifier is valid and that no associated * proof needs to be supplied. * @param fulfillments An array of elements allocating offer components * to consideration components. Note that each * consideration component must be fully met in * order for the match operation to be valid. * @param recipient The intended recipient for all unspent offer * item amounts, or the caller if the null address * is supplied. * * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. Note that unspent offer item amounts or native * tokens will not be reflected as part of this array. */ function matchAdvancedOrders( AdvancedOrder[] calldata orders, CriteriaResolver[] calldata criteriaResolvers, Fulfillment[] calldata fulfillments, address recipient ) external payable returns (Execution[] memory executions); /** * @notice Cancel an arbitrary number of orders. Note that only the offerer * or the zone of a given order may cancel it. Callers should ensure * that the intended order was cancelled by calling `getOrderStatus` * and confirming that `isCancelled` returns `true`. * * @param orders The orders to cancel. * * @return cancelled A boolean indicating whether the supplied orders have * been successfully cancelled. */ function cancel( OrderComponents[] calldata orders ) external returns (bool cancelled); /** * @notice Validate an arbitrary number of orders, thereby registering their * signatures as valid and allowing the fulfiller to skip signature * verification on fulfillment. Note that validated orders may still * be unfulfillable due to invalid item amounts or other factors; * callers should determine whether validated orders are fulfillable * by simulating the fulfillment call prior to execution. Also note * that anyone can validate a signed order, but only the offerer can * validate an order without supplying a signature. * * @param orders The orders to validate. * * @return validated A boolean indicating whether the supplied orders have * been successfully validated. */ function validate( Order[] calldata orders ) external returns (bool validated); /** * @notice Cancel all orders from a given offerer with a given zone in bulk * by incrementing a counter. Note that only the offerer may * increment the counter. * * @return newCounter The new counter. */ function incrementCounter() external returns (uint256 newCounter); /** * @notice Fulfill an order offering an ERC721 token by supplying Ether (or * the native token for the given chain) as consideration for the * order. An arbitrary number of "additional recipients" may also be * supplied which will each receive native tokens from the fulfiller * as consideration. Note that this function costs less gas than * `fulfillBasicOrder` due to the zero bytes in the function * selector (0x00000000) which also results in earlier function * dispatch. * * @param parameters Additional information on the fulfilled order. Note * that the offerer must first approve this contract (or * their preferred conduit if indicated by the order) for * their offered ERC721 token to be transferred. * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillBasicOrder_efficient_6GL6yc( BasicOrderParameters calldata parameters ) external payable returns (bool fulfilled); /** * @notice Retrieve the order hash for a given order. * * @param order The components of the order. * * @return orderHash The order hash. */ function getOrderHash( OrderComponents calldata order ) external view returns (bytes32 orderHash); /** * @notice Retrieve the status of a given order by hash, including whether * the order has been cancelled or validated and the fraction of the * order that has been filled. * * @param orderHash The order hash in question. * * @return isValidated A boolean indicating whether the order in question * has been validated (i.e. previously approved or * partially filled). * @return isCancelled A boolean indicating whether the order in question * has been cancelled. * @return totalFilled The total portion of the order that has been filled * (i.e. the "numerator"). * @return totalSize The total size of the order that is either filled or * unfilled (i.e. the "denominator"). */ function getOrderStatus( bytes32 orderHash ) external view returns ( bool isValidated, bool isCancelled, uint256 totalFilled, uint256 totalSize ); /** * @notice Retrieve the current counter for a given offerer. * * @param offerer The offerer in question. * * @return counter The current counter. */ function getCounter( address offerer ) external view returns (uint256 counter); /** * @notice Retrieve configuration information for this contract. * * @return version The contract version. * @return domainSeparator The domain separator for this contract. * @return conduitController The conduit Controller set for this contract. */ function information() external view returns ( string memory version, bytes32 domainSeparator, address conduitController ); function getContractOffererNonce( address contractOfferer ) external view returns (uint256 nonce); /** * @notice Retrieve the name of this contract. * * @return contractName The name of this contract. */ function name() external view returns (string memory contractName); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; enum OrderType { // 0: no partial fills, anyone can execute FULL_OPEN, // 1: partial fills supported, anyone can execute PARTIAL_OPEN, // 2: no partial fills, only offerer or zone can execute FULL_RESTRICTED, // 3: partial fills supported, only offerer or zone can execute PARTIAL_RESTRICTED, // 4: contract order type CONTRACT } enum BasicOrderType { // 0: no partial fills, anyone can execute ETH_TO_ERC721_FULL_OPEN, // 1: partial fills supported, anyone can execute ETH_TO_ERC721_PARTIAL_OPEN, // 2: no partial fills, only offerer or zone can execute ETH_TO_ERC721_FULL_RESTRICTED, // 3: partial fills supported, only offerer or zone can execute ETH_TO_ERC721_PARTIAL_RESTRICTED, // 4: no partial fills, anyone can execute ETH_TO_ERC1155_FULL_OPEN, // 5: partial fills supported, anyone can execute ETH_TO_ERC1155_PARTIAL_OPEN, // 6: no partial fills, only offerer or zone can execute ETH_TO_ERC1155_FULL_RESTRICTED, // 7: partial fills supported, only offerer or zone can execute ETH_TO_ERC1155_PARTIAL_RESTRICTED, // 8: no partial fills, anyone can execute ERC20_TO_ERC721_FULL_OPEN, // 9: partial fills supported, anyone can execute ERC20_TO_ERC721_PARTIAL_OPEN, // 10: no partial fills, only offerer or zone can execute ERC20_TO_ERC721_FULL_RESTRICTED, // 11: partial fills supported, only offerer or zone can execute ERC20_TO_ERC721_PARTIAL_RESTRICTED, // 12: no partial fills, anyone can execute ERC20_TO_ERC1155_FULL_OPEN, // 13: partial fills supported, anyone can execute ERC20_TO_ERC1155_PARTIAL_OPEN, // 14: no partial fills, only offerer or zone can execute ERC20_TO_ERC1155_FULL_RESTRICTED, // 15: partial fills supported, only offerer or zone can execute ERC20_TO_ERC1155_PARTIAL_RESTRICTED, // 16: no partial fills, anyone can execute ERC721_TO_ERC20_FULL_OPEN, // 17: partial fills supported, anyone can execute ERC721_TO_ERC20_PARTIAL_OPEN, // 18: no partial fills, only offerer or zone can execute ERC721_TO_ERC20_FULL_RESTRICTED, // 19: partial fills supported, only offerer or zone can execute ERC721_TO_ERC20_PARTIAL_RESTRICTED, // 20: no partial fills, anyone can execute ERC1155_TO_ERC20_FULL_OPEN, // 21: partial fills supported, anyone can execute ERC1155_TO_ERC20_PARTIAL_OPEN, // 22: no partial fills, only offerer or zone can execute ERC1155_TO_ERC20_FULL_RESTRICTED, // 23: partial fills supported, only offerer or zone can execute ERC1155_TO_ERC20_PARTIAL_RESTRICTED } enum BasicOrderRouteType { // 0: provide Ether (or other native token) to receive offered ERC721 item. ETH_TO_ERC721, // 1: provide Ether (or other native token) to receive offered ERC1155 item. ETH_TO_ERC1155, // 2: provide ERC20 item to receive offered ERC721 item. ERC20_TO_ERC721, // 3: provide ERC20 item to receive offered ERC1155 item. ERC20_TO_ERC1155, // 4: provide ERC721 item to receive offered ERC20 item. ERC721_TO_ERC20, // 5: provide ERC1155 item to receive offered ERC20 item. ERC1155_TO_ERC20 } enum ItemType { // 0: ETH on mainnet, MATIC on polygon, etc. NATIVE, // 1: ERC20 items (ERC777 and ERC20 analogues could also technically work) ERC20, // 2: ERC721 items ERC721, // 3: ERC1155 items ERC1155, // 4: ERC721 items where a number of tokenIds are supported ERC721_WITH_CRITERIA, // 5: ERC1155 items where a number of ids are supported ERC1155_WITH_CRITERIA } enum Side { // 0: Items that can be spent OFFER, // 1: Items that must be received CONSIDERATION }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import { BasicOrderType, ItemType, OrderType, Side } from "./ConsiderationEnums.sol"; import { CalldataPointer, MemoryPointer } from "../helpers/PointerLibraries.sol"; /** * @dev An order contains eleven components: an offerer, a zone (or account that * can cancel the order or restrict who can fulfill the order depending on * the type), the order type (specifying partial fill support as well as * restricted order status), the start and end time, a hash that will be * provided to the zone when validating restricted orders, a salt, a key * corresponding to a given conduit, a counter, and an arbitrary number of * offer items that can be spent along with consideration items that must * be received by their respective recipient. */ struct OrderComponents { address offerer; address zone; OfferItem[] offer; ConsiderationItem[] consideration; OrderType orderType; uint256 startTime; uint256 endTime; bytes32 zoneHash; uint256 salt; bytes32 conduitKey; uint256 counter; } /** * @dev An offer item has five components: an item type (ETH or other native * tokens, ERC20, ERC721, and ERC1155, as well as criteria-based ERC721 and * ERC1155), a token address, a dual-purpose "identifierOrCriteria" * component that will either represent a tokenId or a merkle root * depending on the item type, and a start and end amount that support * increasing or decreasing amounts over the duration of the respective * order. */ struct OfferItem { ItemType itemType; address token; uint256 identifierOrCriteria; uint256 startAmount; uint256 endAmount; } /** * @dev A consideration item has the same five components as an offer item and * an additional sixth component designating the required recipient of the * item. */ struct ConsiderationItem { ItemType itemType; address token; uint256 identifierOrCriteria; uint256 startAmount; uint256 endAmount; address payable recipient; } /** * @dev A spent item is translated from a utilized offer item and has four * components: an item type (ETH or other native tokens, ERC20, ERC721, and * ERC1155), a token address, a tokenId, and an amount. */ struct SpentItem { ItemType itemType; address token; uint256 identifier; uint256 amount; } /** * @dev A received item is translated from a utilized consideration item and has * the same four components as a spent item, as well as an additional fifth * component designating the required recipient of the item. */ struct ReceivedItem { ItemType itemType; address token; uint256 identifier; uint256 amount; address payable recipient; } /** * @dev For basic orders involving ETH / native / ERC20 <=> ERC721 / ERC1155 * matching, a group of six functions may be called that only requires a * subset of the usual order arguments. Note the use of a "basicOrderType" * enum; this represents both the usual order type as well as the "route" * of the basic order (a simple derivation function for the basic order * type is `basicOrderType = orderType + (4 * basicOrderRoute)`.) */ struct BasicOrderParameters { // calldata offset address considerationToken; // 0x24 uint256 considerationIdentifier; // 0x44 uint256 considerationAmount; // 0x64 address payable offerer; // 0x84 address zone; // 0xa4 address offerToken; // 0xc4 uint256 offerIdentifier; // 0xe4 uint256 offerAmount; // 0x104 BasicOrderType basicOrderType; // 0x124 uint256 startTime; // 0x144 uint256 endTime; // 0x164 bytes32 zoneHash; // 0x184 uint256 salt; // 0x1a4 bytes32 offererConduitKey; // 0x1c4 bytes32 fulfillerConduitKey; // 0x1e4 uint256 totalOriginalAdditionalRecipients; // 0x204 AdditionalRecipient[] additionalRecipients; // 0x224 bytes signature; // 0x244 // Total length, excluding dynamic array data: 0x264 (580) } /** * @dev Basic orders can supply any number of additional recipients, with the * implied assumption that they are supplied from the offered ETH (or other * native token) or ERC20 token for the order. */ struct AdditionalRecipient { uint256 amount; address payable recipient; } /** * @dev The full set of order components, with the exception of the counter, * must be supplied when fulfilling more sophisticated orders or groups of * orders. The total number of original consideration items must also be * supplied, as the caller may specify additional consideration items. */ struct OrderParameters { address offerer; // 0x00 address zone; // 0x20 OfferItem[] offer; // 0x40 ConsiderationItem[] consideration; // 0x60 OrderType orderType; // 0x80 uint256 startTime; // 0xa0 uint256 endTime; // 0xc0 bytes32 zoneHash; // 0xe0 uint256 salt; // 0x100 bytes32 conduitKey; // 0x120 uint256 totalOriginalConsiderationItems; // 0x140 // offer.length // 0x160 } /** * @dev Orders require a signature in addition to the other order parameters. */ struct Order { OrderParameters parameters; bytes signature; } /** * @dev Advanced orders include a numerator (i.e. a fraction to attempt to fill) * and a denominator (the total size of the order) in addition to the * signature and other order parameters. It also supports an optional field * for supplying extra data; this data will be provided to the zone if the * order type is restricted and the zone is not the caller, or will be * provided to the offerer as context for contract order types. */ struct AdvancedOrder { OrderParameters parameters; uint120 numerator; uint120 denominator; bytes signature; bytes extraData; } /** * @dev Orders can be validated (either explicitly via `validate`, or as a * consequence of a full or partial fill), specifically cancelled (they can * also be cancelled in bulk via incrementing a per-zone counter), and * partially or fully filled (with the fraction filled represented by a * numerator and denominator). */ struct OrderStatus { bool isValidated; bool isCancelled; uint120 numerator; uint120 denominator; } /** * @dev A criteria resolver specifies an order, side (offer vs. consideration), * and item index. It then provides a chosen identifier (i.e. tokenId) * alongside a merkle proof demonstrating the identifier meets the required * criteria. */ struct CriteriaResolver { uint256 orderIndex; Side side; uint256 index; uint256 identifier; bytes32[] criteriaProof; } /** * @dev A fulfillment is applied to a group of orders. It decrements a series of * offer and consideration items, then generates a single execution * element. A given fulfillment can be applied to as many offer and * consideration items as desired, but must contain at least one offer and * at least one consideration that match. The fulfillment must also remain * consistent on all key parameters across all offer items (same offerer, * token, type, tokenId, and conduit preference) as well as across all * consideration items (token, type, tokenId, and recipient). */ struct Fulfillment { FulfillmentComponent[] offerComponents; FulfillmentComponent[] considerationComponents; } /** * @dev Each fulfillment component contains one index referencing a specific * order and another referencing a specific offer or consideration item. */ struct FulfillmentComponent { uint256 orderIndex; uint256 itemIndex; } /** * @dev An execution is triggered once all consideration items have been zeroed * out. It sends the item in question from the offerer to the item's * recipient, optionally sourcing approvals from either this contract * directly or from the offerer's chosen conduit if one is specified. An * execution is not provided as an argument, but rather is derived via * orders, criteria resolvers, and fulfillments (where the total number of * executions will be less than or equal to the total number of indicated * fulfillments) and returned as part of `matchOrders`. */ struct Execution { ReceivedItem item; address offerer; bytes32 conduitKey; } /** * @dev Restricted orders are validated post-execution by calling validateOrder * on the zone. This struct provides context about the order fulfillment * and any supplied extraData, as well as all order hashes fulfilled in a * call to a match or fulfillAvailable method. */ struct ZoneParameters { bytes32 orderHash; address fulfiller; address offerer; SpentItem[] offer; ReceivedItem[] consideration; bytes extraData; bytes32[] orderHashes; uint256 startTime; uint256 endTime; bytes32 zoneHash; } /** * @dev Zones and contract offerers can communicate which schemas they implement * along with any associated metadata related to each schema. */ struct Schema { uint256 id; bytes metadata; } using StructPointers for OrderComponents global; using StructPointers for OfferItem global; using StructPointers for ConsiderationItem global; using StructPointers for SpentItem global; using StructPointers for ReceivedItem global; using StructPointers for BasicOrderParameters global; using StructPointers for AdditionalRecipient global; using StructPointers for OrderParameters global; using StructPointers for Order global; using StructPointers for AdvancedOrder global; using StructPointers for OrderStatus global; using StructPointers for CriteriaResolver global; using StructPointers for Fulfillment global; using StructPointers for FulfillmentComponent global; using StructPointers for Execution global; using StructPointers for ZoneParameters global; /** * @dev This library provides a set of functions for converting structs to * pointers. */ library StructPointers { /** * @dev Get a MemoryPointer from OrderComponents. * * @param obj The OrderComponents object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( OrderComponents memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from OrderComponents. * * @param obj The OrderComponents object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( OrderComponents calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from OfferItem. * * @param obj The OfferItem object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( OfferItem memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from OfferItem. * * @param obj The OfferItem object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( OfferItem calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from ConsiderationItem. * * @param obj The ConsiderationItem object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( ConsiderationItem memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from ConsiderationItem. * * @param obj The ConsiderationItem object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( ConsiderationItem calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from SpentItem. * * @param obj The SpentItem object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( SpentItem memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from SpentItem. * * @param obj The SpentItem object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( SpentItem calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from ReceivedItem. * * @param obj The ReceivedItem object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( ReceivedItem memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from ReceivedItem. * * @param obj The ReceivedItem object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( ReceivedItem calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from BasicOrderParameters. * * @param obj The BasicOrderParameters object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( BasicOrderParameters memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from BasicOrderParameters. * * @param obj The BasicOrderParameters object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( BasicOrderParameters calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from AdditionalRecipient. * * @param obj The AdditionalRecipient object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( AdditionalRecipient memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from AdditionalRecipient. * * @param obj The AdditionalRecipient object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( AdditionalRecipient calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from OrderParameters. * * @param obj The OrderParameters object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( OrderParameters memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from OrderParameters. * * @param obj The OrderParameters object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( OrderParameters calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from Order. * * @param obj The Order object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( Order memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from Order. * * @param obj The Order object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( Order calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from AdvancedOrder. * * @param obj The AdvancedOrder object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( AdvancedOrder memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from AdvancedOrder. * * @param obj The AdvancedOrder object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( AdvancedOrder calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from OrderStatus. * * @param obj The OrderStatus object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( OrderStatus memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from OrderStatus. * * @param obj The OrderStatus object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( OrderStatus calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from CriteriaResolver. * * @param obj The CriteriaResolver object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( CriteriaResolver memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from CriteriaResolver. * * @param obj The CriteriaResolver object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( CriteriaResolver calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from Fulfillment. * * @param obj The Fulfillment object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( Fulfillment memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from Fulfillment. * * @param obj The Fulfillment object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( Fulfillment calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from FulfillmentComponent. * * @param obj The FulfillmentComponent object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( FulfillmentComponent memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from FulfillmentComponent. * * @param obj The FulfillmentComponent object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( FulfillmentComponent calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from Execution. * * @param obj The Execution object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( Execution memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from Execution. * * @param obj The Execution object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( Execution calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } /** * @dev Get a MemoryPointer from ZoneParameters. * * @param obj The ZoneParameters object. * * @return ptr The MemoryPointer. */ function toMemoryPointer( ZoneParameters memory obj ) internal pure returns (MemoryPointer ptr) { assembly { ptr := obj } } /** * @dev Get a CalldataPointer from ZoneParameters. * * @param obj The ZoneParameters object. * * @return ptr The CalldataPointer. */ function toCalldataPointer( ZoneParameters calldata obj ) internal pure returns (CalldataPointer ptr) { assembly { ptr := obj } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple ERC20 + EIP-2612 implementation. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol) abstract contract ERC20 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The total supply has overflowed. error TotalSupplyOverflow(); /// @dev The allowance has overflowed. error AllowanceOverflow(); /// @dev The allowance has underflowed. error AllowanceUnderflow(); /// @dev Insufficient balance. error InsufficientBalance(); /// @dev Insufficient allowance. error InsufficientAllowance(); /// @dev The permit is invalid. error InvalidPermit(); /// @dev The permit has expired. error PermitExpired(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Emitted when `amount` tokens is transferred from `from` to `to`. event Transfer(address indexed from, address indexed to, uint256 amount); /// @dev Emitted when `amount` tokens is approved by `owner` to be used by `spender`. event Approval(address indexed owner, address indexed spender, uint256 amount); /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`. uint256 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`. uint256 private constant _APPROVAL_EVENT_SIGNATURE = 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The storage slot for the total supply. uint256 private constant _TOTAL_SUPPLY_SLOT = 0x05345cdf77eb68f44c; /// @dev The balance slot of `owner` is given by: /// ``` /// mstore(0x0c, _BALANCE_SLOT_SEED) /// mstore(0x00, owner) /// let balanceSlot := keccak256(0x0c, 0x20) /// ``` uint256 private constant _BALANCE_SLOT_SEED = 0x87a211a2; /// @dev The allowance slot of (`owner`, `spender`) is given by: /// ``` /// mstore(0x20, spender) /// mstore(0x0c, _ALLOWANCE_SLOT_SEED) /// mstore(0x00, owner) /// let allowanceSlot := keccak256(0x0c, 0x34) /// ``` uint256 private constant _ALLOWANCE_SLOT_SEED = 0x7f5e9f20; /// @dev The nonce slot of `owner` is given by: /// ``` /// mstore(0x0c, _NONCES_SLOT_SEED) /// mstore(0x00, owner) /// let nonceSlot := keccak256(0x0c, 0x20) /// ``` uint256 private constant _NONCES_SLOT_SEED = 0x38377508; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 METADATA */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the name of the token. function name() public view virtual returns (string memory); /// @dev Returns the symbol of the token. function symbol() public view virtual returns (string memory); /// @dev Returns the decimals places of the token. function decimals() public view virtual returns (uint8) { return 18; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the amount of tokens in existence. function totalSupply() public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { result := sload(_TOTAL_SUPPLY_SLOT) } } /// @dev Returns the amount of tokens owned by `owner`. function balanceOf(address owner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x20)) } } /// @dev Returns the amount of tokens that `spender` can spend on behalf of `owner`. function allowance(address owner, address spender) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x34)) } } /// @dev Sets `amount` as the allowance of `spender` over the caller's tokens. /// /// Emits a {Approval} event. function approve(address spender, uint256 amount) public virtual returns (bool) { /// @solidity memory-safe-assembly assembly { // Compute the allowance slot and store the amount. mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x34), amount) // Emit the {Approval} event. mstore(0x00, amount) log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c))) } return true; } /// @dev Atomically increases the allowance granted to `spender` by the caller. /// /// Emits a {Approval} event. function increaseAllowance(address spender, uint256 difference) public virtual returns (bool) { /// @solidity memory-safe-assembly assembly { // Compute the allowance slot and load its value. mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, caller()) let allowanceSlot := keccak256(0x0c, 0x34) let allowanceBefore := sload(allowanceSlot) // Add to the allowance. let allowanceAfter := add(allowanceBefore, difference) // Revert upon overflow. if lt(allowanceAfter, allowanceBefore) { mstore(0x00, 0xf9067066) // `AllowanceOverflow()`. revert(0x1c, 0x04) } // Store the updated allowance. sstore(allowanceSlot, allowanceAfter) // Emit the {Approval} event. mstore(0x00, allowanceAfter) log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c))) } return true; } /// @dev Atomically decreases the allowance granted to `spender` by the caller. /// /// Emits a {Approval} event. function decreaseAllowance(address spender, uint256 difference) public virtual returns (bool) { /// @solidity memory-safe-assembly assembly { // Compute the allowance slot and load its value. mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, caller()) let allowanceSlot := keccak256(0x0c, 0x34) let allowanceBefore := sload(allowanceSlot) // Revert if will underflow. if lt(allowanceBefore, difference) { mstore(0x00, 0x8301ab38) // `AllowanceUnderflow()`. revert(0x1c, 0x04) } // Subtract and store the updated allowance. let allowanceAfter := sub(allowanceBefore, difference) sstore(allowanceSlot, allowanceAfter) // Emit the {Approval} event. mstore(0x00, allowanceAfter) log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, caller(), shr(96, mload(0x2c))) } return true; } /// @dev Transfer `amount` tokens from the caller to `to`. /// /// Requirements: /// - `from` must at least have `amount`. /// /// Emits a {Transfer} event. function transfer(address to, uint256 amount) public virtual returns (bool) { _beforeTokenTransfer(msg.sender, to, amount); /// @solidity memory-safe-assembly assembly { // Compute the balance slot and load its value. mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, caller()) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, caller(), shr(96, mload(0x0c))) } _afterTokenTransfer(msg.sender, to, amount); return true; } /// @dev Transfers `amount` tokens from `from` to `to`. /// /// Note: does not update the allowance if it is the maximum uint256 value. /// /// Requirements: /// - `from` must at least have `amount`. /// - The caller must have at least `amount` of allowance to transfer the tokens of `from`. /// /// Emits a {Transfer} event. function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) { _beforeTokenTransfer(from, to, amount); /// @solidity memory-safe-assembly assembly { let from_ := shl(96, from) // Compute the allowance slot and load its value. mstore(0x20, caller()) mstore(0x0c, or(from_, _ALLOWANCE_SLOT_SEED)) let allowanceSlot := keccak256(0x0c, 0x34) let allowance_ := sload(allowanceSlot) // If the allowance is not the maximum uint256 value. if iszero(eq(allowance_, not(0))) { // Revert if the amount to be transferred exceeds the allowance. if gt(amount, allowance_) { mstore(0x00, 0x13be252b) // `InsufficientAllowance()`. revert(0x1c, 0x04) } // Subtract and store the updated allowance. sstore(allowanceSlot, sub(allowance_, amount)) } // Compute the balance slot and load its value. mstore(0x0c, or(from_, _BALANCE_SLOT_SEED)) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c))) } _afterTokenTransfer(from, to, amount); return true; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EIP-2612 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the current nonce for `owner`. /// This value is used to compute the signature for EIP-2612 permit. function nonces(address owner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the nonce slot and load its value. mstore(0x0c, _NONCES_SLOT_SEED) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x20)) } } /// @dev Sets `value` as the allowance of `spender` over the tokens of `owner`, /// authorized by a signed approval by `owner`. /// /// Emits a {Approval} event. function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { bytes32 domainSeparator = DOMAIN_SEPARATOR(); /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. let m := mload(0x40) // Revert if the block timestamp greater than `deadline`. if gt(timestamp(), deadline) { mstore(0x00, 0x1a15a3cc) // `PermitExpired()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. owner := shr(96, shl(96, owner)) spender := shr(96, shl(96, spender)) // Compute the nonce slot and load its value. mstore(0x0c, _NONCES_SLOT_SEED) mstore(0x00, owner) let nonceSlot := keccak256(0x0c, 0x20) let nonceValue := sload(nonceSlot) // Increment and store the updated nonce. sstore(nonceSlot, add(nonceValue, 1)) // Prepare the inner hash. // `keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)")`. // forgefmt: disable-next-item mstore(m, 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9) mstore(add(m, 0x20), owner) mstore(add(m, 0x40), spender) mstore(add(m, 0x60), value) mstore(add(m, 0x80), nonceValue) mstore(add(m, 0xa0), deadline) // Prepare the outer hash. mstore(0, 0x1901) mstore(0x20, domainSeparator) mstore(0x40, keccak256(m, 0xc0)) // Prepare the ecrecover calldata. mstore(0, keccak256(0x1e, 0x42)) mstore(0x20, and(0xff, v)) mstore(0x40, r) mstore(0x60, s) pop(staticcall(gas(), 1, 0, 0x80, 0x20, 0x20)) // If the ecrecover fails, the returndatasize will be 0x00, // `owner` will be be checked if it equals the hash at 0x00, // which evaluates to false (i.e. 0), and we will revert. // If the ecrecover succeeds, the returndatasize will be 0x20, // `owner` will be compared against the returned address at 0x20. if iszero(eq(mload(returndatasize()), owner)) { mstore(0x00, 0xddafbaef) // `InvalidPermit()`. revert(0x1c, 0x04) } // Compute the allowance slot and store the value. // The `owner` is already at slot 0x20. mstore(0x40, or(shl(160, _ALLOWANCE_SLOT_SEED), spender)) sstore(keccak256(0x2c, 0x34), value) // Emit the {Approval} event. log3(add(m, 0x60), 0x20, _APPROVAL_EVENT_SIGNATURE, owner, spender) mstore(0x40, m) // Restore the free memory pointer. mstore(0x60, 0) // Restore the zero pointer. } } /// @dev Returns the EIP-2612 domains separator. function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) // Grab the free memory pointer. } // We simply calculate it on-the-fly to allow for cases where the `name` may change. bytes32 nameHash = keccak256(bytes(name())); /// @solidity memory-safe-assembly assembly { let m := result // `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`. // forgefmt: disable-next-item mstore(m, 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f) mstore(add(m, 0x20), nameHash) // `keccak256("1")`. // forgefmt: disable-next-item mstore(add(m, 0x40), 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) result := keccak256(m, 0xa0) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL MINT FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Mints `amount` tokens to `to`, increasing the total supply. /// /// Emits a {Transfer} event. function _mint(address to, uint256 amount) internal virtual { _beforeTokenTransfer(address(0), to, amount); /// @solidity memory-safe-assembly assembly { let totalSupplyBefore := sload(_TOTAL_SUPPLY_SLOT) let totalSupplyAfter := add(totalSupplyBefore, amount) // Revert if the total supply overflows. if lt(totalSupplyAfter, totalSupplyBefore) { mstore(0x00, 0xe5cfe957) // `TotalSupplyOverflow()`. revert(0x1c, 0x04) } // Store the updated total supply. sstore(_TOTAL_SUPPLY_SLOT, totalSupplyAfter) // Compute the balance slot and load its value. mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, 0, shr(96, mload(0x0c))) } _afterTokenTransfer(address(0), to, amount); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL BURN FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Burns `amount` tokens from `from`, reducing the total supply. /// /// Emits a {Transfer} event. function _burn(address from, uint256 amount) internal virtual { _beforeTokenTransfer(from, address(0), amount); /// @solidity memory-safe-assembly assembly { // Compute the balance slot and load its value. mstore(0x0c, _BALANCE_SLOT_SEED) mstore(0x00, from) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Subtract and store the updated total supply. sstore(_TOTAL_SUPPLY_SLOT, sub(sload(_TOTAL_SUPPLY_SLOT), amount)) // Emit the {Transfer} event. mstore(0x00, amount) log3(0x00, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, shl(96, from)), 0) } _afterTokenTransfer(from, address(0), amount); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL TRANSFER FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Moves `amount` of tokens from `from` to `to`. function _transfer(address from, address to, uint256 amount) internal virtual { _beforeTokenTransfer(from, to, amount); /// @solidity memory-safe-assembly assembly { let from_ := shl(96, from) // Compute the balance slot and load its value. mstore(0x0c, or(from_, _BALANCE_SLOT_SEED)) let fromBalanceSlot := keccak256(0x0c, 0x20) let fromBalance := sload(fromBalanceSlot) // Revert if insufficient balance. if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } // Subtract and store the updated balance. sstore(fromBalanceSlot, sub(fromBalance, amount)) // Compute the balance slot of `to`. mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x20) // Add and store the updated balance of `to`. // Will not overflow because the sum of all user balances // cannot exceed the maximum uint256 value. sstore(toBalanceSlot, add(sload(toBalanceSlot), amount)) // Emit the {Transfer} event. mstore(0x20, amount) log3(0x20, 0x20, _TRANSFER_EVENT_SIGNATURE, shr(96, from_), shr(96, mload(0x0c))) } _afterTokenTransfer(from, to, amount); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL ALLOWANCE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Updates the allowance of `owner` for `spender` based on spent `amount`. function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { /// @solidity memory-safe-assembly assembly { // Compute the allowance slot and load its value. mstore(0x20, spender) mstore(0x0c, _ALLOWANCE_SLOT_SEED) mstore(0x00, owner) let allowanceSlot := keccak256(0x0c, 0x34) let allowance_ := sload(allowanceSlot) // If the allowance is not the maximum uint256 value. if iszero(eq(allowance_, not(0))) { // Revert if the amount to be transferred exceeds the allowance. if gt(amount, allowance_) { mstore(0x00, 0x13be252b) // `InsufficientAllowance()`. revert(0x1c, 0x04) } // Subtract and store the updated allowance. sstore(allowanceSlot, sub(allowance_, amount)) } } } /// @dev Sets `amount` as the allowance of `spender` over the tokens of `owner`. /// /// Emits a {Approval} event. function _approve(address owner, address spender, uint256 amount) internal virtual { /// @solidity memory-safe-assembly assembly { let owner_ := shl(96, owner) // Compute the allowance slot and store the amount. mstore(0x20, spender) mstore(0x0c, or(owner_, _ALLOWANCE_SLOT_SEED)) sstore(keccak256(0x0c, 0x34), amount) // Emit the {Approval} event. mstore(0x00, amount) log3(0x00, 0x20, _APPROVAL_EVENT_SIGNATURE, shr(96, owner_), shr(96, mload(0x2c))) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HOOKS TO OVERRIDE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Hook that is called before any transfer of tokens. /// This includes minting and burning. function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /// @dev Hook that is called after any transfer of tokens. /// This includes minting and burning. function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple ERC721 implementation with storage hitchhiking. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC721.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC721/ERC721.sol) abstract contract ERC721 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev An account can hold up to 4294967295 tokens. uint256 internal constant _MAX_ACCOUNT_BALANCE = 0xffffffff; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Only the token owner or an approved account can manage the token. error NotOwnerNorApproved(); /// @dev The token does not exist. error TokenDoesNotExist(); /// @dev The token already exists. error TokenAlreadyExists(); /// @dev Cannot query the balance for the zero address. error BalanceQueryForZeroAddress(); /// @dev Cannot mint or transfer to the zero address. error TransferToZeroAddress(); /// @dev The token must be owned by `from`. error TransferFromIncorrectOwner(); /// @dev The recipient's balance has overflowed. error AccountBalanceOverflow(); /// @dev Cannot safely transfer to a contract that does not implement /// the ERC721Receiver interface. error TransferToNonERC721ReceiverImplementer(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Emitted when token `id` is transferred from `from` to `to`. event Transfer(address indexed from, address indexed to, uint256 indexed id); /// @dev Emitted when `owner` enables `account` to manage the `id` token. event Approval(address indexed owner, address indexed account, uint256 indexed id); /// @dev Emitted when `owner` enables or disables `operator` to manage all of their tokens. event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved); /// @dev `keccak256(bytes("Transfer(address,address,uint256)"))`. uint256 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; /// @dev `keccak256(bytes("Approval(address,address,uint256)"))`. uint256 private constant _APPROVAL_EVENT_SIGNATURE = 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925; /// @dev `keccak256(bytes("ApprovalForAll(address,address,bool)"))`. uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE = 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership data slot of `id` is given by: /// ``` /// mstore(0x00, id) /// mstore(0x1c, _ERC721_MASTER_SLOT_SEED) /// let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) /// ``` /// Bits Layout: // - [0..159] `addr` // - [160..223] `extraData` /// /// The approved address slot is given by: `add(1, ownershipSlot)`. /// /// See: https://notes.ethereum.org/%40vbuterin/verkle_tree_eip /// /// The balance slot of `owner` is given by: /// ``` /// mstore(0x1c, _ERC721_MASTER_SLOT_SEED) /// mstore(0x00, owner) /// let balanceSlot := keccak256(0x0c, 0x1c) /// ``` /// Bits Layout: /// - [0..31] `balance` /// - [32..225] `aux` /// /// The `operator` approval slot of `owner` is given by: /// ``` /// mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator)) /// mstore(0x00, owner) /// let operatorApprovalSlot := keccak256(0x0c, 0x30) /// ``` uint256 private constant _ERC721_MASTER_SLOT_SEED = 0x7d8825530a5a2e7a << 192; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC721 METADATA */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the token collection name. function name() public view virtual returns (string memory); /// @dev Returns the token collection symbol. function symbol() public view virtual returns (string memory); /// @dev Returns the Uniform Resource Identifier (URI) for token `id`. function tokenURI(uint256 id) public view virtual returns (string memory); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC721 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of token `id`. /// /// Requirements: /// - Token `id` must exist. function ownerOf(uint256 id) public view virtual returns (address result) { result = _ownerOf(id); /// @solidity memory-safe-assembly assembly { if iszero(result) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } } } /// @dev Returns the number of tokens owned by `owner`. /// /// Requirements: /// - `owner` must not be the zero address. function balanceOf(address owner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Revert if the `owner` is the zero address. if iszero(owner) { mstore(0x00, 0x8f4eb604) // `BalanceQueryForZeroAddress()`. revert(0x1c, 0x04) } mstore(0x1c, _ERC721_MASTER_SLOT_SEED) mstore(0x00, owner) result := and(sload(keccak256(0x0c, 0x1c)), _MAX_ACCOUNT_BALANCE) } } /// @dev Returns the account approved to managed token `id`. /// /// Requirements: /// - Token `id` must exist. function getApproved(uint256 id) public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) if iszero(shr(96, shl(96, sload(ownershipSlot)))) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } result := sload(add(1, ownershipSlot)) } } /// @dev Sets `account` as the approved account to manage token `id`. /// /// Requirements: /// - Token `id` must exist. /// - The caller must be the owner of the token, /// or an approved operator for the token owner. /// /// Emits a {Approval} event. function approve(address account, uint256 id) public payable virtual { _approve(msg.sender, account, id); } /// @dev Returns whether `operator` is approved to manage the tokens of `owner`. function isApprovedForAll(address owner, address operator) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, shr(96, shl(96, operator)))) mstore(0x00, owner) result := sload(keccak256(0x0c, 0x30)) } } /// @dev Sets whether `operator` is approved to manage the tokens of the caller. /// /// Emits a {ApprovalForAll} event. function setApprovalForAll(address operator, bool isApproved) public virtual { /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. operator := shr(96, shl(96, operator)) // Convert to 0 or 1. isApproved := iszero(iszero(isApproved)) // Update the `isApproved` for (`msg.sender`, `operator`). mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator)) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x30), isApproved) // Emit the {ApprovalForAll} event. mstore(0x00, isApproved) log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), operator) } } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - The caller must be the owner of the token, or be approved to manage the token. /// /// Emits a {Transfer} event. function transferFrom(address from, address to, uint256 id) public payable virtual { _beforeTokenTransfer(from, to, id); /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. let bitmaskAddress := shr(96, not(0)) from := and(bitmaskAddress, from) to := and(bitmaskAddress, to) // Load the ownership data. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, caller())) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let ownershipPacked := sload(ownershipSlot) let owner := and(bitmaskAddress, ownershipPacked) // Revert if `from` is not the owner, or does not exist. if iszero(mul(owner, eq(owner, from))) { if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`. revert(0x1c, 0x04) } // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Load, check, and update the token approval. { mstore(0x00, from) let approvedAddress := sload(add(1, ownershipSlot)) // Revert if the caller is not the owner, nor approved. if iszero(or(eq(caller(), from), eq(caller(), approvedAddress))) { if iszero(sload(keccak256(0x0c, 0x30))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Delete the approved address if any. if approvedAddress { sstore(add(1, ownershipSlot), 0) } } // Update with the new owner. sstore(ownershipSlot, xor(ownershipPacked, xor(from, to))) // Decrement the balance of `from`. { let fromBalanceSlot := keccak256(0x0c, 0x1c) sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1)) } // Increment the balance of `to`. { mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x1c) let toBalanceSlotPacked := add(sload(toBalanceSlot), 1) if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceSlotPacked) } // Emit the {Transfer} event. log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id) } _afterTokenTransfer(from, to, id); } /// @dev Equivalent to `safeTransferFrom(from, to, id, "")`. function safeTransferFrom(address from, address to, uint256 id) public payable virtual { transferFrom(from, to, id); if (_hasCode(to)) _checkOnERC721Received(from, to, id, ""); } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - The caller must be the owner of the token, or be approved to manage the token. /// - 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 id, bytes calldata data) public payable virtual { transferFrom(from, to, id); if (_hasCode(to)) _checkOnERC721Received(from, to, id, data); } /// @dev Returns true if this contract implements the interface defined by `interfaceId`. /// See: https://eips.ethereum.org/EIPS/eip-165 /// This function call must use less than 30000 gas. function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { let s := shr(224, interfaceId) // ERC165: 0x01ffc9a7, ERC721: 0x80ac58cd, ERC721Metadata: 0x5b5e139f. result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x80ac58cd)), eq(s, 0x5b5e139f)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL QUERY FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns if token `id` exists. function _exists(uint256 id) internal view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) result := shl(96, sload(add(id, add(id, keccak256(0x00, 0x20))))) } } /// @dev Returns the owner of token `id`. /// Returns the zero address instead of reverting if the token does not exist. function _ownerOf(uint256 id) internal view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) result := shr(96, shl(96, sload(add(id, add(id, keccak256(0x00, 0x20)))))) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL DATA HITCHHIKING FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the auxiliary data for `owner`. /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data. /// Auxiliary data can be set for any address, even if it does not have any tokens. function _getAux(address owner) internal view virtual returns (uint224 result) { /// @solidity memory-safe-assembly assembly { mstore(0x1c, _ERC721_MASTER_SLOT_SEED) mstore(0x00, owner) result := shr(32, sload(keccak256(0x0c, 0x1c))) } } /// @dev Set the auxiliary data for `owner` to `value`. /// Minting, transferring, burning the tokens of `owner` will not change the auxiliary data. /// Auxiliary data can be set for any address, even if it does not have any tokens. function _setAux(address owner, uint224 value) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x1c, _ERC721_MASTER_SLOT_SEED) mstore(0x00, owner) let balanceSlot := keccak256(0x0c, 0x1c) let packed := sload(balanceSlot) sstore(balanceSlot, xor(packed, shl(32, xor(value, shr(32, packed))))) } } /// @dev Returns the extra data for token `id`. /// Minting, transferring, burning a token will not change the extra data. /// The extra data can be set on a non existent token. function _getExtraData(uint256 id) internal view virtual returns (uint96 result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) result := shr(160, sload(add(id, add(id, keccak256(0x00, 0x20))))) } } /// @dev Sets the extra data for token `id` to `value`. /// Minting, transferring, burning a token will not change the extra data. /// The extra data can be set on a non existent token. function _setExtraData(uint256 id, uint96 value) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let packed := sload(ownershipSlot) sstore(ownershipSlot, xor(packed, shl(160, xor(value, shr(160, packed))))) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL MINT FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Mints token `id` to `to`. /// /// Requirements: /// /// - Token `id` must not exist. /// - `to` cannot be the zero address. /// /// Emits a {Transfer} event. function _mint(address to, uint256 id) internal virtual { _beforeTokenTransfer(address(0), to, id); /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. to := shr(96, shl(96, to)) // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Load the ownership data. mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let ownershipPacked := sload(ownershipSlot) // Revert if the token already exists. if shl(96, ownershipPacked) { mstore(0x00, 0xc991cbb1) // `TokenAlreadyExists()`. revert(0x1c, 0x04) } // Update with the owner. sstore(ownershipSlot, or(ownershipPacked, to)) // Increment the balance of the owner. { mstore(0x00, to) let balanceSlot := keccak256(0x0c, 0x1c) let balanceSlotPacked := add(sload(balanceSlot), 1) if iszero(and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE)) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(balanceSlot, balanceSlotPacked) } // Emit the {Transfer} event. log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, 0, to, id) } _afterTokenTransfer(address(0), to, id); } /// @dev Equivalent to `_safeMint(to, id, "")`. function _safeMint(address to, uint256 id) internal virtual { _safeMint(to, id, ""); } /// @dev Mints token `id` to `to`. /// /// Requirements: /// /// - Token `id` must not exist. /// - `to` cannot be the zero address. /// - If `to` refers to a smart contract, it must implement /// {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. /// /// Emits a {Transfer} event. function _safeMint(address to, uint256 id, bytes memory data) internal virtual { _mint(to, id); if (_hasCode(to)) _checkOnERC721Received(address(0), to, id, data); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL BURN FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `_burn(address(0), id)`. function _burn(uint256 id) internal virtual { _burn(address(0), id); } /// @dev Destroys token `id`, using `by`. /// /// Requirements: /// /// - Token `id` must exist. /// - If `by` is not the zero address, /// it must be the owner of the token, or be approved to manage the token. /// /// Emits a {Transfer} event. function _burn(address by, uint256 id) internal virtual { address owner = ownerOf(id); _beforeTokenTransfer(owner, address(0), id); /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. by := shr(96, shl(96, by)) // Load the ownership data. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by)) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let ownershipPacked := sload(ownershipSlot) // Reload the owner in case it is changed in `_beforeTokenTransfer`. owner := shr(96, shl(96, ownershipPacked)) // Revert if the token does not exist. if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } // Load and check the token approval. { mstore(0x00, owner) let approvedAddress := sload(add(1, ownershipSlot)) // If `by` is not the zero address, do the authorization check. // Revert if the `by` is not the owner, nor approved. if iszero(or(iszero(by), or(eq(by, owner), eq(by, approvedAddress)))) { if iszero(sload(keccak256(0x0c, 0x30))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Delete the approved address if any. if approvedAddress { sstore(add(1, ownershipSlot), 0) } } // Clear the owner. sstore(ownershipSlot, xor(ownershipPacked, owner)) // Decrement the balance of `owner`. { let balanceSlot := keccak256(0x0c, 0x1c) sstore(balanceSlot, sub(sload(balanceSlot), 1)) } // Emit the {Transfer} event. log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, owner, 0, id) } _afterTokenTransfer(owner, address(0), id); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL APPROVAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `account` is the owner of token `id`, or is approved to managed it. /// /// Requirements: /// - Token `id` must exist. function _isApprovedOrOwner(address account, uint256 id) internal view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { result := 1 // Clear the upper 96 bits. account := shr(96, shl(96, account)) // Load the ownership data. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, account)) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let owner := shr(96, shl(96, sload(ownershipSlot))) // Revert if the token does not exist. if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } // Check if `account` is the `owner`. if iszero(eq(account, owner)) { mstore(0x00, owner) // Check if `account` is approved to if iszero(sload(keccak256(0x0c, 0x30))) { result := eq(account, sload(add(1, ownershipSlot))) } } } } /// @dev Returns the account approved to manage token `id`. /// Returns the zero address instead of reverting if the token does not exist. function _getApproved(uint256 id) internal view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, id) mstore(0x1c, _ERC721_MASTER_SLOT_SEED) result := sload(add(1, add(id, add(id, keccak256(0x00, 0x20))))) } } /// @dev Equivalent to `_approve(address(0), account, id)`. function _approve(address account, uint256 id) internal virtual { _approve(address(0), account, id); } /// @dev Sets `account` as the approved account to manage token `id`, using `by`. /// /// Requirements: /// - Token `id` must exist. /// - If `by` is not the zero address, `by` must be the owner /// or an approved operator for the token owner. /// /// Emits a {Transfer} event. function _approve(address by, address account, uint256 id) internal virtual { assembly { // Clear the upper 96 bits. let bitmaskAddress := shr(96, not(0)) account := and(bitmaskAddress, account) by := and(bitmaskAddress, by) // Load the owner of the token. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by)) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let owner := and(bitmaskAddress, sload(ownershipSlot)) // Revert if the token does not exist. if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } // If `by` is not the zero address, do the authorization check. // Revert if `by` is not the owner, nor approved. if iszero(or(iszero(by), eq(by, owner))) { mstore(0x00, owner) if iszero(sload(keccak256(0x0c, 0x30))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Sets `account` as the approved account to manage `id`. sstore(add(1, ownershipSlot), account) // Emit the {Approval} event. log4(0x00, 0x00, _APPROVAL_EVENT_SIGNATURE, owner, account, id) } } /// @dev Approve or remove the `operator` as an operator for `by`, /// without authorization checks. /// /// Emits a {ApprovalForAll} event. function _setApprovalForAll(address by, address operator, bool isApproved) internal virtual { /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. by := shr(96, shl(96, by)) operator := shr(96, shl(96, operator)) // Convert to 0 or 1. isApproved := iszero(iszero(isApproved)) // Update the `isApproved` for (`by`, `operator`). mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, operator)) mstore(0x00, by) sstore(keccak256(0x0c, 0x30), isApproved) // Emit the {ApprovalForAll} event. mstore(0x00, isApproved) log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, by, operator) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL TRANSFER FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `_transfer(address(0), from, to, id)`. function _transfer(address from, address to, uint256 id) internal virtual { _transfer(address(0), from, to, id); } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - If `by` is not the zero address, /// it must be the owner of the token, or be approved to manage the token. /// /// Emits a {Transfer} event. function _transfer(address by, address from, address to, uint256 id) internal virtual { _beforeTokenTransfer(from, to, id); /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. let bitmaskAddress := shr(96, not(0)) from := and(bitmaskAddress, from) to := and(bitmaskAddress, to) by := and(bitmaskAddress, by) // Load the ownership data. mstore(0x00, id) mstore(0x1c, or(_ERC721_MASTER_SLOT_SEED, by)) let ownershipSlot := add(id, add(id, keccak256(0x00, 0x20))) let ownershipPacked := sload(ownershipSlot) let owner := and(bitmaskAddress, ownershipPacked) // Revert if `from` is not the owner, or does not exist. if iszero(mul(owner, eq(owner, from))) { if iszero(owner) { mstore(0x00, 0xceea21b6) // `TokenDoesNotExist()`. revert(0x1c, 0x04) } mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`. revert(0x1c, 0x04) } // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Load, check, and update the token approval. { mstore(0x00, from) let approvedAddress := sload(add(1, ownershipSlot)) // If `by` is not the zero address, do the authorization check. // Revert if the `by` is not the owner, nor approved. if iszero(or(iszero(by), or(eq(by, from), eq(by, approvedAddress)))) { if iszero(sload(keccak256(0x0c, 0x30))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Delete the approved address if any. if approvedAddress { sstore(add(1, ownershipSlot), 0) } } // Update with the new owner. sstore(ownershipSlot, xor(ownershipPacked, xor(from, to))) // Decrement the balance of `from`. { let fromBalanceSlot := keccak256(0x0c, 0x1c) sstore(fromBalanceSlot, sub(sload(fromBalanceSlot), 1)) } // Increment the balance of `to`. { mstore(0x00, to) let toBalanceSlot := keccak256(0x0c, 0x1c) let toBalanceSlotPacked := add(sload(toBalanceSlot), 1) if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceSlotPacked) } // Emit the {Transfer} event. log4(0x00, 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id) } _afterTokenTransfer(from, to, id); } /// @dev Equivalent to `_safeTransfer(from, to, id, "")`. function _safeTransfer(address from, address to, uint256 id) internal virtual { _safeTransfer(from, to, id, ""); } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - The caller must be the owner of the token, or be approved to manage the token. /// - If `to` refers to a smart contract, it must implement /// {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. /// /// Emits a {Transfer} event. function _safeTransfer(address from, address to, uint256 id, bytes memory data) internal virtual { _transfer(address(0), from, to, id); if (_hasCode(to)) _checkOnERC721Received(from, to, id, data); } /// @dev Equivalent to `_safeTransfer(by, from, to, id, "")`. function _safeTransfer(address by, address from, address to, uint256 id) internal virtual { _safeTransfer(by, from, to, id, ""); } /// @dev Transfers token `id` from `from` to `to`. /// /// Requirements: /// /// - Token `id` must exist. /// - `from` must be the owner of the token. /// - `to` cannot be the zero address. /// - If `by` is not the zero address, /// it must be the owner of the token, or be approved to manage the token. /// - If `to` refers to a smart contract, it must implement /// {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. /// /// Emits a {Transfer} event. function _safeTransfer(address by, address from, address to, uint256 id, bytes memory data) internal virtual { _transfer(by, from, to, id); if (_hasCode(to)) _checkOnERC721Received(from, to, id, data); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HOOKS FOR OVERRIDING */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Hook that is called before any token transfers, including minting and burning. function _beforeTokenTransfer(address from, address to, uint256 id) internal virtual {} /// @dev Hook that is called after any token transfers, including minting and burning. function _afterTokenTransfer(address from, address to, uint256 id) internal virtual {} /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns if `a` has bytecode of non-zero length. function _hasCode(address a) private view returns (bool result) { /// @solidity memory-safe-assembly assembly { result := extcodesize(a) // Can handle dirty upper bits. } } /// @dev Perform a call to invoke {IERC721Receiver-onERC721Received} on `to`. /// Reverts if the target does not support the function correctly. function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data) private { /// @solidity memory-safe-assembly assembly { // Prepare the calldata. let m := mload(0x40) let onERC721ReceivedSelector := 0x150b7a02 mstore(m, onERC721ReceivedSelector) mstore(add(m, 0x20), caller()) // The `operator`, which is always `msg.sender`. mstore(add(m, 0x40), shr(96, shl(96, from))) mstore(add(m, 0x60), id) mstore(add(m, 0x80), 0x80) let n := mload(data) mstore(add(m, 0xa0), n) if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xc0), n)) } // Revert if the call reverts. if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), m, 0x20)) { if returndatasize() { // Bubble up the revert if the delegatecall reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } mstore(m, 0) } // Load the returndata and compare it. if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) { mstore(0x00, 0xd1a57ed6) // `TransferToNonERC721ReceiverImplementer()`. revert(0x1c, 0x04) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple ERC1155 implementation. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC1155.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC1155/ERC1155.sol) abstract contract ERC1155 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The lengths of the input arrays are not the same. error ArrayLengthsMismatch(); /// @dev Cannot mint or transfer to the zero address. error TransferToZeroAddress(); /// @dev The recipient's balance has overflowed. error AccountBalanceOverflow(); /// @dev Insufficient balance. error InsufficientBalance(); /// @dev Only the token owner or an approved account can manage the tokens. error NotOwnerNorApproved(); /// @dev Cannot safely transfer to a contract that does not implement /// the ERC1155Receiver interface. error TransferToNonERC1155ReceiverImplementer(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Emitted when `amount` of token `id` is transferred /// from `from` to `to` by `operator`. event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); /// @dev Emitted when `amounts` of token `ids` are transferred /// from `from` to `to` by `operator`. event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); /// @dev Emitted when `owner` enables or disables `operator` to manage all of their tokens. event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved); /// @dev Emitted when the Uniform Resource Identifier (URI) for token `id` /// is updated to `value`. This event is not used in the base contract. /// You may need to emit this event depending on your URI logic. /// /// See: https://eips.ethereum.org/EIPS/eip-1155#metadata event URI(string value, uint256 indexed id); /// @dev `keccak256(bytes("TransferSingle(address,address,address,uint256,uint256)"))`. uint256 private constant _TRANSFER_SINGLE_EVENT_SIGNATURE = 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62; /// @dev `keccak256(bytes("TransferBatch(address,address,address,uint256[],uint256[])"))`. uint256 private constant _TRANSFER_BATCH_EVENT_SIGNATURE = 0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb; /// @dev `keccak256(bytes("ApprovalForAll(address,address,bool)"))`. uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE = 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The `ownerSlotSeed` of a given owner is given by. /// ``` /// let ownerSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, owner)) /// ``` /// /// The balance slot of `owner` is given by. /// ``` /// mstore(0x20, ownerSlotSeed) /// mstore(0x00, id) /// let balanceSlot := keccak256(0x00, 0x40) /// ``` /// /// The operator approval slot of `owner` is given by. /// ``` /// mstore(0x20, ownerSlotSeed) /// mstore(0x00, operator) /// let operatorApprovalSlot := keccak256(0x0c, 0x34) /// ``` uint256 private constant _ERC1155_MASTER_SLOT_SEED = 0x9a31110384e0b0c9; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC1155 METADATA */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the URI for token `id`. /// /// You can either return the same templated URI for all token IDs, /// (e.g. "https://example.com/api/{id}.json"), /// or return a unique URI for each `id`. /// /// See: https://eips.ethereum.org/EIPS/eip-1155#metadata function uri(uint256 id) public view virtual returns (string memory); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC1155 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the amount of `id` owned by `owner`. function balanceOf(address owner, uint256 id) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, shl(96, owner))) mstore(0x00, id) result := sload(keccak256(0x00, 0x40)) } } /// @dev Returns whether `operator` is approved to manage the tokens of `owner`. function isApprovedForAll(address owner, address operator) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, shl(96, owner))) mstore(0x00, operator) result := sload(keccak256(0x0c, 0x34)) } } /// @dev Sets whether `operator` is approved to manage the tokens of the caller. /// /// Emits a {ApprovalForAll} event. function setApprovalForAll(address operator, bool isApproved) public virtual { /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. operator := shr(96, shl(96, operator)) // Convert to 0 or 1. isApproved := iszero(iszero(isApproved)) // Update the `isApproved` for (`msg.sender`, `operator`). mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, shl(96, caller()))) mstore(0x00, operator) sstore(keccak256(0x0c, 0x34), isApproved) // Emit the {ApprovalForAll} event. mstore(0x00, isApproved) log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), operator) } } /// @dev Transfers `amount` of `id` from `from` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `from` must have at least `amount` of `id`. /// - If the caller is not `from`, /// it must be approved to manage the tokens of `from`. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155Reveived}, which is called upon a batch transfer. /// /// Emits a {Transfer} event. function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, to, _single(id), _single(amount), data); } /// @solidity memory-safe-assembly assembly { let fromSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, from)) let toSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, to)) mstore(0x20, fromSlotSeed) // Clear the upper 96 bits. from := shr(96, fromSlotSeed) to := shr(96, toSlotSeed) // If the caller is not `from`, do the authorization check. if iszero(eq(caller(), from)) { mstore(0x00, caller()) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Subtract and store the updated balance of `from`. { mstore(0x00, id) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Increase and store the updated balance of `to`. { mstore(0x20, toSlotSeed) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } // Emit a {TransferSingle} event. { mstore(0x20, amount) log4(0x00, 0x40, _TRANSFER_SINGLE_EVENT_SIGNATURE, caller(), from, to) } } if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, to, _single(id), _single(amount), data); } /// @solidity memory-safe-assembly assembly { // Do the {onERC1155Received} check if `to` is a smart contract. if extcodesize(to) { // Prepare the calldata. let m := mload(0x40) let onERC1155ReceivedSelector := 0xf23a6e61 mstore(m, onERC1155ReceivedSelector) mstore(add(m, 0x20), caller()) mstore(add(m, 0x40), from) mstore(add(m, 0x60), id) mstore(add(m, 0x80), amount) mstore(add(m, 0xa0), 0xa0) calldatacopy(add(m, 0xc0), sub(data.offset, 0x20), add(0x20, data.length)) // Revert if the call reverts. if iszero(call(gas(), to, 0, add(m, 0x1c), add(0xc4, data.length), m, 0x20)) { if returndatasize() { // Bubble up the revert if the delegatecall reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } mstore(m, 0) } // Load the returndata and compare it. if iszero(eq(mload(m), shl(224, onERC1155ReceivedSelector))) { mstore(0x00, 0x9c05499b) // `TransferToNonERC1155ReceiverImplementer()`. revert(0x1c, 0x04) } } } } /// @dev Transfers `amounts` of `ids` from `from` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `from` must have at least `amount` of `id`. /// - `ids` and `amounts` must have the same length. /// - If the caller is not `from`, /// it must be approved to manage the tokens of `from`. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155BatchReveived}, which is called upon a batch transfer. /// /// Emits a {TransferBatch} event. function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, to, ids, amounts, data); } /// @solidity memory-safe-assembly assembly { if iszero(eq(ids.length, amounts.length)) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } let fromSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, from)) let toSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, to)) mstore(0x20, fromSlotSeed) // Clear the upper 96 bits. from := shr(96, fromSlotSeed) to := shr(96, toSlotSeed) // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // If the caller is not `from`, do the authorization check. if iszero(eq(caller(), from)) { mstore(0x00, caller()) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Loop through all the `ids` and update the balances. { let end := shl(5, ids.length) for { let i := 0 } iszero(eq(i, end)) { i := add(i, 0x20) } { let amount := calldataload(add(amounts.offset, i)) // Subtract and store the updated balance of `from`. { mstore(0x20, fromSlotSeed) mstore(0x00, calldataload(add(ids.offset, i))) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Increase and store the updated balance of `to`. { mstore(0x20, toSlotSeed) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } } } // Emit a {TransferBatch} event. { let m := mload(0x40) // Copy the `ids`. mstore(m, 0x40) let n := add(0x20, shl(5, ids.length)) let o := add(m, 0x40) calldatacopy(o, sub(ids.offset, 0x20), n) // Copy the `amounts`. mstore(add(m, 0x20), add(0x40, n)) o := add(o, n) n := add(0x20, shl(5, amounts.length)) calldatacopy(o, sub(amounts.offset, 0x20), n) n := sub(add(o, n), m) // Do the emit. log4(m, n, _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), from, to) } } if (_useAfterTokenTransfer()) { _afterTokenTransferCalldata(from, to, ids, amounts, data); } /// @solidity memory-safe-assembly assembly { // Do the {onERC1155BatchReceived} check if `to` is a smart contract. if extcodesize(to) { let m := mload(0x40) // Prepare the calldata. let onERC1155BatchReceivedSelector := 0xbc197c81 mstore(m, onERC1155BatchReceivedSelector) mstore(add(m, 0x20), caller()) mstore(add(m, 0x40), from) // Copy the `ids`. mstore(add(m, 0x60), 0xa0) let n := add(0x20, shl(5, ids.length)) let o := add(m, 0xc0) calldatacopy(o, sub(ids.offset, 0x20), n) // Copy the `amounts`. let s := add(0xa0, n) mstore(add(m, 0x80), s) o := add(o, n) n := add(0x20, shl(5, amounts.length)) calldatacopy(o, sub(amounts.offset, 0x20), n) // Copy the `data`. mstore(add(m, 0xa0), add(s, n)) o := add(o, n) n := add(0x20, data.length) calldatacopy(o, sub(data.offset, 0x20), n) n := sub(add(o, n), add(m, 0x1c)) // Revert if the call reverts. if iszero(call(gas(), to, 0, add(m, 0x1c), n, m, 0x20)) { if returndatasize() { // Bubble up the revert if the delegatecall reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } mstore(m, 0) } // Load the returndata and compare it. if iszero(eq(mload(m), shl(224, onERC1155BatchReceivedSelector))) { mstore(0x00, 0x9c05499b) // `TransferToNonERC1155ReceiverImplementer()`. revert(0x1c, 0x04) } } } } /// @dev Returns the amounts of `ids` for `owners. /// /// Requirements: /// - `owners` and `ids` must have the same length. function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { /// @solidity memory-safe-assembly assembly { if iszero(eq(ids.length, owners.length)) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } balances := mload(0x40) mstore(balances, ids.length) let o := add(balances, 0x20) let end := shl(5, ids.length) mstore(0x40, add(end, o)) // Loop through all the `ids` and load the balances. for { let i := 0 } iszero(eq(i, end)) { i := add(i, 0x20) } { let owner := calldataload(add(owners.offset, i)) mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, shl(96, owner))) mstore(0x00, calldataload(add(ids.offset, i))) mstore(add(o, i), sload(keccak256(0x00, 0x40))) } } } /// @dev Returns true if this contract implements the interface defined by `interfaceId`. /// See: https://eips.ethereum.org/EIPS/eip-165 /// This function call must use less than 30000 gas. function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { let s := shr(224, interfaceId) // ERC165: 0x01ffc9a7, ERC1155: 0xd9b67a26, ERC1155MetadataURI: 0x0e89341c. result := or(or(eq(s, 0x01ffc9a7), eq(s, 0xd9b67a26)), eq(s, 0x0e89341c)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL MINT FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Mints `amount` of `id` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155Reveived}, which is called upon a batch transfer. /// /// Emits a {Transfer} event. function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(address(0), to, _single(id), _single(amount), data); } /// @solidity memory-safe-assembly assembly { let toSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, to)) // Clear the upper 96 bits. to := shr(96, toSlotSeed) // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Increase and store the updated balance of `to`. { mstore(0x20, toSlotSeed) mstore(0x00, id) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } // Emit a {TransferSingle} event. { mstore(0x00, id) mstore(0x20, amount) log4(0x00, 0x40, _TRANSFER_SINGLE_EVENT_SIGNATURE, caller(), 0, to) } } if (_useAfterTokenTransfer()) { _afterTokenTransfer(address(0), to, _single(id), _single(amount), data); } if (_hasCode(to)) _checkOnERC1155Received(address(0), to, id, amount, data); } /// @dev Mints `amounts` of `ids` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `ids` and `amounts` must have the same length. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155BatchReveived}, which is called upon a batch transfer. /// /// Emits a {TransferBatch} event. function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(address(0), to, ids, amounts, data); } /// @solidity memory-safe-assembly assembly { if iszero(eq(mload(ids), mload(amounts))) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } let toSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, to)) // Clear the upper 96 bits. to := shr(96, toSlotSeed) // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Loop through all the `ids` and update the balances. { let end := shl(5, mload(ids)) for { let i := 0 } iszero(eq(i, end)) {} { i := add(i, 0x20) let amount := mload(add(amounts, i)) // Increase and store the updated balance of `to`. { mstore(0x20, toSlotSeed) mstore(0x00, mload(add(ids, i))) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } } } // Emit a {TransferBatch} event. { let m := mload(0x40) // Copy the `ids`. mstore(m, 0x40) let n := add(0x20, shl(5, mload(ids))) let o := add(m, 0x40) pop(staticcall(gas(), 4, ids, n, o, n)) // Copy the `amounts`. mstore(add(m, 0x20), add(0x40, returndatasize())) o := add(o, returndatasize()) n := add(0x20, shl(5, mload(amounts))) pop(staticcall(gas(), 4, amounts, n, o, n)) n := sub(add(o, returndatasize()), m) // Do the emit. log4(m, n, _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), 0, to) } } if (_useAfterTokenTransfer()) { _afterTokenTransfer(address(0), to, ids, amounts, data); } if (_hasCode(to)) _checkOnERC1155BatchReceived(address(0), to, ids, amounts, data); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL BURN FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `_burn(address(0), from, id, amount)`. function _burn(address from, uint256 id, uint256 amount) internal virtual { _burn(address(0), from, id, amount); } /// @dev Destroys `amount` of `id` from `from`. /// /// Requirements: /// - `from` must have at least `amount` of `id`. /// - If `by` is not the zero address, it must be either `from`, /// or approved to manage the tokens of `from`. /// /// Emits a {Transfer} event. function _burn(address by, address from, uint256 id, uint256 amount) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, address(0), _single(id), _single(amount), ""); } /// @solidity memory-safe-assembly assembly { let fromSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, from)) mstore(0x20, fromSlotSeed) // Clear the upper 96 bits. from := shr(96, fromSlotSeed) by := shr(96, shl(96, by)) // If `by` is not the zero address, and not equal to `from`, // check if it is approved to manage all the tokens of `from`. if iszero(or(iszero(by), eq(by, from))) { mstore(0x00, by) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Decrease and store the updated balance of `from`. { mstore(0x00, id) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Emit a {TransferSingle} event. { mstore(0x00, id) mstore(0x20, amount) log4(0x00, 0x40, _TRANSFER_SINGLE_EVENT_SIGNATURE, caller(), from, 0) } } if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, address(0), _single(id), _single(amount), ""); } } /// @dev Equivalent to `_batchBurn(address(0), from, ids, amounts)`. function _batchBurn(address from, uint256[] memory ids, uint256[] memory amounts) internal virtual { _batchBurn(address(0), from, ids, amounts); } /// @dev Destroys `amounts` of `ids` from `from`. /// /// Requirements: /// - `ids` and `amounts` must have the same length. /// - `from` must have at least `amounts` of `ids`. /// - If `by` is not the zero address, it must be either `from`, /// or approved to manage the tokens of `from`. /// /// Emits a {TransferBatch} event. function _batchBurn(address by, address from, uint256[] memory ids, uint256[] memory amounts) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, address(0), ids, amounts, ""); } /// @solidity memory-safe-assembly assembly { if iszero(eq(mload(ids), mload(amounts))) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } let fromSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, from)) mstore(0x20, fromSlotSeed) // Clear the upper 96 bits. from := shr(96, fromSlotSeed) by := shr(96, shl(96, by)) // If `by` is not the zero address, and not equal to `from`, // check if it is approved to manage all the tokens of `from`. if iszero(or(iszero(by), eq(by, from))) { mstore(0x00, by) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Loop through all the `ids` and update the balances. { let end := shl(5, mload(ids)) for { let i := 0 } iszero(eq(i, end)) {} { i := add(i, 0x20) let amount := mload(add(amounts, i)) // Increase and store the updated balance of `to`. { mstore(0x00, mload(add(ids, i))) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } } } // Emit a {TransferBatch} event. { let m := mload(0x40) // Copy the `ids`. mstore(m, 0x40) let n := add(0x20, shl(5, mload(ids))) let o := add(m, 0x40) pop(staticcall(gas(), 4, ids, n, o, n)) // Copy the `amounts`. mstore(add(m, 0x20), add(0x40, returndatasize())) o := add(o, returndatasize()) n := add(0x20, shl(5, mload(amounts))) pop(staticcall(gas(), 4, amounts, n, o, n)) n := sub(add(o, returndatasize()), m) // Do the emit. log4(m, n, _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), from, 0) } } if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, address(0), ids, amounts, ""); } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL APPROVAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Approve or remove the `operator` as an operator for `by`, /// without authorization checks. /// /// Emits a {ApprovalForAll} event. function _setApprovalForAll(address by, address operator, bool isApproved) internal virtual { /// @solidity memory-safe-assembly assembly { // Clear the upper 96 bits. operator := shr(96, shl(96, operator)) // Convert to 0 or 1. isApproved := iszero(iszero(isApproved)) // Update the `isApproved` for (`by`, `operator`). mstore(0x20, or(_ERC1155_MASTER_SLOT_SEED, shl(96, by))) mstore(0x00, operator) sstore(keccak256(0x0c, 0x34), isApproved) // Emit the {ApprovalForAll} event. mstore(0x00, isApproved) log3(0x00, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), operator) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL TRANSFER FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `_safeTransfer(address(0), from, to, id, amount, data)`. function _safeTransfer(address from, address to, uint256 id, uint256 amount, bytes memory data) internal virtual { _safeTransfer(address(0), from, to, id, amount, data); } /// @dev Transfers `amount` of `id` from `from` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `from` must have at least `amount` of `id`. /// - If `by` is not the zero address, it must be either `from`, /// or approved to manage the tokens of `from`. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155Reveived}, which is called upon a batch transfer. /// /// Emits a {Transfer} event. function _safeTransfer( address by, address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, to, _single(id), _single(amount), data); } /// @solidity memory-safe-assembly assembly { let fromSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, from)) let toSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, to)) mstore(0x20, fromSlotSeed) // Clear the upper 96 bits. from := shr(96, fromSlotSeed) to := shr(96, toSlotSeed) by := shr(96, shl(96, by)) // If `by` is not the zero address, and not equal to `from`, // check if it is approved to manage all the tokens of `from`. if iszero(or(iszero(by), eq(by, from))) { mstore(0x00, by) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // Subtract and store the updated balance of `from`. { mstore(0x00, id) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Increase and store the updated balance of `to`. { mstore(0x20, toSlotSeed) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } // Emit a {TransferSingle} event. { mstore(0x20, amount) log4(0x00, 0x40, _TRANSFER_SINGLE_EVENT_SIGNATURE, caller(), from, to) } } if (_hasCode(to)) _checkOnERC1155Received(from, to, id, amount, data); if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, to, _single(id), _single(amount), data); } } /// @dev Equivalent to `_safeBatchTransfer(address(0), from, to, ids, amounts, data)`. function _safeBatchTransfer( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { _safeBatchTransfer(address(0), from, to, ids, amounts, data); } /// @dev Transfers `amounts` of `ids` from `from` to `to`. /// /// Requirements: /// - `to` cannot be the zero address. /// - `ids` and `amounts` must have the same length. /// - `from` must have at least `amounts` of `ids`. /// - If `by` is not the zero address, it must be either `from`, /// or approved to manage the tokens of `from`. /// - If `to` refers to a smart contract, it must implement /// {ERC1155-onERC1155BatchReveived}, which is called upon a batch transfer. /// /// Emits a {TransferBatch} event. function _safeBatchTransfer( address by, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { if (_useBeforeTokenTransfer()) { _beforeTokenTransfer(from, to, ids, amounts, data); } /// @solidity memory-safe-assembly assembly { if iszero(eq(mload(ids), mload(amounts))) { mstore(0x00, 0x3b800a46) // `ArrayLengthsMismatch()`. revert(0x1c, 0x04) } let fromSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, from)) let toSlotSeed := or(_ERC1155_MASTER_SLOT_SEED, shl(96, to)) mstore(0x20, fromSlotSeed) // Clear the upper 96 bits. from := shr(96, fromSlotSeed) to := shr(96, toSlotSeed) by := shr(96, shl(96, by)) // Revert if `to` is the zero address. if iszero(to) { mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`. revert(0x1c, 0x04) } // If `by` is not the zero address, and not equal to `from`, // check if it is approved to manage all the tokens of `from`. if iszero(or(iszero(by), eq(by, from))) { mstore(0x00, by) if iszero(sload(keccak256(0x0c, 0x34))) { mstore(0x00, 0x4b6e7f18) // `NotOwnerNorApproved()`. revert(0x1c, 0x04) } } // Loop through all the `ids` and update the balances. { let end := shl(5, mload(ids)) for { let i := 0 } iszero(eq(i, end)) {} { i := add(i, 0x20) let amount := mload(add(amounts, i)) // Subtract and store the updated balance of `from`. { mstore(0x20, fromSlotSeed) mstore(0x00, mload(add(ids, i))) let fromBalanceSlot := keccak256(0x00, 0x40) let fromBalance := sload(fromBalanceSlot) if gt(amount, fromBalance) { mstore(0x00, 0xf4d678b8) // `InsufficientBalance()`. revert(0x1c, 0x04) } sstore(fromBalanceSlot, sub(fromBalance, amount)) } // Increase and store the updated balance of `to`. { mstore(0x20, toSlotSeed) let toBalanceSlot := keccak256(0x00, 0x40) let toBalanceBefore := sload(toBalanceSlot) let toBalanceAfter := add(toBalanceBefore, amount) if lt(toBalanceAfter, toBalanceBefore) { mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`. revert(0x1c, 0x04) } sstore(toBalanceSlot, toBalanceAfter) } } } // Emit a {TransferBatch} event. { let m := mload(0x40) // Copy the `ids`. mstore(m, 0x40) let n := add(0x20, shl(5, mload(ids))) let o := add(m, 0x40) pop(staticcall(gas(), 4, ids, n, o, n)) // Copy the `amounts`. mstore(add(m, 0x20), add(0x40, returndatasize())) o := add(o, returndatasize()) n := add(0x20, shl(5, mload(amounts))) pop(staticcall(gas(), 4, amounts, n, o, n)) n := sub(add(o, returndatasize()), m) // Do the emit. log4(m, n, _TRANSFER_BATCH_EVENT_SIGNATURE, caller(), from, to) } } if (_hasCode(to)) _checkOnERC1155BatchReceived(from, to, ids, amounts, data); if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, to, ids, amounts, data); } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HOOKS FOR OVERRIDING */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override this function to return true if `_beforeTokenTransfer` is used. /// The is to help the compiler avoid producing dead bytecode. function _useBeforeTokenTransfer() internal view virtual returns (bool) { return false; } /// @dev Hook that is called before any token transfer. /// This includes minting and burning, as well as batched variants. /// /// The same hook is called on both single and batched variants. /// For single transfers, the length of the `id` and `amount` arrays are 1. function _beforeTokenTransfer( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /// @dev Override this function to return true if `_afterTokenTransfer` is used. /// The is to help the compiler avoid producing dead bytecode. function _useAfterTokenTransfer() internal view virtual returns (bool) { return false; } /// @dev Hook that is called after any token transfer. /// This includes minting and burning, as well as batched variants. /// /// The same hook is called on both single and batched variants. /// For single transfers, the length of the `id` and `amount` arrays are 1. function _afterTokenTransfer( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Helper for calling the `_afterTokenTransfer` hook. /// The is to help the compiler avoid producing dead bytecode. function _afterTokenTransferCalldata( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) private { if (_useAfterTokenTransfer()) { _afterTokenTransfer(from, to, ids, amounts, data); } } /// @dev Returns if `a` has bytecode of non-zero length. function _hasCode(address a) private view returns (bool result) { /// @solidity memory-safe-assembly assembly { result := extcodesize(a) // Can handle dirty upper bits. } } /// @dev Perform a call to invoke {IERC1155Receiver-onERC1155Received} on `to`. /// Reverts if the target does not support the function correctly. function _checkOnERC1155Received( address from, address to, uint256 id, uint256 amount, bytes memory data ) private { /// @solidity memory-safe-assembly assembly { // Prepare the calldata. let m := mload(0x40) let onERC1155ReceivedSelector := 0xf23a6e61 mstore(m, onERC1155ReceivedSelector) mstore(add(m, 0x20), caller()) mstore(add(m, 0x40), shr(96, shl(96, from))) mstore(add(m, 0x60), id) mstore(add(m, 0x80), amount) mstore(add(m, 0xa0), 0xa0) let n := mload(data) mstore(add(m, 0xc0), n) if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xe0), n)) } // Revert if the call reverts. if iszero(call(gas(), to, 0, add(m, 0x1c), add(0xc4, n), m, 0x20)) { if returndatasize() { // Bubble up the revert if the delegatecall reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } mstore(m, 0) } // Load the returndata and compare it. if iszero(eq(mload(m), shl(224, onERC1155ReceivedSelector))) { mstore(0x00, 0x9c05499b) // `TransferToNonERC1155ReceiverImplementer()`. revert(0x1c, 0x04) } } } /// @dev Perform a call to invoke {IERC1155Receiver-onERC1155BatchReceived} on `to`. /// Reverts if the target does not support the function correctly. function _checkOnERC1155BatchReceived( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { /// @solidity memory-safe-assembly assembly { // Prepare the calldata. let m := mload(0x40) let onERC1155BatchReceivedSelector := 0xbc197c81 mstore(m, onERC1155BatchReceivedSelector) mstore(add(m, 0x20), caller()) mstore(add(m, 0x40), shr(96, shl(96, from))) // Copy the `ids`. mstore(add(m, 0x60), 0xa0) let n := add(0x20, shl(5, mload(ids))) let o := add(m, 0xc0) pop(staticcall(gas(), 4, ids, n, o, n)) // Copy the `amounts`. let s := add(0xa0, returndatasize()) mstore(add(m, 0x80), s) o := add(o, returndatasize()) n := add(0x20, shl(5, mload(amounts))) pop(staticcall(gas(), 4, amounts, n, o, n)) // Copy the `data`. mstore(add(m, 0xa0), add(s, returndatasize())) o := add(o, returndatasize()) n := add(0x20, mload(data)) pop(staticcall(gas(), 4, data, n, o, n)) n := sub(add(o, returndatasize()), add(m, 0x1c)) // Revert if the call reverts. if iszero(call(gas(), to, 0, add(m, 0x1c), n, m, 0x20)) { if returndatasize() { // Bubble up the revert if the delegatecall reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } mstore(m, 0) } // Load the returndata and compare it. if iszero(eq(mload(m), shl(224, onERC1155BatchReceivedSelector))) { mstore(0x00, 0x9c05499b) // `TransferToNonERC1155ReceiverImplementer()`. revert(0x1c, 0x04) } } } /// @dev Returns `x` in an array with a single element. function _single(uint256 x) private pure returns (uint256[] memory result) { assembly { result := mload(0x40) mstore(0x40, add(result, 0x40)) mstore(result, 1) mstore(add(result, 0x20), x) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an ERC721 token is transferred to this contract via * safeTransferFrom, this function is called. * * @param operator The address of the operator. * @param from The address of the sender. * @param tokenId The ID of the ERC721. * @param data Additional data. * * @return bytes4 The magic value, unless throwing. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface IERC1155Receiver { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received(address operator, address from, uint256 id, uint256 value, bytes calldata data) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; interface IERC721RedemptionMintable { function mintRedemption(address to, SpentItem[] calldata spent) external returns (uint256 tokenId); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; interface IERC1155RedemptionMintable { function mintRedemption(address to, SpentItem[] calldata spent) external returns (uint256 tokenId); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {SignatureCheckerLib} from "solady/src/utils/SignatureCheckerLib.sol"; import {SignedRedeemErrorsAndEvents} from "./SignedRedeemErrorsAndEvents.sol"; contract SignedRedeemContractOfferer is SignedRedeemErrorsAndEvents { /// @dev The used digests, each digest can only be used once. mapping(bytes32 => bool) internal _usedDigests; /// @notice Internal constants for EIP-712: Typed structured /// data hashing and signing bytes32 internal constant _SIGNED_REDEEM_TYPEHASH = keccak256("SignedRedeem(address owner,address token,uint256[] tokenIds,bytes32 redemptionHash,uint256 salt)"); bytes32 internal constant _EIP_712_DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); bytes32 internal constant _NAME_HASH = keccak256("SignedRedeem"); bytes32 internal constant _VERSION_HASH = keccak256("1.0"); uint256 internal immutable _CHAIN_ID = block.chainid; bytes32 internal immutable _DOMAIN_SEPARATOR; constructor() { _DOMAIN_SEPARATOR = _deriveDomainSeparator(); } function _verifySignature( address signer, address owner, SpentItem[] memory maximumSpent, bytes32 redemptionHash, uint256 salt, bytes memory signature, bool recordDigest ) internal { // Get the digest. bytes32 digest = _getDigest(owner, maximumSpent, redemptionHash, salt); // Revert if signature does not recover to signer. if (!SignatureCheckerLib.isValidSignatureNow(signer, digest, signature)) revert InvalidSigner(); // Revert if the digest is already used. if (_usedDigests[digest]) revert DigestAlreadyUsed(); // Record digest as used. if (recordDigest) _usedDigests[digest] = true; } /* * @notice Verify an EIP-712 signature by recreating the data structure * that we signed on the client side, and then using that to recover * the address that signed the signature for this data. */ function _getDigest(address owner, SpentItem[] memory maximumSpent, bytes32 redemptionHash, uint256 salt) internal view returns (bytes32 digest) { digest = keccak256( bytes.concat( bytes2(0x1901), _domainSeparator(), keccak256(abi.encode(_SIGNED_REDEEM_TYPEHASH, owner, maximumSpent, redemptionHash, salt)) ) ); } /** * @dev Internal view function to get the EIP-712 domain separator. If the * chainId matches the chainId set on deployment, the cached domain * separator will be returned; otherwise, it will be derived from * scratch. * * @return The domain separator. */ function _domainSeparator() internal view returns (bytes32) { return block.chainid == _CHAIN_ID ? _DOMAIN_SEPARATOR : _deriveDomainSeparator(); } /** * @dev Internal view function to derive the EIP-712 domain separator. * * @return The derived domain separator. */ function _deriveDomainSeparator() internal view returns (bytes32) { return keccak256(abi.encode(_EIP_712_DOMAIN_TYPEHASH, _NAME_HASH, _VERSION_HASH, block.chainid, address(this))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; import {CampaignParams} from "./RedeemableStructs.sol"; interface RedeemableErrorsAndEvents { /// Configuration errors error NotManager(); error InvalidTime(); error NoConsiderationItems(); error ConsiderationItemRecipientCannotBeZeroAddress(); /// Redemption errors error InvalidCampaignId(); error CampaignAlreadyExists(); error InvalidCaller(address caller); error NotActive(uint256 currentTimestamp, uint256 startTime, uint256 endTime); error MaxRedemptionsReached(uint256 total, uint256 max); error MaxCampaignRedemptionsReached(uint256 total, uint256 max); error RedeemMismatchedLengths(); error TraitValueUnchanged(bytes32 traitKey, bytes32 value); error InvalidConsiderationLength(uint256 got, uint256 want); error InvalidConsiderationItem(address got, address want); error InvalidOfferLength(uint256 got, uint256 want); error InvalidNativeOfferItem(); error InvalidOwner(); error InvalidRequiredValue(bytes32 got, bytes32 want); error InvalidSubstandard(uint256 substandard); error InvalidTraitRedemption(); error InvalidTraitRedemptionToken(address token); error ConsiderationRecipientNotFound(address token); error RedemptionValuesAreImmutable(); /// Events event CampaignUpdated(uint256 indexed campaignId, CampaignParams params, string uri); event Redemption(uint256 indexed campaignId, bytes32 redemptionHash); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {OfferItem, ConsiderationItem, SpentItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; struct CampaignParams { uint32 startTime; uint32 endTime; uint32 maxCampaignRedemptions; address manager; address signer; OfferItem[] offer; ConsiderationItem[] consideration; } struct TraitRedemption { uint8 substandard; address token; uint256 identifier; bytes32 traitKey; bytes32 traitValue; bytes32 substandardValue; } struct RedemptionContext { SpentItem[] spent; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.7; /** * @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`. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; type CalldataPointer is uint256; type ReturndataPointer is uint256; type MemoryPointer is uint256; using CalldataPointerLib for CalldataPointer global; using MemoryPointerLib for MemoryPointer global; using ReturndataPointerLib for ReturndataPointer global; using CalldataReaders for CalldataPointer global; using ReturndataReaders for ReturndataPointer global; using MemoryReaders for MemoryPointer global; using MemoryWriters for MemoryPointer global; CalldataPointer constant CalldataStart = CalldataPointer.wrap(0x04); MemoryPointer constant FreeMemoryPPtr = MemoryPointer.wrap(0x40); uint256 constant IdentityPrecompileAddress = 0x4; uint256 constant OffsetOrLengthMask = 0xffffffff; uint256 constant _OneWord = 0x20; uint256 constant _FreeMemoryPointerSlot = 0x40; /// @dev Allocates `size` bytes in memory by increasing the free memory pointer /// and returns the memory pointer to the first byte of the allocated region. // (Free functions cannot have visibility.) // solhint-disable-next-line func-visibility function malloc(uint256 size) pure returns (MemoryPointer mPtr) { assembly { mPtr := mload(_FreeMemoryPointerSlot) mstore(_FreeMemoryPointerSlot, add(mPtr, size)) } } // (Free functions cannot have visibility.) // solhint-disable-next-line func-visibility function getFreeMemoryPointer() pure returns (MemoryPointer mPtr) { mPtr = FreeMemoryPPtr.readMemoryPointer(); } // (Free functions cannot have visibility.) // solhint-disable-next-line func-visibility function setFreeMemoryPointer(MemoryPointer mPtr) pure { FreeMemoryPPtr.write(mPtr); } library CalldataPointerLib { function lt( CalldataPointer a, CalldataPointer b ) internal pure returns (bool c) { assembly { c := lt(a, b) } } function gt( CalldataPointer a, CalldataPointer b ) internal pure returns (bool c) { assembly { c := gt(a, b) } } function eq( CalldataPointer a, CalldataPointer b ) internal pure returns (bool c) { assembly { c := eq(a, b) } } function isNull(CalldataPointer a) internal pure returns (bool b) { assembly { b := iszero(a) } } /// @dev Resolves an offset stored at `cdPtr + headOffset` to a calldata. /// pointer `cdPtr` must point to some parent object with a dynamic /// type's head stored at `cdPtr + headOffset`. function pptr( CalldataPointer cdPtr, uint256 headOffset ) internal pure returns (CalldataPointer cdPtrChild) { cdPtrChild = cdPtr.offset( cdPtr.offset(headOffset).readUint256() & OffsetOrLengthMask ); } /// @dev Resolves an offset stored at `cdPtr` to a calldata pointer. /// `cdPtr` must point to some parent object with a dynamic type as its /// first member, e.g. `struct { bytes data; }` function pptr( CalldataPointer cdPtr ) internal pure returns (CalldataPointer cdPtrChild) { cdPtrChild = cdPtr.offset(cdPtr.readUint256() & OffsetOrLengthMask); } /// @dev Returns the calldata pointer one word after `cdPtr`. function next( CalldataPointer cdPtr ) internal pure returns (CalldataPointer cdPtrNext) { assembly { cdPtrNext := add(cdPtr, _OneWord) } } /// @dev Returns the calldata pointer `_offset` bytes after `cdPtr`. function offset( CalldataPointer cdPtr, uint256 _offset ) internal pure returns (CalldataPointer cdPtrNext) { assembly { cdPtrNext := add(cdPtr, _offset) } } /// @dev Copies `size` bytes from calldata starting at `src` to memory at /// `dst`. function copy( CalldataPointer src, MemoryPointer dst, uint256 size ) internal pure { assembly { calldatacopy(dst, src, size) } } } library ReturndataPointerLib { function lt( ReturndataPointer a, ReturndataPointer b ) internal pure returns (bool c) { assembly { c := lt(a, b) } } function gt( ReturndataPointer a, ReturndataPointer b ) internal pure returns (bool c) { assembly { c := gt(a, b) } } function eq( ReturndataPointer a, ReturndataPointer b ) internal pure returns (bool c) { assembly { c := eq(a, b) } } function isNull(ReturndataPointer a) internal pure returns (bool b) { assembly { b := iszero(a) } } /// @dev Resolves an offset stored at `rdPtr + headOffset` to a returndata /// pointer. `rdPtr` must point to some parent object with a dynamic /// type's head stored at `rdPtr + headOffset`. function pptr( ReturndataPointer rdPtr, uint256 headOffset ) internal pure returns (ReturndataPointer rdPtrChild) { rdPtrChild = rdPtr.offset( rdPtr.offset(headOffset).readUint256() & OffsetOrLengthMask ); } /// @dev Resolves an offset stored at `rdPtr` to a returndata pointer. /// `rdPtr` must point to some parent object with a dynamic type as its /// first member, e.g. `struct { bytes data; }` function pptr( ReturndataPointer rdPtr ) internal pure returns (ReturndataPointer rdPtrChild) { rdPtrChild = rdPtr.offset(rdPtr.readUint256() & OffsetOrLengthMask); } /// @dev Returns the returndata pointer one word after `cdPtr`. function next( ReturndataPointer rdPtr ) internal pure returns (ReturndataPointer rdPtrNext) { assembly { rdPtrNext := add(rdPtr, _OneWord) } } /// @dev Returns the returndata pointer `_offset` bytes after `cdPtr`. function offset( ReturndataPointer rdPtr, uint256 _offset ) internal pure returns (ReturndataPointer rdPtrNext) { assembly { rdPtrNext := add(rdPtr, _offset) } } /// @dev Copies `size` bytes from returndata starting at `src` to memory at /// `dst`. function copy( ReturndataPointer src, MemoryPointer dst, uint256 size ) internal pure { assembly { returndatacopy(dst, src, size) } } } library MemoryPointerLib { function copy( MemoryPointer src, MemoryPointer dst, uint256 size ) internal view { assembly { let success := staticcall( gas(), IdentityPrecompileAddress, src, size, dst, size ) if or(iszero(returndatasize()), iszero(success)) { revert(0, 0) } } } function lt( MemoryPointer a, MemoryPointer b ) internal pure returns (bool c) { assembly { c := lt(a, b) } } function gt( MemoryPointer a, MemoryPointer b ) internal pure returns (bool c) { assembly { c := gt(a, b) } } function eq( MemoryPointer a, MemoryPointer b ) internal pure returns (bool c) { assembly { c := eq(a, b) } } function isNull(MemoryPointer a) internal pure returns (bool b) { assembly { b := iszero(a) } } function hash( MemoryPointer ptr, uint256 length ) internal pure returns (bytes32 _hash) { assembly { _hash := keccak256(ptr, length) } } /// @dev Returns the memory pointer one word after `mPtr`. function next( MemoryPointer mPtr ) internal pure returns (MemoryPointer mPtrNext) { assembly { mPtrNext := add(mPtr, _OneWord) } } /// @dev Returns the memory pointer `_offset` bytes after `mPtr`. function offset( MemoryPointer mPtr, uint256 _offset ) internal pure returns (MemoryPointer mPtrNext) { assembly { mPtrNext := add(mPtr, _offset) } } /// @dev Resolves a pointer at `mPtr + headOffset` to a memory /// pointer. `mPtr` must point to some parent object with a dynamic /// type's pointer stored at `mPtr + headOffset`. function pptr( MemoryPointer mPtr, uint256 headOffset ) internal pure returns (MemoryPointer mPtrChild) { mPtrChild = mPtr.offset(headOffset).readMemoryPointer(); } /// @dev Resolves a pointer stored at `mPtr` to a memory pointer. /// `mPtr` must point to some parent object with a dynamic type as its /// first member, e.g. `struct { bytes data; }` function pptr( MemoryPointer mPtr ) internal pure returns (MemoryPointer mPtrChild) { mPtrChild = mPtr.readMemoryPointer(); } } library CalldataReaders { /// @dev Reads the value at `cdPtr` and applies a mask to return only the /// last 4 bytes. function readMaskedUint256( CalldataPointer cdPtr ) internal pure returns (uint256 value) { value = cdPtr.readUint256() & OffsetOrLengthMask; } /// @dev Reads the bool at `cdPtr` in calldata. function readBool( CalldataPointer cdPtr ) internal pure returns (bool value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the address at `cdPtr` in calldata. function readAddress( CalldataPointer cdPtr ) internal pure returns (address value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes1 at `cdPtr` in calldata. function readBytes1( CalldataPointer cdPtr ) internal pure returns (bytes1 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes2 at `cdPtr` in calldata. function readBytes2( CalldataPointer cdPtr ) internal pure returns (bytes2 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes3 at `cdPtr` in calldata. function readBytes3( CalldataPointer cdPtr ) internal pure returns (bytes3 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes4 at `cdPtr` in calldata. function readBytes4( CalldataPointer cdPtr ) internal pure returns (bytes4 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes5 at `cdPtr` in calldata. function readBytes5( CalldataPointer cdPtr ) internal pure returns (bytes5 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes6 at `cdPtr` in calldata. function readBytes6( CalldataPointer cdPtr ) internal pure returns (bytes6 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes7 at `cdPtr` in calldata. function readBytes7( CalldataPointer cdPtr ) internal pure returns (bytes7 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes8 at `cdPtr` in calldata. function readBytes8( CalldataPointer cdPtr ) internal pure returns (bytes8 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes9 at `cdPtr` in calldata. function readBytes9( CalldataPointer cdPtr ) internal pure returns (bytes9 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes10 at `cdPtr` in calldata. function readBytes10( CalldataPointer cdPtr ) internal pure returns (bytes10 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes11 at `cdPtr` in calldata. function readBytes11( CalldataPointer cdPtr ) internal pure returns (bytes11 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes12 at `cdPtr` in calldata. function readBytes12( CalldataPointer cdPtr ) internal pure returns (bytes12 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes13 at `cdPtr` in calldata. function readBytes13( CalldataPointer cdPtr ) internal pure returns (bytes13 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes14 at `cdPtr` in calldata. function readBytes14( CalldataPointer cdPtr ) internal pure returns (bytes14 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes15 at `cdPtr` in calldata. function readBytes15( CalldataPointer cdPtr ) internal pure returns (bytes15 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes16 at `cdPtr` in calldata. function readBytes16( CalldataPointer cdPtr ) internal pure returns (bytes16 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes17 at `cdPtr` in calldata. function readBytes17( CalldataPointer cdPtr ) internal pure returns (bytes17 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes18 at `cdPtr` in calldata. function readBytes18( CalldataPointer cdPtr ) internal pure returns (bytes18 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes19 at `cdPtr` in calldata. function readBytes19( CalldataPointer cdPtr ) internal pure returns (bytes19 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes20 at `cdPtr` in calldata. function readBytes20( CalldataPointer cdPtr ) internal pure returns (bytes20 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes21 at `cdPtr` in calldata. function readBytes21( CalldataPointer cdPtr ) internal pure returns (bytes21 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes22 at `cdPtr` in calldata. function readBytes22( CalldataPointer cdPtr ) internal pure returns (bytes22 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes23 at `cdPtr` in calldata. function readBytes23( CalldataPointer cdPtr ) internal pure returns (bytes23 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes24 at `cdPtr` in calldata. function readBytes24( CalldataPointer cdPtr ) internal pure returns (bytes24 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes25 at `cdPtr` in calldata. function readBytes25( CalldataPointer cdPtr ) internal pure returns (bytes25 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes26 at `cdPtr` in calldata. function readBytes26( CalldataPointer cdPtr ) internal pure returns (bytes26 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes27 at `cdPtr` in calldata. function readBytes27( CalldataPointer cdPtr ) internal pure returns (bytes27 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes28 at `cdPtr` in calldata. function readBytes28( CalldataPointer cdPtr ) internal pure returns (bytes28 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes29 at `cdPtr` in calldata. function readBytes29( CalldataPointer cdPtr ) internal pure returns (bytes29 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes30 at `cdPtr` in calldata. function readBytes30( CalldataPointer cdPtr ) internal pure returns (bytes30 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes31 at `cdPtr` in calldata. function readBytes31( CalldataPointer cdPtr ) internal pure returns (bytes31 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the bytes32 at `cdPtr` in calldata. function readBytes32( CalldataPointer cdPtr ) internal pure returns (bytes32 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint8 at `cdPtr` in calldata. function readUint8( CalldataPointer cdPtr ) internal pure returns (uint8 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint16 at `cdPtr` in calldata. function readUint16( CalldataPointer cdPtr ) internal pure returns (uint16 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint24 at `cdPtr` in calldata. function readUint24( CalldataPointer cdPtr ) internal pure returns (uint24 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint32 at `cdPtr` in calldata. function readUint32( CalldataPointer cdPtr ) internal pure returns (uint32 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint40 at `cdPtr` in calldata. function readUint40( CalldataPointer cdPtr ) internal pure returns (uint40 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint48 at `cdPtr` in calldata. function readUint48( CalldataPointer cdPtr ) internal pure returns (uint48 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint56 at `cdPtr` in calldata. function readUint56( CalldataPointer cdPtr ) internal pure returns (uint56 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint64 at `cdPtr` in calldata. function readUint64( CalldataPointer cdPtr ) internal pure returns (uint64 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint72 at `cdPtr` in calldata. function readUint72( CalldataPointer cdPtr ) internal pure returns (uint72 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint80 at `cdPtr` in calldata. function readUint80( CalldataPointer cdPtr ) internal pure returns (uint80 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint88 at `cdPtr` in calldata. function readUint88( CalldataPointer cdPtr ) internal pure returns (uint88 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint96 at `cdPtr` in calldata. function readUint96( CalldataPointer cdPtr ) internal pure returns (uint96 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint104 at `cdPtr` in calldata. function readUint104( CalldataPointer cdPtr ) internal pure returns (uint104 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint112 at `cdPtr` in calldata. function readUint112( CalldataPointer cdPtr ) internal pure returns (uint112 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint120 at `cdPtr` in calldata. function readUint120( CalldataPointer cdPtr ) internal pure returns (uint120 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint128 at `cdPtr` in calldata. function readUint128( CalldataPointer cdPtr ) internal pure returns (uint128 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint136 at `cdPtr` in calldata. function readUint136( CalldataPointer cdPtr ) internal pure returns (uint136 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint144 at `cdPtr` in calldata. function readUint144( CalldataPointer cdPtr ) internal pure returns (uint144 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint152 at `cdPtr` in calldata. function readUint152( CalldataPointer cdPtr ) internal pure returns (uint152 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint160 at `cdPtr` in calldata. function readUint160( CalldataPointer cdPtr ) internal pure returns (uint160 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint168 at `cdPtr` in calldata. function readUint168( CalldataPointer cdPtr ) internal pure returns (uint168 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint176 at `cdPtr` in calldata. function readUint176( CalldataPointer cdPtr ) internal pure returns (uint176 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint184 at `cdPtr` in calldata. function readUint184( CalldataPointer cdPtr ) internal pure returns (uint184 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint192 at `cdPtr` in calldata. function readUint192( CalldataPointer cdPtr ) internal pure returns (uint192 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint200 at `cdPtr` in calldata. function readUint200( CalldataPointer cdPtr ) internal pure returns (uint200 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint208 at `cdPtr` in calldata. function readUint208( CalldataPointer cdPtr ) internal pure returns (uint208 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint216 at `cdPtr` in calldata. function readUint216( CalldataPointer cdPtr ) internal pure returns (uint216 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint224 at `cdPtr` in calldata. function readUint224( CalldataPointer cdPtr ) internal pure returns (uint224 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint232 at `cdPtr` in calldata. function readUint232( CalldataPointer cdPtr ) internal pure returns (uint232 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint240 at `cdPtr` in calldata. function readUint240( CalldataPointer cdPtr ) internal pure returns (uint240 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint248 at `cdPtr` in calldata. function readUint248( CalldataPointer cdPtr ) internal pure returns (uint248 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the uint256 at `cdPtr` in calldata. function readUint256( CalldataPointer cdPtr ) internal pure returns (uint256 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int8 at `cdPtr` in calldata. function readInt8( CalldataPointer cdPtr ) internal pure returns (int8 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int16 at `cdPtr` in calldata. function readInt16( CalldataPointer cdPtr ) internal pure returns (int16 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int24 at `cdPtr` in calldata. function readInt24( CalldataPointer cdPtr ) internal pure returns (int24 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int32 at `cdPtr` in calldata. function readInt32( CalldataPointer cdPtr ) internal pure returns (int32 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int40 at `cdPtr` in calldata. function readInt40( CalldataPointer cdPtr ) internal pure returns (int40 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int48 at `cdPtr` in calldata. function readInt48( CalldataPointer cdPtr ) internal pure returns (int48 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int56 at `cdPtr` in calldata. function readInt56( CalldataPointer cdPtr ) internal pure returns (int56 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int64 at `cdPtr` in calldata. function readInt64( CalldataPointer cdPtr ) internal pure returns (int64 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int72 at `cdPtr` in calldata. function readInt72( CalldataPointer cdPtr ) internal pure returns (int72 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int80 at `cdPtr` in calldata. function readInt80( CalldataPointer cdPtr ) internal pure returns (int80 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int88 at `cdPtr` in calldata. function readInt88( CalldataPointer cdPtr ) internal pure returns (int88 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int96 at `cdPtr` in calldata. function readInt96( CalldataPointer cdPtr ) internal pure returns (int96 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int104 at `cdPtr` in calldata. function readInt104( CalldataPointer cdPtr ) internal pure returns (int104 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int112 at `cdPtr` in calldata. function readInt112( CalldataPointer cdPtr ) internal pure returns (int112 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int120 at `cdPtr` in calldata. function readInt120( CalldataPointer cdPtr ) internal pure returns (int120 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int128 at `cdPtr` in calldata. function readInt128( CalldataPointer cdPtr ) internal pure returns (int128 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int136 at `cdPtr` in calldata. function readInt136( CalldataPointer cdPtr ) internal pure returns (int136 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int144 at `cdPtr` in calldata. function readInt144( CalldataPointer cdPtr ) internal pure returns (int144 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int152 at `cdPtr` in calldata. function readInt152( CalldataPointer cdPtr ) internal pure returns (int152 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int160 at `cdPtr` in calldata. function readInt160( CalldataPointer cdPtr ) internal pure returns (int160 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int168 at `cdPtr` in calldata. function readInt168( CalldataPointer cdPtr ) internal pure returns (int168 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int176 at `cdPtr` in calldata. function readInt176( CalldataPointer cdPtr ) internal pure returns (int176 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int184 at `cdPtr` in calldata. function readInt184( CalldataPointer cdPtr ) internal pure returns (int184 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int192 at `cdPtr` in calldata. function readInt192( CalldataPointer cdPtr ) internal pure returns (int192 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int200 at `cdPtr` in calldata. function readInt200( CalldataPointer cdPtr ) internal pure returns (int200 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int208 at `cdPtr` in calldata. function readInt208( CalldataPointer cdPtr ) internal pure returns (int208 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int216 at `cdPtr` in calldata. function readInt216( CalldataPointer cdPtr ) internal pure returns (int216 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int224 at `cdPtr` in calldata. function readInt224( CalldataPointer cdPtr ) internal pure returns (int224 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int232 at `cdPtr` in calldata. function readInt232( CalldataPointer cdPtr ) internal pure returns (int232 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int240 at `cdPtr` in calldata. function readInt240( CalldataPointer cdPtr ) internal pure returns (int240 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int248 at `cdPtr` in calldata. function readInt248( CalldataPointer cdPtr ) internal pure returns (int248 value) { assembly { value := calldataload(cdPtr) } } /// @dev Reads the int256 at `cdPtr` in calldata. function readInt256( CalldataPointer cdPtr ) internal pure returns (int256 value) { assembly { value := calldataload(cdPtr) } } } library ReturndataReaders { /// @dev Reads value at `rdPtr` & applies a mask to return only last 4 bytes function readMaskedUint256( ReturndataPointer rdPtr ) internal pure returns (uint256 value) { value = rdPtr.readUint256() & OffsetOrLengthMask; } /// @dev Reads the bool at `rdPtr` in returndata. function readBool( ReturndataPointer rdPtr ) internal pure returns (bool value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the address at `rdPtr` in returndata. function readAddress( ReturndataPointer rdPtr ) internal pure returns (address value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes1 at `rdPtr` in returndata. function readBytes1( ReturndataPointer rdPtr ) internal pure returns (bytes1 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes2 at `rdPtr` in returndata. function readBytes2( ReturndataPointer rdPtr ) internal pure returns (bytes2 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes3 at `rdPtr` in returndata. function readBytes3( ReturndataPointer rdPtr ) internal pure returns (bytes3 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes4 at `rdPtr` in returndata. function readBytes4( ReturndataPointer rdPtr ) internal pure returns (bytes4 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes5 at `rdPtr` in returndata. function readBytes5( ReturndataPointer rdPtr ) internal pure returns (bytes5 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes6 at `rdPtr` in returndata. function readBytes6( ReturndataPointer rdPtr ) internal pure returns (bytes6 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes7 at `rdPtr` in returndata. function readBytes7( ReturndataPointer rdPtr ) internal pure returns (bytes7 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes8 at `rdPtr` in returndata. function readBytes8( ReturndataPointer rdPtr ) internal pure returns (bytes8 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes9 at `rdPtr` in returndata. function readBytes9( ReturndataPointer rdPtr ) internal pure returns (bytes9 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes10 at `rdPtr` in returndata. function readBytes10( ReturndataPointer rdPtr ) internal pure returns (bytes10 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes11 at `rdPtr` in returndata. function readBytes11( ReturndataPointer rdPtr ) internal pure returns (bytes11 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes12 at `rdPtr` in returndata. function readBytes12( ReturndataPointer rdPtr ) internal pure returns (bytes12 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes13 at `rdPtr` in returndata. function readBytes13( ReturndataPointer rdPtr ) internal pure returns (bytes13 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes14 at `rdPtr` in returndata. function readBytes14( ReturndataPointer rdPtr ) internal pure returns (bytes14 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes15 at `rdPtr` in returndata. function readBytes15( ReturndataPointer rdPtr ) internal pure returns (bytes15 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes16 at `rdPtr` in returndata. function readBytes16( ReturndataPointer rdPtr ) internal pure returns (bytes16 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes17 at `rdPtr` in returndata. function readBytes17( ReturndataPointer rdPtr ) internal pure returns (bytes17 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes18 at `rdPtr` in returndata. function readBytes18( ReturndataPointer rdPtr ) internal pure returns (bytes18 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes19 at `rdPtr` in returndata. function readBytes19( ReturndataPointer rdPtr ) internal pure returns (bytes19 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes20 at `rdPtr` in returndata. function readBytes20( ReturndataPointer rdPtr ) internal pure returns (bytes20 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes21 at `rdPtr` in returndata. function readBytes21( ReturndataPointer rdPtr ) internal pure returns (bytes21 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes22 at `rdPtr` in returndata. function readBytes22( ReturndataPointer rdPtr ) internal pure returns (bytes22 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes23 at `rdPtr` in returndata. function readBytes23( ReturndataPointer rdPtr ) internal pure returns (bytes23 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes24 at `rdPtr` in returndata. function readBytes24( ReturndataPointer rdPtr ) internal pure returns (bytes24 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes25 at `rdPtr` in returndata. function readBytes25( ReturndataPointer rdPtr ) internal pure returns (bytes25 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes26 at `rdPtr` in returndata. function readBytes26( ReturndataPointer rdPtr ) internal pure returns (bytes26 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes27 at `rdPtr` in returndata. function readBytes27( ReturndataPointer rdPtr ) internal pure returns (bytes27 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes28 at `rdPtr` in returndata. function readBytes28( ReturndataPointer rdPtr ) internal pure returns (bytes28 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes29 at `rdPtr` in returndata. function readBytes29( ReturndataPointer rdPtr ) internal pure returns (bytes29 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes30 at `rdPtr` in returndata. function readBytes30( ReturndataPointer rdPtr ) internal pure returns (bytes30 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes31 at `rdPtr` in returndata. function readBytes31( ReturndataPointer rdPtr ) internal pure returns (bytes31 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the bytes32 at `rdPtr` in returndata. function readBytes32( ReturndataPointer rdPtr ) internal pure returns (bytes32 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint8 at `rdPtr` in returndata. function readUint8( ReturndataPointer rdPtr ) internal pure returns (uint8 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint16 at `rdPtr` in returndata. function readUint16( ReturndataPointer rdPtr ) internal pure returns (uint16 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint24 at `rdPtr` in returndata. function readUint24( ReturndataPointer rdPtr ) internal pure returns (uint24 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint32 at `rdPtr` in returndata. function readUint32( ReturndataPointer rdPtr ) internal pure returns (uint32 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint40 at `rdPtr` in returndata. function readUint40( ReturndataPointer rdPtr ) internal pure returns (uint40 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint48 at `rdPtr` in returndata. function readUint48( ReturndataPointer rdPtr ) internal pure returns (uint48 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint56 at `rdPtr` in returndata. function readUint56( ReturndataPointer rdPtr ) internal pure returns (uint56 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint64 at `rdPtr` in returndata. function readUint64( ReturndataPointer rdPtr ) internal pure returns (uint64 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint72 at `rdPtr` in returndata. function readUint72( ReturndataPointer rdPtr ) internal pure returns (uint72 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint80 at `rdPtr` in returndata. function readUint80( ReturndataPointer rdPtr ) internal pure returns (uint80 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint88 at `rdPtr` in returndata. function readUint88( ReturndataPointer rdPtr ) internal pure returns (uint88 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint96 at `rdPtr` in returndata. function readUint96( ReturndataPointer rdPtr ) internal pure returns (uint96 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint104 at `rdPtr` in returndata. function readUint104( ReturndataPointer rdPtr ) internal pure returns (uint104 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint112 at `rdPtr` in returndata. function readUint112( ReturndataPointer rdPtr ) internal pure returns (uint112 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint120 at `rdPtr` in returndata. function readUint120( ReturndataPointer rdPtr ) internal pure returns (uint120 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint128 at `rdPtr` in returndata. function readUint128( ReturndataPointer rdPtr ) internal pure returns (uint128 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint136 at `rdPtr` in returndata. function readUint136( ReturndataPointer rdPtr ) internal pure returns (uint136 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint144 at `rdPtr` in returndata. function readUint144( ReturndataPointer rdPtr ) internal pure returns (uint144 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint152 at `rdPtr` in returndata. function readUint152( ReturndataPointer rdPtr ) internal pure returns (uint152 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint160 at `rdPtr` in returndata. function readUint160( ReturndataPointer rdPtr ) internal pure returns (uint160 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint168 at `rdPtr` in returndata. function readUint168( ReturndataPointer rdPtr ) internal pure returns (uint168 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint176 at `rdPtr` in returndata. function readUint176( ReturndataPointer rdPtr ) internal pure returns (uint176 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint184 at `rdPtr` in returndata. function readUint184( ReturndataPointer rdPtr ) internal pure returns (uint184 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint192 at `rdPtr` in returndata. function readUint192( ReturndataPointer rdPtr ) internal pure returns (uint192 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint200 at `rdPtr` in returndata. function readUint200( ReturndataPointer rdPtr ) internal pure returns (uint200 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint208 at `rdPtr` in returndata. function readUint208( ReturndataPointer rdPtr ) internal pure returns (uint208 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint216 at `rdPtr` in returndata. function readUint216( ReturndataPointer rdPtr ) internal pure returns (uint216 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint224 at `rdPtr` in returndata. function readUint224( ReturndataPointer rdPtr ) internal pure returns (uint224 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint232 at `rdPtr` in returndata. function readUint232( ReturndataPointer rdPtr ) internal pure returns (uint232 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint240 at `rdPtr` in returndata. function readUint240( ReturndataPointer rdPtr ) internal pure returns (uint240 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint248 at `rdPtr` in returndata. function readUint248( ReturndataPointer rdPtr ) internal pure returns (uint248 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the uint256 at `rdPtr` in returndata. function readUint256( ReturndataPointer rdPtr ) internal pure returns (uint256 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int8 at `rdPtr` in returndata. function readInt8( ReturndataPointer rdPtr ) internal pure returns (int8 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int16 at `rdPtr` in returndata. function readInt16( ReturndataPointer rdPtr ) internal pure returns (int16 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int24 at `rdPtr` in returndata. function readInt24( ReturndataPointer rdPtr ) internal pure returns (int24 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int32 at `rdPtr` in returndata. function readInt32( ReturndataPointer rdPtr ) internal pure returns (int32 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int40 at `rdPtr` in returndata. function readInt40( ReturndataPointer rdPtr ) internal pure returns (int40 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int48 at `rdPtr` in returndata. function readInt48( ReturndataPointer rdPtr ) internal pure returns (int48 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int56 at `rdPtr` in returndata. function readInt56( ReturndataPointer rdPtr ) internal pure returns (int56 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int64 at `rdPtr` in returndata. function readInt64( ReturndataPointer rdPtr ) internal pure returns (int64 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int72 at `rdPtr` in returndata. function readInt72( ReturndataPointer rdPtr ) internal pure returns (int72 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int80 at `rdPtr` in returndata. function readInt80( ReturndataPointer rdPtr ) internal pure returns (int80 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int88 at `rdPtr` in returndata. function readInt88( ReturndataPointer rdPtr ) internal pure returns (int88 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int96 at `rdPtr` in returndata. function readInt96( ReturndataPointer rdPtr ) internal pure returns (int96 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int104 at `rdPtr` in returndata. function readInt104( ReturndataPointer rdPtr ) internal pure returns (int104 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int112 at `rdPtr` in returndata. function readInt112( ReturndataPointer rdPtr ) internal pure returns (int112 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int120 at `rdPtr` in returndata. function readInt120( ReturndataPointer rdPtr ) internal pure returns (int120 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int128 at `rdPtr` in returndata. function readInt128( ReturndataPointer rdPtr ) internal pure returns (int128 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int136 at `rdPtr` in returndata. function readInt136( ReturndataPointer rdPtr ) internal pure returns (int136 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int144 at `rdPtr` in returndata. function readInt144( ReturndataPointer rdPtr ) internal pure returns (int144 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int152 at `rdPtr` in returndata. function readInt152( ReturndataPointer rdPtr ) internal pure returns (int152 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int160 at `rdPtr` in returndata. function readInt160( ReturndataPointer rdPtr ) internal pure returns (int160 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int168 at `rdPtr` in returndata. function readInt168( ReturndataPointer rdPtr ) internal pure returns (int168 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int176 at `rdPtr` in returndata. function readInt176( ReturndataPointer rdPtr ) internal pure returns (int176 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int184 at `rdPtr` in returndata. function readInt184( ReturndataPointer rdPtr ) internal pure returns (int184 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int192 at `rdPtr` in returndata. function readInt192( ReturndataPointer rdPtr ) internal pure returns (int192 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int200 at `rdPtr` in returndata. function readInt200( ReturndataPointer rdPtr ) internal pure returns (int200 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int208 at `rdPtr` in returndata. function readInt208( ReturndataPointer rdPtr ) internal pure returns (int208 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int216 at `rdPtr` in returndata. function readInt216( ReturndataPointer rdPtr ) internal pure returns (int216 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int224 at `rdPtr` in returndata. function readInt224( ReturndataPointer rdPtr ) internal pure returns (int224 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int232 at `rdPtr` in returndata. function readInt232( ReturndataPointer rdPtr ) internal pure returns (int232 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int240 at `rdPtr` in returndata. function readInt240( ReturndataPointer rdPtr ) internal pure returns (int240 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int248 at `rdPtr` in returndata. function readInt248( ReturndataPointer rdPtr ) internal pure returns (int248 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } /// @dev Reads the int256 at `rdPtr` in returndata. function readInt256( ReturndataPointer rdPtr ) internal pure returns (int256 value) { assembly { returndatacopy(0, rdPtr, _OneWord) value := mload(0) } } } library MemoryReaders { /// @dev Reads the memory pointer at `mPtr` in memory. function readMemoryPointer( MemoryPointer mPtr ) internal pure returns (MemoryPointer value) { assembly { value := mload(mPtr) } } /// @dev Reads value at `mPtr` & applies a mask to return only last 4 bytes function readMaskedUint256( MemoryPointer mPtr ) internal pure returns (uint256 value) { value = mPtr.readUint256() & OffsetOrLengthMask; } /// @dev Reads the bool at `mPtr` in memory. function readBool(MemoryPointer mPtr) internal pure returns (bool value) { assembly { value := mload(mPtr) } } /// @dev Reads the address at `mPtr` in memory. function readAddress( MemoryPointer mPtr ) internal pure returns (address value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes1 at `mPtr` in memory. function readBytes1( MemoryPointer mPtr ) internal pure returns (bytes1 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes2 at `mPtr` in memory. function readBytes2( MemoryPointer mPtr ) internal pure returns (bytes2 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes3 at `mPtr` in memory. function readBytes3( MemoryPointer mPtr ) internal pure returns (bytes3 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes4 at `mPtr` in memory. function readBytes4( MemoryPointer mPtr ) internal pure returns (bytes4 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes5 at `mPtr` in memory. function readBytes5( MemoryPointer mPtr ) internal pure returns (bytes5 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes6 at `mPtr` in memory. function readBytes6( MemoryPointer mPtr ) internal pure returns (bytes6 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes7 at `mPtr` in memory. function readBytes7( MemoryPointer mPtr ) internal pure returns (bytes7 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes8 at `mPtr` in memory. function readBytes8( MemoryPointer mPtr ) internal pure returns (bytes8 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes9 at `mPtr` in memory. function readBytes9( MemoryPointer mPtr ) internal pure returns (bytes9 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes10 at `mPtr` in memory. function readBytes10( MemoryPointer mPtr ) internal pure returns (bytes10 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes11 at `mPtr` in memory. function readBytes11( MemoryPointer mPtr ) internal pure returns (bytes11 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes12 at `mPtr` in memory. function readBytes12( MemoryPointer mPtr ) internal pure returns (bytes12 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes13 at `mPtr` in memory. function readBytes13( MemoryPointer mPtr ) internal pure returns (bytes13 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes14 at `mPtr` in memory. function readBytes14( MemoryPointer mPtr ) internal pure returns (bytes14 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes15 at `mPtr` in memory. function readBytes15( MemoryPointer mPtr ) internal pure returns (bytes15 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes16 at `mPtr` in memory. function readBytes16( MemoryPointer mPtr ) internal pure returns (bytes16 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes17 at `mPtr` in memory. function readBytes17( MemoryPointer mPtr ) internal pure returns (bytes17 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes18 at `mPtr` in memory. function readBytes18( MemoryPointer mPtr ) internal pure returns (bytes18 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes19 at `mPtr` in memory. function readBytes19( MemoryPointer mPtr ) internal pure returns (bytes19 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes20 at `mPtr` in memory. function readBytes20( MemoryPointer mPtr ) internal pure returns (bytes20 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes21 at `mPtr` in memory. function readBytes21( MemoryPointer mPtr ) internal pure returns (bytes21 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes22 at `mPtr` in memory. function readBytes22( MemoryPointer mPtr ) internal pure returns (bytes22 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes23 at `mPtr` in memory. function readBytes23( MemoryPointer mPtr ) internal pure returns (bytes23 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes24 at `mPtr` in memory. function readBytes24( MemoryPointer mPtr ) internal pure returns (bytes24 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes25 at `mPtr` in memory. function readBytes25( MemoryPointer mPtr ) internal pure returns (bytes25 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes26 at `mPtr` in memory. function readBytes26( MemoryPointer mPtr ) internal pure returns (bytes26 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes27 at `mPtr` in memory. function readBytes27( MemoryPointer mPtr ) internal pure returns (bytes27 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes28 at `mPtr` in memory. function readBytes28( MemoryPointer mPtr ) internal pure returns (bytes28 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes29 at `mPtr` in memory. function readBytes29( MemoryPointer mPtr ) internal pure returns (bytes29 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes30 at `mPtr` in memory. function readBytes30( MemoryPointer mPtr ) internal pure returns (bytes30 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes31 at `mPtr` in memory. function readBytes31( MemoryPointer mPtr ) internal pure returns (bytes31 value) { assembly { value := mload(mPtr) } } /// @dev Reads the bytes32 at `mPtr` in memory. function readBytes32( MemoryPointer mPtr ) internal pure returns (bytes32 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint8 at `mPtr` in memory. function readUint8(MemoryPointer mPtr) internal pure returns (uint8 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint16 at `mPtr` in memory. function readUint16( MemoryPointer mPtr ) internal pure returns (uint16 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint24 at `mPtr` in memory. function readUint24( MemoryPointer mPtr ) internal pure returns (uint24 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint32 at `mPtr` in memory. function readUint32( MemoryPointer mPtr ) internal pure returns (uint32 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint40 at `mPtr` in memory. function readUint40( MemoryPointer mPtr ) internal pure returns (uint40 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint48 at `mPtr` in memory. function readUint48( MemoryPointer mPtr ) internal pure returns (uint48 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint56 at `mPtr` in memory. function readUint56( MemoryPointer mPtr ) internal pure returns (uint56 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint64 at `mPtr` in memory. function readUint64( MemoryPointer mPtr ) internal pure returns (uint64 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint72 at `mPtr` in memory. function readUint72( MemoryPointer mPtr ) internal pure returns (uint72 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint80 at `mPtr` in memory. function readUint80( MemoryPointer mPtr ) internal pure returns (uint80 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint88 at `mPtr` in memory. function readUint88( MemoryPointer mPtr ) internal pure returns (uint88 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint96 at `mPtr` in memory. function readUint96( MemoryPointer mPtr ) internal pure returns (uint96 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint104 at `mPtr` in memory. function readUint104( MemoryPointer mPtr ) internal pure returns (uint104 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint112 at `mPtr` in memory. function readUint112( MemoryPointer mPtr ) internal pure returns (uint112 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint120 at `mPtr` in memory. function readUint120( MemoryPointer mPtr ) internal pure returns (uint120 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint128 at `mPtr` in memory. function readUint128( MemoryPointer mPtr ) internal pure returns (uint128 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint136 at `mPtr` in memory. function readUint136( MemoryPointer mPtr ) internal pure returns (uint136 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint144 at `mPtr` in memory. function readUint144( MemoryPointer mPtr ) internal pure returns (uint144 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint152 at `mPtr` in memory. function readUint152( MemoryPointer mPtr ) internal pure returns (uint152 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint160 at `mPtr` in memory. function readUint160( MemoryPointer mPtr ) internal pure returns (uint160 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint168 at `mPtr` in memory. function readUint168( MemoryPointer mPtr ) internal pure returns (uint168 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint176 at `mPtr` in memory. function readUint176( MemoryPointer mPtr ) internal pure returns (uint176 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint184 at `mPtr` in memory. function readUint184( MemoryPointer mPtr ) internal pure returns (uint184 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint192 at `mPtr` in memory. function readUint192( MemoryPointer mPtr ) internal pure returns (uint192 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint200 at `mPtr` in memory. function readUint200( MemoryPointer mPtr ) internal pure returns (uint200 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint208 at `mPtr` in memory. function readUint208( MemoryPointer mPtr ) internal pure returns (uint208 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint216 at `mPtr` in memory. function readUint216( MemoryPointer mPtr ) internal pure returns (uint216 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint224 at `mPtr` in memory. function readUint224( MemoryPointer mPtr ) internal pure returns (uint224 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint232 at `mPtr` in memory. function readUint232( MemoryPointer mPtr ) internal pure returns (uint232 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint240 at `mPtr` in memory. function readUint240( MemoryPointer mPtr ) internal pure returns (uint240 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint248 at `mPtr` in memory. function readUint248( MemoryPointer mPtr ) internal pure returns (uint248 value) { assembly { value := mload(mPtr) } } /// @dev Reads the uint256 at `mPtr` in memory. function readUint256( MemoryPointer mPtr ) internal pure returns (uint256 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int8 at `mPtr` in memory. function readInt8(MemoryPointer mPtr) internal pure returns (int8 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int16 at `mPtr` in memory. function readInt16(MemoryPointer mPtr) internal pure returns (int16 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int24 at `mPtr` in memory. function readInt24(MemoryPointer mPtr) internal pure returns (int24 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int32 at `mPtr` in memory. function readInt32(MemoryPointer mPtr) internal pure returns (int32 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int40 at `mPtr` in memory. function readInt40(MemoryPointer mPtr) internal pure returns (int40 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int48 at `mPtr` in memory. function readInt48(MemoryPointer mPtr) internal pure returns (int48 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int56 at `mPtr` in memory. function readInt56(MemoryPointer mPtr) internal pure returns (int56 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int64 at `mPtr` in memory. function readInt64(MemoryPointer mPtr) internal pure returns (int64 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int72 at `mPtr` in memory. function readInt72(MemoryPointer mPtr) internal pure returns (int72 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int80 at `mPtr` in memory. function readInt80(MemoryPointer mPtr) internal pure returns (int80 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int88 at `mPtr` in memory. function readInt88(MemoryPointer mPtr) internal pure returns (int88 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int96 at `mPtr` in memory. function readInt96(MemoryPointer mPtr) internal pure returns (int96 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int104 at `mPtr` in memory. function readInt104( MemoryPointer mPtr ) internal pure returns (int104 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int112 at `mPtr` in memory. function readInt112( MemoryPointer mPtr ) internal pure returns (int112 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int120 at `mPtr` in memory. function readInt120( MemoryPointer mPtr ) internal pure returns (int120 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int128 at `mPtr` in memory. function readInt128( MemoryPointer mPtr ) internal pure returns (int128 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int136 at `mPtr` in memory. function readInt136( MemoryPointer mPtr ) internal pure returns (int136 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int144 at `mPtr` in memory. function readInt144( MemoryPointer mPtr ) internal pure returns (int144 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int152 at `mPtr` in memory. function readInt152( MemoryPointer mPtr ) internal pure returns (int152 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int160 at `mPtr` in memory. function readInt160( MemoryPointer mPtr ) internal pure returns (int160 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int168 at `mPtr` in memory. function readInt168( MemoryPointer mPtr ) internal pure returns (int168 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int176 at `mPtr` in memory. function readInt176( MemoryPointer mPtr ) internal pure returns (int176 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int184 at `mPtr` in memory. function readInt184( MemoryPointer mPtr ) internal pure returns (int184 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int192 at `mPtr` in memory. function readInt192( MemoryPointer mPtr ) internal pure returns (int192 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int200 at `mPtr` in memory. function readInt200( MemoryPointer mPtr ) internal pure returns (int200 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int208 at `mPtr` in memory. function readInt208( MemoryPointer mPtr ) internal pure returns (int208 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int216 at `mPtr` in memory. function readInt216( MemoryPointer mPtr ) internal pure returns (int216 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int224 at `mPtr` in memory. function readInt224( MemoryPointer mPtr ) internal pure returns (int224 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int232 at `mPtr` in memory. function readInt232( MemoryPointer mPtr ) internal pure returns (int232 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int240 at `mPtr` in memory. function readInt240( MemoryPointer mPtr ) internal pure returns (int240 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int248 at `mPtr` in memory. function readInt248( MemoryPointer mPtr ) internal pure returns (int248 value) { assembly { value := mload(mPtr) } } /// @dev Reads the int256 at `mPtr` in memory. function readInt256( MemoryPointer mPtr ) internal pure returns (int256 value) { assembly { value := mload(mPtr) } } } library MemoryWriters { /// @dev Writes `valuePtr` to memory at `mPtr`. function write(MemoryPointer mPtr, MemoryPointer valuePtr) internal pure { assembly { mstore(mPtr, valuePtr) } } /// @dev Writes a boolean `value` to `mPtr` in memory. function write(MemoryPointer mPtr, bool value) internal pure { assembly { mstore(mPtr, value) } } /// @dev Writes an address `value` to `mPtr` in memory. function write(MemoryPointer mPtr, address value) internal pure { assembly { mstore(mPtr, value) } } /// @dev Writes a bytes32 `value` to `mPtr` in memory. /// Separate name to disambiguate literal write parameters. function writeBytes32(MemoryPointer mPtr, bytes32 value) internal pure { assembly { mstore(mPtr, value) } } /// @dev Writes a uint256 `value` to `mPtr` in memory. function write(MemoryPointer mPtr, uint256 value) internal pure { assembly { mstore(mPtr, value) } } /// @dev Writes an int256 `value` to `mPtr` in memory. /// Separate name to disambiguate literal write parameters. function writeInt(MemoryPointer mPtr, int256 value) internal pure { assembly { mstore(mPtr, value) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Signature verification helper that supports both ECDSA signatures from EOAs /// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol) /// /// Note: unlike ECDSA signatures, contract signatures are revocable. library SignatureCheckerLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The number which `s` must not exceed in order for /// the signature to be non-malleable. bytes32 private constant _MALLEABILITY_THRESHOLD = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIGNATURE CHECKING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { // Load the free memory pointer. // Simply using the free memory usually costs less if many slots are needed. let m := mload(0x40) let signatureLength := mload(signature) // If the signature is exactly 65 bytes in length. if iszero(xor(signatureLength, 65)) { // Copy `r` and `s`. mstore(add(m, 0x40), mload(add(signature, 0x20))) // `r`. let s := mload(add(signature, 0x40)) mstore(add(m, 0x60), s) // If `s` in lower half order, such that the signature is not malleable. if iszero(gt(s, _MALLEABILITY_THRESHOLD)) { mstore(m, hash) // Compute `v` and store it in the memory. mstore(add(m, 0x20), byte(0, mload(add(signature, 0x60)))) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. m, // Start of input. 0x80, // Size of input. m, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if mul(eq(mload(m), signer), returndatasize()) { isValid := 1 break } } } // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. let f := shl(224, 0x1626ba7e) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(m, f) mstore(add(m, 0x04), hash) mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata. { let j := add(m, 0x44) mstore(j, signatureLength) // The signature length. // Copy the `signature` over. for { let i := 0 } 1 {} { i := add(i, 0x20) mstore(add(j, i), mload(add(signature, i))) if iszero(lt(i, signatureLength)) { break } } } // forgefmt: disable-next-item isValid := and( and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(0x00), f), // Whether the returndata is exactly 0x20 bytes (1 word) long. eq(returndatasize(), 0x20) ), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signatureLength, 0x64), // Length of calldata in memory. 0x00, // Offset of returndata. 0x20 // Length of returndata to write. ) ) break } } } /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { // Load the free memory pointer. // Simply using the free memory usually costs less if many slots are needed. let m := mload(0x40) // If the signature is exactly 65 bytes in length. if iszero(xor(signature.length, 65)) { // Directly copy `r` and `s` from the calldata. calldatacopy(add(m, 0x40), signature.offset, 0x40) // If `s` in lower half order, such that the signature is not malleable. if iszero(gt(mload(add(m, 0x60)), _MALLEABILITY_THRESHOLD)) { mstore(m, hash) // Compute `v` and store it in the memory. mstore(add(m, 0x20), byte(0, calldataload(add(signature.offset, 0x40)))) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. m, // Start of input. 0x80, // Size of input. m, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if mul(eq(mload(m), signer), returndatasize()) { isValid := 1 break } } } // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. let f := shl(224, 0x1626ba7e) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(m, f) mstore(add(m, 0x04), hash) mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // The signature length // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) // forgefmt: disable-next-item isValid := and( and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(0x00), f), // Whether the returndata is exactly 0x20 bytes (1 word) long. eq(returndatasize(), 0x20) ), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signature.length, 0x64), // Length of calldata in memory. 0x00, // Offset of returndata. 0x20 // Length of returndata to write. ) ) break } } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { uint8 v; bytes32 s; /// @solidity memory-safe-assembly assembly { s := shr(1, shl(1, vs)) v := add(shr(255, vs), 27) } isValid = isValidSignatureNow(signer, hash, v, r, s); } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { // Load the free memory pointer. // Simply using the free memory usually costs less if many slots are needed. let m := mload(0x40) // Clean the excess bits of `v` in case they are dirty. v := and(v, 0xff) // If `s` in lower half order, such that the signature is not malleable. if iszero(gt(s, _MALLEABILITY_THRESHOLD)) { mstore(m, hash) mstore(add(m, 0x20), v) mstore(add(m, 0x40), r) mstore(add(m, 0x60), s) pop( staticcall( gas(), // Amount of gas left for the transaction. 0x01, // Address of `ecrecover`. m, // Start of input. 0x80, // Size of input. m, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if mul(eq(mload(m), signer), returndatasize()) { isValid := 1 break } } // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. let f := shl(224, 0x1626ba7e) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Store the length of the signature. mstore(add(m, 0x64), r) // Store `r` of the signature. mstore(add(m, 0x84), s) // Store `s` of the signature. mstore8(add(m, 0xa4), v) // Store `v` of the signature. // forgefmt: disable-next-item isValid := and( and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(0x00), f), // Whether the returndata is exactly 0x20 bytes (1 word) long. eq(returndatasize(), 0x20) ), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. 0x00, // Offset of returndata. 0x20 // Length of returndata to write. ) ) break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC1271 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `signature` is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Load the free memory pointer. // Simply using the free memory usually costs less if many slots are needed. let m := mload(0x40) let signatureLength := mload(signature) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. let f := shl(224, 0x1626ba7e) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(m, f) mstore(add(m, 0x04), hash) mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata. { let j := add(m, 0x44) mstore(j, signatureLength) // The signature length. // Copy the `signature` over. for { let i := 0 } 1 {} { i := add(i, 0x20) mstore(add(j, i), mload(add(signature, i))) if iszero(lt(i, signatureLength)) { break } } } // forgefmt: disable-next-item isValid := and( and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(0x00), f), // Whether the returndata is exactly 0x20 bytes (1 word) long. eq(returndatasize(), 0x20) ), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signatureLength, 0x64), // Length of calldata in memory. 0x00, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether `signature` is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNowCalldata( address signer, bytes32 hash, bytes calldata signature ) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Load the free memory pointer. // Simply using the free memory usually costs less if many slots are needed. let m := mload(0x40) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. let f := shl(224, 0x1626ba7e) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(m, f) mstore(add(m, 0x04), hash) mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // The signature length // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) // forgefmt: disable-next-item isValid := and( and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(0x00), f), // Whether the returndata is exactly 0x20 bytes (1 word) long. eq(returndatasize(), 0x20) ), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signature.length, 0x64), // Length of calldata in memory. 0x00, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { uint8 v; bytes32 s; /// @solidity memory-safe-assembly assembly { s := shr(1, shl(1, vs)) v := add(shr(255, vs), 27) } isValid = isValidERC1271SignatureNow(signer, hash, v, r, s); } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Load the free memory pointer. // Simply using the free memory usually costs less if many slots are needed. let m := mload(0x40) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. let f := shl(224, 0x1626ba7e) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) mstore(add(m, 0x24), 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Store the length of the signature. mstore(add(m, 0x64), r) // Store `r` of the signature. mstore(add(m, 0x84), s) // Store `s` of the signature. mstore8(add(m, 0xa4), v) // Store `v` of the signature. // forgefmt: disable-next-item isValid := and( and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(0x00), f), // Whether the returndata is exactly 0x20 bytes (1 word) long. eq(returndatasize(), 0x20) ), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. 0x00, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes. function emptySignature() internal pure returns (bytes calldata signature) { /// @solidity memory-safe-assembly assembly { signature.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; interface SignedRedeemErrorsAndEvents { error InvalidSigner(); error DigestAlreadyUsed(); }
{ "remappings": [ "@rari-capital/solmate/=lib/seaport-sol/lib/seaport/lib/solmate/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/seaport-sol/lib/seaport/lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "murky/=lib/murky/src/", "openzeppelin-contracts/=lib/murky/lib/openzeppelin-contracts/", "seaport-core/=lib/seaport-core/", "seaport-sol/=lib/seaport-sol/", "seaport-types/=lib/seaport-types/", "seaport/=lib/seaport-sol/lib/seaport/contracts/", "solady/=lib/solady/", "solarray/=lib/solarray/src/", "solmate/=lib/solady/lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"conduit","type":"address"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"address","name":"seaport","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CampaignAlreadyExists","type":"error"},{"inputs":[],"name":"ConsiderationItemRecipientCannotBeZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"ConsiderationRecipientNotFound","type":"error"},{"inputs":[],"name":"DigestAlreadyUsed","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidCampaignId","type":"error"},{"inputs":[{"internalType":"address","name":"got","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"InvalidConsiderationItem","type":"error"},{"inputs":[{"internalType":"uint256","name":"got","type":"uint256"},{"internalType":"uint256","name":"want","type":"uint256"}],"name":"InvalidConsiderationLength","type":"error"},{"inputs":[],"name":"InvalidNativeOfferItem","type":"error"},{"inputs":[{"internalType":"uint256","name":"got","type":"uint256"},{"internalType":"uint256","name":"want","type":"uint256"}],"name":"InvalidOfferLength","type":"error"},{"inputs":[],"name":"InvalidOwner","type":"error"},{"inputs":[{"internalType":"bytes32","name":"got","type":"bytes32"},{"internalType":"bytes32","name":"want","type":"bytes32"}],"name":"InvalidRequiredValue","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[{"internalType":"uint256","name":"substandard","type":"uint256"}],"name":"InvalidSubstandard","type":"error"},{"inputs":[],"name":"InvalidTime","type":"error"},{"inputs":[],"name":"InvalidTraitRedemption","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"InvalidTraitRedemptionToken","type":"error"},{"inputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"MaxCampaignRedemptionsReached","type":"error"},{"inputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"MaxRedemptionsReached","type":"error"},{"inputs":[],"name":"NoConsiderationItems","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentTimestamp","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"NotActive","type":"error"},{"inputs":[],"name":"NotManager","type":"error"},{"inputs":[],"name":"RedeemMismatchedLengths","type":"error"},{"inputs":[],"name":"RedemptionValuesAreImmutable","type":"error"},{"inputs":[{"internalType":"bytes32","name":"traitKey","type":"bytes32"},{"internalType":"bytes32","name":"value","type":"bytes32"}],"name":"TraitValueUnchanged","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"components":[{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxCampaignRedemptions","type":"uint32"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"}],"indexed":false,"internalType":"struct CampaignParams","name":"params","type":"tuple"},{"indexed":false,"internalType":"string","name":"uri","type":"string"}],"name":"CampaignUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"campaignId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"redemptionHash","type":"bytes32"}],"name":"Redemption","type":"event"},{"inputs":[{"components":[{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxCampaignRedemptions","type":"uint32"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"}],"internalType":"struct CampaignParams","name":"params","type":"tuple"},{"internalType":"string","name":"uri","type":"string"}],"name":"createCampaign","outputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"fulfiller","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct SpentItem[]","name":"minimumReceived","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct SpentItem[]","name":"maximumSpent","type":"tuple[]"},{"internalType":"bytes","name":"context","type":"bytes"}],"name":"generateOrder","outputs":[{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct SpentItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ReceivedItem[]","name":"consideration","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"}],"name":"getCampaign","outputs":[{"components":[{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxCampaignRedemptions","type":"uint32"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"}],"internalType":"struct CampaignParams","name":"params","type":"tuple"},{"internalType":"string","name":"uri","type":"string"},{"internalType":"uint256","name":"totalRedemptions","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSeaportMetadata","outputs":[{"internalType":"string","name":"name","type":"string"},{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"metadata","type":"bytes"}],"internalType":"struct Schema[]","name":"schemas","type":"tuple[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"fulfiller","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct SpentItem[]","name":"minimumReceived","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct SpentItem[]","name":"maximumSpent","type":"tuple[]"},{"internalType":"bytes","name":"context","type":"bytes"}],"name":"previewOrder","outputs":[{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct SpentItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ReceivedItem[]","name":"consideration","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct SpentItem[]","name":"","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ReceivedItem[]","name":"","type":"tuple[]"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes32[]","name":"","type":"bytes32[]"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"ratifyOrder","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"components":[{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxCampaignRedemptions","type":"uint32"},{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"}],"internalType":"struct CampaignParams","name":"params","type":"tuple"},{"internalType":"string","name":"uri","type":"string"}],"name":"updateCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignId","type":"uint256"},{"internalType":"string","name":"uri","type":"string"}],"name":"updateCampaignURI","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
61012060405246608052600180553480156200001a57600080fd5b5060405162004877380380620048778339810160408190526200003d9162000125565b620000e6604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f72bd9d4f5e0c77485716a81d0206989b5585b787318a1d712306f456f301ecfa918101919091527fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b360608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b60a0526001600160a01b0392831660e052610100919091521660c05262000166565b80516001600160a01b03811681146200012057600080fd5b919050565b6000806000606084860312156200013b57600080fd5b620001468462000108565b9250602084015191506200015d6040850162000108565b90509250925092565b60805160a05160c05160e0516101005161469b620001dc600039600081816104ac01526105ea01526000818161182d015281816118e60152818161199301528181611aa101528181611b5a0152611c4101526000818161056a0152611d07015260006129b4015260006128df015261469b6000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c80636354d427116100715780636354d42714610187578063989197651461019c578063bc197c81146101af578063dfbbb4dd146101c2578063f23a6e61146101d5578063f4dd92ce146101e857600080fd5b806301ffc9a7146100b9578063150b7a02146100e15780632e778efc1461010d57806330d2bbdc146101235780635598f8cc14610144578063582d424114610166575b600080fd5b6100cc6100c7366004612a12565b6101fb565b60405190151581526020015b60405180910390f35b6100f46100ef366004612aac565b61024d565b6040516001600160e01b031990911681526020016100d8565b610115610687565b6040516100d8929190612b64565b610136610131366004612c00565b610707565b6040519081526020016100d8565b610157610152366004612c68565b6108b4565b6040516100d893929190612d97565b610179610174366004612e8f565b610be0565b6040516100d8929190612fad565b61019a610195366004613040565b610cbb565b005b6101796101aa3660046130af565b610f10565b6100f46101bd36600461319f565b610fd6565b61019a6101d0366004613223565b61138d565b6100f46101e3366004613261565b611428565b6100f46101f63660046132dc565b611745565b60006001600160e01b03198216631be900b160e01b148061022c57506001600160e01b03198216630a85bd0160e11b145b8061024757506001600160e01b03198216630271189760e51b145b92915050565b60006001600160a01b03851661026b5750630a85bd0160e11b61067e565b600061027a60208285876133d8565b61028391613402565b600081815260026020526040808220815160018082528184019093529394509290816020015b6102e56040805160a08101909152806000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b8152602001906001900390816102a9579050506040805160a0810190915290915080600481526020018360020160008154811061032457610324613436565b906000526020600020906004020160000160019054906101000a90046001600160a01b03166001600160a01b03168152602001600081526020016001815260200160018152508160008151811061037d5761037d613436565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a0820152825260001990920191018161039f5750506040805160c081018252600281523360208201529081018a9052600160608201819052608082015261dead60a0820152815191925090829060009061042757610427613436565b60200260200101819052506000604051806101600160405280306001600160a01b0316815260200160006001600160a01b0316815260200184815260200183815260200160048081111561047d5761047d612c81565b815260200142815260200142600a6104959190613462565b81526020016000801b8152602001600081526020017f000000000000000000000000000000000000000000000000000000000000000081526020018351815250905060006040518060a0016040528083815260200160016001600160781b0316815260200160016001600160781b031681526020016040518060200160405280600081525081526020018a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093909452505060408051828152602081019091529293507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169263e7acab24925084916105e7565b6105d46040805160a081019091526000808252602082019081526020016000815260200160008152602001606081525090565b8152602001906001900390816105a15790505b507f00000000000000000000000000000000000000000000000000000000000000008f6040518563ffffffff1660e01b81526004016106299493929190613547565b6020604051808303816000875af1158015610648573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066c91906136c1565b50630a85bd0160e11b96505050505050505b95945050505050565b604080516000808252602082019092526060918291906106ca565b6040805180820190915260008152606060208201528152602001906001900390816106a25790505b5060408051808201909152601a81527f52656465656d61626c6573436f6e74726163744f6666657265720000000000006020820152939092509050565b600061071660c08501856136e3565b90506000036107375760405162beae3760e01b815260040160405180910390fd5b6107476040850160208601613748565b63ffffffff1661075a6020860186613748565b63ffffffff16111561077f576040516337bf561360e11b815260040160405180910390fd5b60005b61078f60c08601866136e3565b90508110156107fe5760006107a760c08701876136e3565b838181106107b7576107b7613436565b905060c0020160a00160208101906107cf9190613765565b6001600160a01b0316036107f65760405163f821dcf560e01b815260040160405180910390fd5b600101610782565b5061081061080b856139cd565b611755565b6001546000908152600260205260409020849061082d8282613da6565b5050600154600090815260036020526040902061084b838583613f39565b505060018054908190600061085f83613ff9565b909155505060008181526003602052604090819020905182917fdb54a1b38e1210a4d1523de422a1c1e3e98ab58faf7869c00bd99dad186a212b916108a5918891614227565b60405180910390a29392505050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915260606000600154841061091557604051636824bccd60e01b815260040160405180910390fd5b6000848152600260208181526040808420815160e081018352815463ffffffff80821683526401000000008204811683870152600160401b820416828501526001600160a01b03600160601b90910481166060830152600183015416608082015293810180548351818602810186019094528084529495919460a08701949192909184015b82821015610a46576000848152602090206040805160a08101909152600484029091018054829060ff1660058111156109d5576109d5612c81565b60058111156109e6576109e6612c81565b81526020016000820160019054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200160018201548152602001600282015481526020016003820154815250508152602001906001019061099a565b50505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b82821015610b2757838290600052602060002090600502016040518060c00160405290816000820160009054906101000a900460ff166005811115610aba57610aba612c81565b6005811115610acb57610acb612c81565b815281546001600160a01b0361010090910481166020808401919091526001808501546040850152600285015460608501526003850154608085015260049094015490911660a090920191909152918352929092019101610a73565b505050915250506000858152600360205260409020805491945090610b4b90613ebf565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7790613ebf565b8015610bc45780601f10610b9957610100808354040283529160200191610bc4565b820191906000526020600020905b815481529060010190602001808311610ba757829003601f168201915b5050506000968752505060046020526040909420549294915050565b6060806129d66129d6611ccd9050809150610ca88b8b8b808060200260200160405190810160405280939291908181526020016000905b82821015610c4357610c3460808302860136819003810190614307565b81526020019060010190610c17565b50505050508a8a808060200260200160405190810160405280939291908181526020016000905b82821015610c9657610c8760808302860136819003810190614307565b81526020019060010190610c6a565b5050505050898960008863ffffffff16565b909d909c509a5050505050505050505050565b831580610cca57506001548410155b15610ce857604051636824bccd60e01b815260040160405180910390fd5b610cf560c08401846136e3565b9050600003610d165760405162beae3760e01b815260040160405180910390fd5b610d266040840160208501613748565b63ffffffff16610d396020850185613748565b63ffffffff161115610d5e576040516337bf561360e11b815260040160405180910390fd5b600084815260026020526040902054600160601b90046001600160a01b031633610d8e6080860160608701613765565b6001600160a01b031614158015610dd957506001600160a01b03811615801590610dd95750610dc36080850160608601613765565b6001600160a01b0316816001600160a01b031614155b15610df75760405163607e454560e11b815260040160405180910390fd5b60005b610e0760c08601866136e3565b9050811015610e76576000610e1f60c08701876136e3565b83818110610e2f57610e2f613436565b905060c0020160a0016020810190610e479190613765565b6001600160a01b031603610e6e5760405163f821dcf560e01b815260040160405180910390fd5b600101610dfa565b50610e8361080b856139cd565b60008581526002602052604090208490610e9d8282613da6565b50508115610ec0576000858152600360205260409020610ebe838583613f39565b505b60008581526003602052604090819020905186917fdb54a1b38e1210a4d1523de422a1c1e3e98ab58faf7869c00bd99dad186a212b91610f01918891614227565b60405180910390a25050505050565b606080610fc6898989808060200260200160405190810160405280939291908181526020016000905b82821015610f6557610f5660808302860136819003810190614307565b81526020019060010190610f39565b50505050508888808060200260200160405190810160405280939291908181526020016000905b82821015610fb857610fa960808302860136819003810190614307565b81526020019060010190610f8c565b505050505087876001611ccd565b909a909950975050505050505050565b60006001600160a01b038816610ff4575063bc197c8160e01b611381565b858414611014576040516331ffa8d360e21b815260040160405180910390fd5b600061102360208285876133d8565b61102c91613402565b600081815260026020526040808220815160018082528184019093529394509290816020015b61105a6129e0565b81526020019060019003908161105257905050604080516080810190915290915080600281526020018360020160008154811061109957611099613436565b906000526020600020906004020160000160019054906101000a90046001600160a01b03166001600160a01b03168152602001836002016000815481106110e2576110e2613436565b90600052602060002090600402016001015481526020018360020160008154811061110f5761110f613436565b9060005260206000209060040201600201548152508160008151811061113757611137613436565b60209081029190910101526000896001600160401b0381111561115c5761115c613420565b60405190808252806020026020018201604052801561119557816020015b6111826129e0565b81526020019060019003908161117a5790505b50905060005b8a8110156112195760408051608081018252600381523360208201529081018d8d848181106111cc576111cc613436565b9050602002013581526020018b8b848181106111ea576111ea613436565b9050602002013581525082828151811061120657611206613436565b602090810291909101015260010161119b565b506112298c83838a8a6001611ccd565b5050600061123a8460030133612603565b9050336001600160a01b0316632eb2c2d630838f8f8f8f6040518763ffffffff1660e01b8152600401611272969594939291906143ad565b600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b50505050836002016000815481106112ba576112ba613436565b906000526020600020906004020160000160019054906101000a90046001600160a01b03166001600160a01b03166342842e0e308f8f8f600081811061130257611302613436565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561135957600080fd5b505af115801561136d573d6000803e3d6000fd5b5063bc197c8160e01b985050505050505050505b98975050505050505050565b60008381526002602052604090208054600160601b90046001600160a01b031633146113cc5760405163607e454560e11b815260040160405180910390fd5b60008481526003602052604090206113e5838583613f39565b50837fdb54a1b38e1210a4d1523de422a1c1e3e98ab58faf7869c00bd99dad186a212b82858560405161141a93929190614527565b60405180910390a250505050565b60006001600160a01b038616611446575063f23a6e6160e01b61173b565b600061145560208285876133d8565b61145e91613402565b600081815260026020526040808220815160018082528184019093529394509290816020015b61148c6129e0565b8152602001906001900390816114845790505060408051608081019091529091508060028152602001836002016000815481106114cb576114cb613436565b906000526020600020906004020160000160019054906101000a90046001600160a01b03166001600160a01b031681526020018360020160008154811061151457611514613436565b90600052602060002090600402016001015481526020018360020160008154811061154157611541613436565b9060005260206000209060040201600201548152508160008151811061156957611569613436565b6020908102919091010152604080516001808252818301909252600091816020015b6115936129e0565b81526020019060019003908161158b57505060408051608081018252600381523360208201529081018b9052606081018a905281519192509082906000906115dd576115dd613436565b60200260200101819052506115f78a83838a8a6001611ccd565b505060006116088460030133612603565b604051637921219560e11b81523060048201526001600160a01b0382166024820152604481018c9052606481018b905260a06084820152600060a4820152909150339063f242432a9060c401600060405180830381600087803b15801561166e57600080fd5b505af1158015611682573d6000803e3d6000fd5b505050508360020160008154811061169c5761169c613436565b60009182526020822060049182020154604051635c46a7ef60e11b815230928101929092526001600160a01b038e81166024840152604483018e905260806064840152608483019390935261010090049091169063b88d4fde9060a401600060405180830381600087803b15801561171357600080fd5b505af1158015611727573d6000803e3d6000fd5b5063f23a6e6160e01b985050505050505050505b9695505050505050565b600063f4dd92ce6000526020601cf35b60005b8160a0015151811015611a1b5760008260a00151828151811061177d5761177d613436565b602002602001015160000151600581111561179a5761179a612c81565b036117b8576040516312d3f5a360e01b815260040160405180910390fd5b60028260a0015182815181106117d0576117d0613436565b60200260200101516000015160058111156117ed576117ed612c81565b10611958578160a00151818151811061180857611808613436565b602090810291909101810151015160405163e985e9c560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301529091169063e985e9c590604401602060405180830381865afa158015611883573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a791906136c1565b611953578160a0015181815181106118c1576118c1613436565b602090810291909101810151015160405163a22cb46560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152600160248301529091169063a22cb46590604401600060405180830381600087803b15801561193a57600080fd5b505af115801561194e573d6000803e3d6000fd5b505050505b611a13565b8160a00151818151811061196e5761196e613436565b602090810291909101810151015160405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156119ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1191906136c1565b505b600101611758565b5060005b8160c0015151811015611cc95760028260c001518281518110611a4457611a44613436565b6020026020010151600001516005811115611a6157611a61612c81565b10611bcc578160c001518181518110611a7c57611a7c613436565b602090810291909101810151015160405163e985e9c560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301529091169063e985e9c590604401602060405180830381865afa158015611af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1b91906136c1565b611bc7578160c001518181518110611b3557611b35613436565b602090810291909101810151015160405163a22cb46560e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152600160248301529091169063a22cb46590604401600060405180830381600087803b158015611bae57600080fd5b505af1158015611bc2573d6000803e3d6000fd5b505050505b611cc1565b60018260c001518281518110611be457611be4613436565b6020026020010151600001516005811115611c0157611c01612c81565b03611cc1578160c001518181518110611c1c57611c1c613436565b602090810291909101810151015160405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015611c9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cbf91906136c1565b505b600101611a1f565b5050565b6060806000611cdf60208287896133d8565b611ce891613402565b6000818152600260205260408120919250611d6c336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614801590611d69575082600301600081548110611d4657611d46613436565b600091825260209091206005909102015461010090046001600160a01b03163314155b90565b8254909150600190611d93904263ffffffff80831682106401000000009093041611151790565b83548b516000878152600460205260409020549290931b9390931792600292611dd392600160401b90920463ffffffff1691611dcf9190613462565b1190565b901b176000611de6604060208a8c6133d8565b611def91613402565b60018401549091506001600160a01b031615611e86576000611e15606060408b8d6133d8565b611e1e91613402565b90506000611e2f8a6060818e6133d8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506001860154909150611e83906001600160a01b03168f8e8686868f6126b5565b50505b8115611fd45760ff82901b15611eb65760405163065ece9760e51b81523360048201526024015b60405180910390fd5b60fe82901b15611efb5782546040516309ed117960e11b815242600482015263ffffffff80831660248301526401000000009092049091166044820152606401611ead565b60fd82901b15611f51578951600085815260046020526040902054611f209190613462565b8354604051631921f9d960e11b81526004810192909252600160401b900463ffffffff166024820152604401611ead565b60fc82901b15611fd45789600081518110611f6e57611f6e613436565b60200260200101516020015183600301600081548110611f9057611f90613436565b600091825260209091206005909102015460405163422d340d60e11b81526001600160a01b0392831660048201526101009091049091166024820152604401611ead565b60028301546001600160401b03811115611ff057611ff0613420565b60405190808252806020026020018201604052801561202957816020015b6120166129e0565b81526020019060019003908161200e5790505b50955060005b600284015481101561220057600084600201828154811061205257612052613436565b600091825260209091206040805160a081019091526004909202018054829060ff16600581111561208557612085612c81565b600581111561209657612096612c81565b815281546001600160a01b0361010090910416602082015260018201546040820152600282015460608201526003909101546080909101529050600081602001516001600160a01b031663caa7a3bf308f6040518363ffffffff1660e01b81526004016121049291906145cc565b6020604051808303816000875af1158015612123573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214791906145f8565b9050600060048351600581111561216057612160612c81565b1461218d5760058351600581111561217a5761217a612c81565b14612186578251612190565b6003612190565b60025b905060405180608001604052808260058111156121af576121af612c81565b815260200184602001516001600160a01b0316815260200183815260200184606001518152508a85815181106121e7576121e7613436565b602002602001018190525083600101935050505061202f565b5060038301546001600160401b0381111561221d5761221d613420565b60405190808252806020026020018201604052801561227657816020015b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825260001990920191018161223b5790505b50945060005b600384015481101561245357600084600301828154811061229f5761229f613436565b90600052602060002090600502016040518060c00160405290816000820160009054906101000a900460ff1660058111156122dc576122dc612c81565b60058111156122ed576122ed612c81565b815281546001600160a01b03610100909104811660208301526001830154604083015260028301546060830152600383015460808301526004928301541660a09091015290915060009081908351600581111561234c5761234c612c81565b14801561235b57506040830151155b1561238957600291508d848151811061237657612376613436565b60200260200101516040015190506123d2565b60058351600581111561239e5761239e612c81565b1480156123ad57506040830151155b156123c857600391508d848151811061237657612376613436565b5050805160408201515b6040518060a001604052808360058111156123ef576123ef612c81565b815260200184602001516001600160a01b03168152602001828152602001846060015181526020018460a001516001600160a01b031681525089858151811061243a5761243a613436565b602002602001018190525083600101935050505061227c565b5086156125f45789516000858152600460205260408120805490919061247a908490613462565b909155505084516000906001600160401b0381111561249b5761249b613420565b6040519080825280602002602001820160405280156124d457816020015b6124c16129e0565b8152602001906001900390816124b95790505b50905060005b86518110156125b757604051806080016040528088838151811061250057612500613436565b602002602001015160000151600581111561251d5761251d612c81565b815260200188838151811061253457612534613436565b6020026020010151602001516001600160a01b0316815260200188838151811061256057612560613436565b602002602001015160400151815260200188838151811061258357612583613436565b6020026020010151606001518152508282815181106125a4576125a4613436565b60209081029190910101526001016124da565b50847f22b74592c6fe41b9abd40d5613fc7f33b093a80c413d044512812b65efbc5e49836040516125ea91815260200190565b60405180910390a2505b50505050965096945050505050565b6000805b835481101561269057826001600160a01b031684828154811061262c5761262c613436565b600091825260209091206005909102015461010090046001600160a01b0316036126885783818154811061266257612662613436565b60009182526020909120600460059092020101546001600160a01b031691506102479050565b600101612607565b50604051639b80195960e01b81526001600160a01b0383166004820152602401611ead565b60006126c387878787612747565b90506126d08882856127ec565b6126ed57604051632057875960e21b815260040160405180910390fd5b60008181526020819052604090205460ff161561271d576040516306542de760e11b815260040160405180910390fd5b811561273d576000818152602081905260409020805460ff191660011790555b5050505050505050565b600061190160f01b6127576128db565b7fc7a2a262d4b4b848fc84384dbfb45673c0280e2483024db24804448579c6c19d87878787604051602001612790959493929190614611565b60408051601f198184030181529082905280516020918201206001600160f01b03199094169082015260228101919091526042810191909152606201604051602081830303815290604052805190602001209050949350505050565b6001600160a01b0390921691600083156128d45760405182516041811861287d576020840151604083015260408401518060608401527f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0811161287b57858352606085015160001a602084015260208360808560015afa503d87845114021561287b57600193505050506128d4565b505b630b135d3f60e11b80835260048301869052604060248401526044830182815260005b60208101905080870151818301528381106128a05750506020600060648401858a5afa60203d148260005114161693505050505b9392505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146129b1576129ac604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f72bd9d4f5e0c77485716a81d0206989b5585b787318a1d712306f456f301ecfa918101919091527fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b360608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b6129de61464f565b565b6040805160808101909152806000815260200160006001600160a01b0316815260200160008152602001600081525090565b600060208284031215612a2457600080fd5b81356001600160e01b0319811681146128d457600080fd5b6001600160a01b0381168114612a5157600080fd5b50565b8035612a5f81612a3c565b919050565b60008083601f840112612a7657600080fd5b5081356001600160401b03811115612a8d57600080fd5b602083019150836020828501011115612aa557600080fd5b9250929050565b600080600080600060808688031215612ac457600080fd5b8535612acf81612a3c565b94506020860135612adf81612a3c565b93506040860135925060608601356001600160401b03811115612b0157600080fd5b612b0d88828901612a64565b969995985093965092949392505050565b6000815180845260005b81811015612b4457602081850181015186830182015201612b28565b506000602082860101526020601f19601f83011685010191505092915050565b60006040808352612b7781840186612b1e565b6020848203818601528186518084528284019150828160051b85010183890160005b83811015612bd857868303601f19018552815180518452860151868401899052612bc589850182612b1e565b9587019593505090850190600101612b99565b50909a9950505050505050505050565b600060e08284031215612bfa57600080fd5b50919050565b600080600060408486031215612c1557600080fd5b83356001600160401b0380821115612c2c57600080fd5b612c3887838801612be8565b94506020860135915080821115612c4e57600080fd5b50612c5b86828701612a64565b9497909650939450505050565b600060208284031215612c7a57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60068110612ca757612ca7612c81565b9052565b600081518084526020808501945080840160005b83811015612d15578151612cd4888251612c97565b838101516001600160a01b03168885015260408082015190890152606080820151908901526080908101519088015260a09096019590820190600101612cbf565b509495945050505050565b600081518084526020808501945080840160005b83811015612d15578151612d49888251612c97565b808401516001600160a01b0390811689860152604080830151908a0152606080830151908a0152608080830151908a015260a091820151169088015260c09096019590820190600101612d34565b6060808252845163ffffffff9081168383015260208601518116608084015260408601511660a08301528401516001600160a01b03811660c08301526000905060808501516001600160a01b03811660e08401525060a085015160e0610100840152612e07610140840182612cab565b905060c0860151605f1984830301610120850152612e258282612d20565b9150508281036020840152612e3a8186612b1e565b915050826040830152949350505050565b60008083601f840112612e5d57600080fd5b5081356001600160401b03811115612e7457600080fd5b6020830191508360208260071b8501011115612aa557600080fd5b60008060008060008060008060a0898b031215612eab57600080fd5b8835612eb681612a3c565b97506020890135612ec681612a3c565b965060408901356001600160401b0380821115612ee257600080fd5b612eee8c838d01612e4b565b909850965060608b0135915080821115612f0757600080fd5b612f138c838d01612e4b565b909650945060808b0135915080821115612f2c57600080fd5b50612f398b828c01612a64565b999c989b5096995094979396929594505050565b600081518084526020808501945080840160005b83811015612d15578151612f76888251612c97565b808401516001600160a01b031688850152604080820151908901526060908101519088015260809096019590820190600101612f61565b60006040808352612fc081840186612f4d565b83810360208581019190915285518083528682019282019060005b81811015613032578451612ff0848251612c97565b848101516001600160a01b039081168587015287820151888601526060808301519086015260809182015116908401529383019360a090920191600101612fdb565b509098975050505050505050565b6000806000806060858703121561305657600080fd5b8435935060208501356001600160401b038082111561307457600080fd5b61308088838901612be8565b9450604087013591508082111561309657600080fd5b506130a387828801612a64565b95989497509550505050565b60008060008060008060006080888a0312156130ca57600080fd5b87356130d581612a3c565b965060208801356001600160401b03808211156130f157600080fd5b6130fd8b838c01612e4b565b909850965060408a013591508082111561311657600080fd5b6131228b838c01612e4b565b909650945060608a013591508082111561313b57600080fd5b506131488a828b01612a64565b989b979a50959850939692959293505050565b60008083601f84011261316d57600080fd5b5081356001600160401b0381111561318457600080fd5b6020830191508360208260051b8501011115612aa557600080fd5b60008060008060008060008060a0898b0312156131bb57600080fd5b88356131c681612a3c565b975060208901356131d681612a3c565b965060408901356001600160401b03808211156131f257600080fd5b6131fe8c838d0161315b565b909850965060608b013591508082111561321757600080fd5b612f138c838d0161315b565b60008060006040848603121561323857600080fd5b8335925060208401356001600160401b0381111561325557600080fd5b612c5b86828701612a64565b60008060008060008060a0878903121561327a57600080fd5b863561328581612a3c565b9550602087013561329581612a3c565b9450604087013593506060870135925060808701356001600160401b038111156132be57600080fd5b6132ca89828a01612a64565b979a9699509497509295939492505050565b600080600080600080600080600060a08a8c0312156132fa57600080fd5b89356001600160401b038082111561331157600080fd5b61331d8d838e01612e4b565b909b50995060208c013591508082111561333657600080fd5b818c0191508c601f83011261334a57600080fd5b81358181111561335957600080fd5b8d602060a08302850101111561336e57600080fd5b6020830199508098505060408c013591508082111561338c57600080fd5b6133988d838e01612a64565b909750955060608c01359150808211156133b157600080fd5b506133be8c828d0161315b565b9a9d999c50979a9699959894979660800135949350505050565b600080858511156133e857600080fd5b838611156133f557600080fd5b5050820193919092039150565b8035602083101561024757600019602084900360031b1b1692915050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156102475761024761344c565b60058110612ca757612ca7612c81565b6000815180845260208085019450848260051b86018286016000805b86811015613539578484038a52825160a08086018251875288830151600281106134cd576134cd612c81565b878a01526040838101519088015260608084015190880152608092830151928701919091528151908190529087019060c086019084905b808210156135245783518352928901929189019160019190910190613504565b50509a87019a945050918501916001016134a1565b509198975050505050505050565b608081526000610120865160a0608085015261356e82850182516001600160a01b03169052565b602081015161014061358a818701836001600160a01b03169052565b60408301516101608781015291506135a6610280870183612cab565b9150606083015161011f19878403016101808801526135c58382612d20565b92505060808301516135db6101a0880182613475565b5060a08301516101c087015260c08301516101e087015260e083015161020087015261010080840151610220880152848401516102408801528184015161026088015260208b0151945061363a60a08801866001600160781b03169052565b60408b01516001600160781b031660c088015260608b0151878403607f1990810160e08a0152909550935061366f8386612b1e565b945060808b01519250838786030181880152505061368d8382612b1e565b9250505082810360208401526136a38187613485565b91505083604083015261067e60608301846001600160a01b03169052565b6000602082840312156136d357600080fd5b815180151581146128d457600080fd5b6000808335601e198436030181126136fa57600080fd5b8301803591506001600160401b0382111561371457600080fd5b602001915060c081023603821315612aa557600080fd5b63ffffffff81168114612a5157600080fd5b8035612a5f8161372b565b60006020828403121561375a57600080fd5b81356128d48161372b565b60006020828403121561377757600080fd5b81356128d481612a3c565b60405160a081016001600160401b03811182821017156137a4576137a4613420565b60405290565b60405160c081016001600160401b03811182821017156137a4576137a4613420565b60405160e081016001600160401b03811182821017156137a4576137a4613420565b604051601f8201601f191681016001600160401b038111828210171561381657613816613420565b604052919050565b60006001600160401b0382111561383757613837613420565b5060051b60200190565b60068110612a5157600080fd5b600082601f83011261385f57600080fd5b8135602061387461386f8361381e565b6137ee565b82815260a0928302850182019282820191908785111561389357600080fd5b8387015b858110156139005781818a0312156138af5760008081fd5b6138b7613782565b81356138c281613841565b8152818601356138d181612a3c565b818701526040828101359082015260608083013590820152608080830135908201528452928401928101613897565b5090979650505050505050565b600082601f83011261391e57600080fd5b8135602061392e61386f8361381e565b82815260c0928302850182019282820191908785111561394d57600080fd5b8387015b858110156139005781818a0312156139695760008081fd5b6139716137aa565b813561397c81613841565b81528186013561398b81612a3c565b8187015260408281013590820152606080830135908201526080808301359082015260a0808301356139bc81612a3c565b908201528452928401928101613951565b600060e082360312156139df57600080fd5b6139e76137cc565b6139f08361373d565b81526139fe6020840161373d565b6020820152613a0f6040840161373d565b6040820152613a2060608401612a54565b6060820152613a3160808401612a54565b608082015260a08301356001600160401b0380821115613a5057600080fd5b613a5c3683870161384e565b60a084015260c0850135915080821115613a7557600080fd5b50613a823682860161390d565b60c08301525092915050565b600081356102478161372b565b6000813561024781612a3c565b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000808335601e19843603018112613adf57600080fd5b8301803591506001600160401b03821115613af957600080fd5b602001915060a081023603821315612aa557600080fd5b60068210613b2057613b20612c81565b60ff1981541660ff831681178255505050565b8054610100600160a81b03191660089290921b610100600160a81b0316919091179055565b8135613b6381613841565b613b6d8183613b10565b506020820135613b7c81612a3c565b613b868183613b33565b506040820135600182015560608201356002820155608082013560038201555050565b600160401b831115613bbd57613bbd613420565b805483825580841015613c375760026001600160fe1b038281168314613be557613be561344c565b8086168614613bf657613bf661344c565b5060008381526020812086831b81019084841b015b80821015613c32578282558260018301558284830155826003830155600482019150613c0b565b505050505b5060008181526020812083915b85811015613c6c57613c568383613b58565b60a0929092019160049190910190600101613c44565b505050505050565b8135613c7f81613841565b613c898183613b10565b506020820135613c9881612a3c565b613ca28183613b33565b5060408201356001820155606082013560028201556080820135600382015560a0820135613ccf81612a3c565b613cdc8160048401613aa8565b505050565b600160401b831115613cf557613cf5613420565b805483825580841015613d715760058181028181048314613d1857613d1861344c565b8582028281048714613d2c57613d2c61344c565b6000858152602081209283019291909101905b82821015613d6c578082558060018301558060028301558060038301558060048301558382019150613d3f565b505050505b5060008181526020812083915b85811015613c6c57613d908383613c74565b60c0929092019160059190910190600101613d7e565b8135613db18161372b565b63ffffffff8116905081548163ffffffff1982161783556020840135613dd68161372b565b67ffffffff000000008160201b16836001600160401b0319841617178455505050613e30613e0660408401613a8e565b82546bffffffff0000000000000000191660409190911b6bffffffff000000000000000016178255565b613e69613e3f60608401613a9b565b82546bffffffffffffffffffffffff1660609190911b6bffffffffffffffffffffffff1916178255565b613e81613e7860808401613a9b565b60018301613aa8565b613e8e60a0830183613ac8565b613e9c818360028601613ba9565b5050613eab60c08301836136e3565b613eb9818360038601613ce1565b50505050565b600181811c90821680613ed357607f821691505b602082108103612bfa57634e487b7160e01b600052602260045260246000fd5b601f821115613cdc57600081815260208120601f850160051c81016020861015613f1a5750805b601f850160051c820191505b81811015613c6c57828155600101613f26565b6001600160401b03831115613f5057613f50613420565b613f6483613f5e8354613ebf565b83613ef3565b6000601f841160018114613f985760008515613f805750838201355b600019600387901b1c1916600186901b178355613ff2565b600083815260209020601f19861690835b82811015613fc95786850135825560209485019460019092019101613fa9565b5086821015613fe65760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60006001820161400b5761400b61344c565b5060010190565b6000808335601e1984360301811261402957600080fd5b83016020810192503590506001600160401b0381111561404857600080fd5b60a081023603821315612aa557600080fd5b8183526000602080850194508260005b85811015612d1557813561407d81613841565b6140878882612c97565b508282013561409581612a3c565b6001600160a01b03168388015260408281013590880152606080830135908801526080808301359088015260a0968701969091019060010161406a565b6000808335601e198436030181126140e957600080fd5b83016020810192503590506001600160401b0381111561410857600080fd5b60c081023603821315612aa557600080fd5b8183526000602080850194508260005b85811015612d1557813561413d81613841565b6141478882612c97565b508282013561415581612a3c565b6001600160a01b039081168885015260408381013590890152606080840135908901526080808401359089015260a0908382013561419281612a3c565b169088015260c096870196919091019060010161412a565b600081546141b781613ebf565b8085526020600183811680156141d457600181146141ee5761421c565b60ff1985168884015283151560051b88018301955061421c565b866000528260002060005b858110156142145781548a82018601529083019084016141f9565b890184019650505b505050505092915050565b60408152600083356142388161372b565b63ffffffff16604083015260208401356142518161372b565b63ffffffff1660608301526142686040850161373d565b63ffffffff16608083015261427f60608501612a54565b6001600160a01b031660a083015261429960808501612a54565b6001600160a01b031660c08301526142b460a0850185614012565b60e0808501526142c96101208501828461405a565b9150506142d960c08601866140d2565b848303603f19016101008601526142f183828461411a565b92505050828103602084015261067e81856141aa565b60006080828403121561431957600080fd5b604051608081018181106001600160401b038211171561433b5761433b613420565b604052823561434981613841565b8152602083013561435981612a3c565b6020820152604083810135908201526060928301359281019290925250919050565b81835260006001600160fb1b0383111561439457600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b0387811682528616602082015260a0604082018190526000906143da908301868861437b565b82810360608401526143ed81858761437b565b8381036080909401939093525050600081526020019695505050505050565b6000815480845260208085019450836000528060002060005b83811015612d1557815461443c8860ff8316612c97565b60081c6001600160a01b0316878401526001828101546040890152600283015460608901526003830154608089015260a0979097019660049092019101614425565b6000815480845260208085019450836000528060002060005b83811015612d155781546144ae8860ff8316612c97565b60081c6001600160a01b039081168885015260018381015460408a0152600284015460608a0152600384015460808a0152600484015490911660a089015260c09097019660059092019101614497565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000845463ffffffff808216604085015261455360608501828460201c1663ffffffff169052565b61456a60808501828460401c1663ffffffff169052565b5060601c60a083015260018501546001600160a01b031660c083015260e08083015261459d61012083016002870161440c565b828103603f19016101008401526145b7816003880161447e565b9050828103602084015261173b8185876144fe565b6001600160a01b03831681526040602082018190526000906145f090830184612f4d565b949350505050565b60006020828403121561460a57600080fd5b5051919050565b8581526001600160a01b038516602082015260a06040820181905260009061463b90830186612f4d565b606083019490945250608001529392505050565b634e487b7160e01b600052605160045260246000fdfea2646970667358221220328bc3ae7622530320e41d1d4e5ff20adf20548eb5147fb4f9fe9692f740e18b64736f6c634300081300330000000000000000000000001e0049783f008a0085193e00003d00cd54003c710000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f000000000000000000000000000000000000000000adc04c56bf30ac9d3c0aaf14dc
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80636354d427116100715780636354d42714610187578063989197651461019c578063bc197c81146101af578063dfbbb4dd146101c2578063f23a6e61146101d5578063f4dd92ce146101e857600080fd5b806301ffc9a7146100b9578063150b7a02146100e15780632e778efc1461010d57806330d2bbdc146101235780635598f8cc14610144578063582d424114610166575b600080fd5b6100cc6100c7366004612a12565b6101fb565b60405190151581526020015b60405180910390f35b6100f46100ef366004612aac565b61024d565b6040516001600160e01b031990911681526020016100d8565b610115610687565b6040516100d8929190612b64565b610136610131366004612c00565b610707565b6040519081526020016100d8565b610157610152366004612c68565b6108b4565b6040516100d893929190612d97565b610179610174366004612e8f565b610be0565b6040516100d8929190612fad565b61019a610195366004613040565b610cbb565b005b6101796101aa3660046130af565b610f10565b6100f46101bd36600461319f565b610fd6565b61019a6101d0366004613223565b61138d565b6100f46101e3366004613261565b611428565b6100f46101f63660046132dc565b611745565b60006001600160e01b03198216631be900b160e01b148061022c57506001600160e01b03198216630a85bd0160e11b145b8061024757506001600160e01b03198216630271189760e51b145b92915050565b60006001600160a01b03851661026b5750630a85bd0160e11b61067e565b600061027a60208285876133d8565b61028391613402565b600081815260026020526040808220815160018082528184019093529394509290816020015b6102e56040805160a08101909152806000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b8152602001906001900390816102a9579050506040805160a0810190915290915080600481526020018360020160008154811061032457610324613436565b906000526020600020906004020160000160019054906101000a90046001600160a01b03166001600160a01b03168152602001600081526020016001815260200160018152508160008151811061037d5761037d613436565b6020908102919091010152604080516001808252818301909252600091816020015b6040805160c08101825260008082526020808301829052928201819052606082018190526080820181905260a0820152825260001990920191018161039f5750506040805160c081018252600281523360208201529081018a9052600160608201819052608082015261dead60a0820152815191925090829060009061042757610427613436565b60200260200101819052506000604051806101600160405280306001600160a01b0316815260200160006001600160a01b0316815260200184815260200183815260200160048081111561047d5761047d612c81565b815260200142815260200142600a6104959190613462565b81526020016000801b8152602001600081526020017f0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f000081526020018351815250905060006040518060a0016040528083815260200160016001600160781b0316815260200160016001600160781b031681526020016040518060200160405280600081525081526020018a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525093909452505060408051828152602081019091529293507f00000000000000000000000000000000000000adc04c56bf30ac9d3c0aaf14dc6001600160a01b03169263e7acab24925084916105e7565b6105d46040805160a081019091526000808252602082019081526020016000815260200160008152602001606081525090565b8152602001906001900390816105a15790505b507f0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f00008f6040518563ffffffff1660e01b81526004016106299493929190613547565b6020604051808303816000875af1158015610648573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066c91906136c1565b50630a85bd0160e11b96505050505050505b95945050505050565b604080516000808252602082019092526060918291906106ca565b6040805180820190915260008152606060208201528152602001906001900390816106a25790505b5060408051808201909152601a81527f52656465656d61626c6573436f6e74726163744f6666657265720000000000006020820152939092509050565b600061071660c08501856136e3565b90506000036107375760405162beae3760e01b815260040160405180910390fd5b6107476040850160208601613748565b63ffffffff1661075a6020860186613748565b63ffffffff16111561077f576040516337bf561360e11b815260040160405180910390fd5b60005b61078f60c08601866136e3565b90508110156107fe5760006107a760c08701876136e3565b838181106107b7576107b7613436565b905060c0020160a00160208101906107cf9190613765565b6001600160a01b0316036107f65760405163f821dcf560e01b815260040160405180910390fd5b600101610782565b5061081061080b856139cd565b611755565b6001546000908152600260205260409020849061082d8282613da6565b5050600154600090815260036020526040902061084b838583613f39565b505060018054908190600061085f83613ff9565b909155505060008181526003602052604090819020905182917fdb54a1b38e1210a4d1523de422a1c1e3e98ab58faf7869c00bd99dad186a212b916108a5918891614227565b60405180910390a29392505050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915260606000600154841061091557604051636824bccd60e01b815260040160405180910390fd5b6000848152600260208181526040808420815160e081018352815463ffffffff80821683526401000000008204811683870152600160401b820416828501526001600160a01b03600160601b90910481166060830152600183015416608082015293810180548351818602810186019094528084529495919460a08701949192909184015b82821015610a46576000848152602090206040805160a08101909152600484029091018054829060ff1660058111156109d5576109d5612c81565b60058111156109e6576109e6612c81565b81526020016000820160019054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200160018201548152602001600282015481526020016003820154815250508152602001906001019061099a565b50505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b82821015610b2757838290600052602060002090600502016040518060c00160405290816000820160009054906101000a900460ff166005811115610aba57610aba612c81565b6005811115610acb57610acb612c81565b815281546001600160a01b0361010090910481166020808401919091526001808501546040850152600285015460608501526003850154608085015260049094015490911660a090920191909152918352929092019101610a73565b505050915250506000858152600360205260409020805491945090610b4b90613ebf565b80601f0160208091040260200160405190810160405280929190818152602001828054610b7790613ebf565b8015610bc45780601f10610b9957610100808354040283529160200191610bc4565b820191906000526020600020905b815481529060010190602001808311610ba757829003601f168201915b5050506000968752505060046020526040909420549294915050565b6060806129d66129d6611ccd9050809150610ca88b8b8b808060200260200160405190810160405280939291908181526020016000905b82821015610c4357610c3460808302860136819003810190614307565b81526020019060010190610c17565b50505050508a8a808060200260200160405190810160405280939291908181526020016000905b82821015610c9657610c8760808302860136819003810190614307565b81526020019060010190610c6a565b5050505050898960008863ffffffff16565b909d909c509a5050505050505050505050565b831580610cca57506001548410155b15610ce857604051636824bccd60e01b815260040160405180910390fd5b610cf560c08401846136e3565b9050600003610d165760405162beae3760e01b815260040160405180910390fd5b610d266040840160208501613748565b63ffffffff16610d396020850185613748565b63ffffffff161115610d5e576040516337bf561360e11b815260040160405180910390fd5b600084815260026020526040902054600160601b90046001600160a01b031633610d8e6080860160608701613765565b6001600160a01b031614158015610dd957506001600160a01b03811615801590610dd95750610dc36080850160608601613765565b6001600160a01b0316816001600160a01b031614155b15610df75760405163607e454560e11b815260040160405180910390fd5b60005b610e0760c08601866136e3565b9050811015610e76576000610e1f60c08701876136e3565b83818110610e2f57610e2f613436565b905060c0020160a0016020810190610e479190613765565b6001600160a01b031603610e6e5760405163f821dcf560e01b815260040160405180910390fd5b600101610dfa565b50610e8361080b856139cd565b60008581526002602052604090208490610e9d8282613da6565b50508115610ec0576000858152600360205260409020610ebe838583613f39565b505b60008581526003602052604090819020905186917fdb54a1b38e1210a4d1523de422a1c1e3e98ab58faf7869c00bd99dad186a212b91610f01918891614227565b60405180910390a25050505050565b606080610fc6898989808060200260200160405190810160405280939291908181526020016000905b82821015610f6557610f5660808302860136819003810190614307565b81526020019060010190610f39565b50505050508888808060200260200160405190810160405280939291908181526020016000905b82821015610fb857610fa960808302860136819003810190614307565b81526020019060010190610f8c565b505050505087876001611ccd565b909a909950975050505050505050565b60006001600160a01b038816610ff4575063bc197c8160e01b611381565b858414611014576040516331ffa8d360e21b815260040160405180910390fd5b600061102360208285876133d8565b61102c91613402565b600081815260026020526040808220815160018082528184019093529394509290816020015b61105a6129e0565b81526020019060019003908161105257905050604080516080810190915290915080600281526020018360020160008154811061109957611099613436565b906000526020600020906004020160000160019054906101000a90046001600160a01b03166001600160a01b03168152602001836002016000815481106110e2576110e2613436565b90600052602060002090600402016001015481526020018360020160008154811061110f5761110f613436565b9060005260206000209060040201600201548152508160008151811061113757611137613436565b60209081029190910101526000896001600160401b0381111561115c5761115c613420565b60405190808252806020026020018201604052801561119557816020015b6111826129e0565b81526020019060019003908161117a5790505b50905060005b8a8110156112195760408051608081018252600381523360208201529081018d8d848181106111cc576111cc613436565b9050602002013581526020018b8b848181106111ea576111ea613436565b9050602002013581525082828151811061120657611206613436565b602090810291909101015260010161119b565b506112298c83838a8a6001611ccd565b5050600061123a8460030133612603565b9050336001600160a01b0316632eb2c2d630838f8f8f8f6040518763ffffffff1660e01b8152600401611272969594939291906143ad565b600060405180830381600087803b15801561128c57600080fd5b505af11580156112a0573d6000803e3d6000fd5b50505050836002016000815481106112ba576112ba613436565b906000526020600020906004020160000160019054906101000a90046001600160a01b03166001600160a01b03166342842e0e308f8f8f600081811061130257611302613436565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561135957600080fd5b505af115801561136d573d6000803e3d6000fd5b5063bc197c8160e01b985050505050505050505b98975050505050505050565b60008381526002602052604090208054600160601b90046001600160a01b031633146113cc5760405163607e454560e11b815260040160405180910390fd5b60008481526003602052604090206113e5838583613f39565b50837fdb54a1b38e1210a4d1523de422a1c1e3e98ab58faf7869c00bd99dad186a212b82858560405161141a93929190614527565b60405180910390a250505050565b60006001600160a01b038616611446575063f23a6e6160e01b61173b565b600061145560208285876133d8565b61145e91613402565b600081815260026020526040808220815160018082528184019093529394509290816020015b61148c6129e0565b8152602001906001900390816114845790505060408051608081019091529091508060028152602001836002016000815481106114cb576114cb613436565b906000526020600020906004020160000160019054906101000a90046001600160a01b03166001600160a01b031681526020018360020160008154811061151457611514613436565b90600052602060002090600402016001015481526020018360020160008154811061154157611541613436565b9060005260206000209060040201600201548152508160008151811061156957611569613436565b6020908102919091010152604080516001808252818301909252600091816020015b6115936129e0565b81526020019060019003908161158b57505060408051608081018252600381523360208201529081018b9052606081018a905281519192509082906000906115dd576115dd613436565b60200260200101819052506115f78a83838a8a6001611ccd565b505060006116088460030133612603565b604051637921219560e11b81523060048201526001600160a01b0382166024820152604481018c9052606481018b905260a06084820152600060a4820152909150339063f242432a9060c401600060405180830381600087803b15801561166e57600080fd5b505af1158015611682573d6000803e3d6000fd5b505050508360020160008154811061169c5761169c613436565b60009182526020822060049182020154604051635c46a7ef60e11b815230928101929092526001600160a01b038e81166024840152604483018e905260806064840152608483019390935261010090049091169063b88d4fde9060a401600060405180830381600087803b15801561171357600080fd5b505af1158015611727573d6000803e3d6000fd5b5063f23a6e6160e01b985050505050505050505b9695505050505050565b600063f4dd92ce6000526020601cf35b60005b8160a0015151811015611a1b5760008260a00151828151811061177d5761177d613436565b602002602001015160000151600581111561179a5761179a612c81565b036117b8576040516312d3f5a360e01b815260040160405180910390fd5b60028260a0015182815181106117d0576117d0613436565b60200260200101516000015160058111156117ed576117ed612c81565b10611958578160a00151818151811061180857611808613436565b602090810291909101810151015160405163e985e9c560e01b81526001600160a01b037f0000000000000000000000001e0049783f008a0085193e00003d00cd54003c71811660048301523060248301529091169063e985e9c590604401602060405180830381865afa158015611883573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a791906136c1565b611953578160a0015181815181106118c1576118c1613436565b602090810291909101810151015160405163a22cb46560e01b81526001600160a01b037f0000000000000000000000001e0049783f008a0085193e00003d00cd54003c7181166004830152600160248301529091169063a22cb46590604401600060405180830381600087803b15801561193a57600080fd5b505af115801561194e573d6000803e3d6000fd5b505050505b611a13565b8160a00151818151811061196e5761196e613436565b602090810291909101810151015160405163095ea7b360e01b81526001600160a01b037f0000000000000000000000001e0049783f008a0085193e00003d00cd54003c718116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af11580156119ed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a1191906136c1565b505b600101611758565b5060005b8160c0015151811015611cc95760028260c001518281518110611a4457611a44613436565b6020026020010151600001516005811115611a6157611a61612c81565b10611bcc578160c001518181518110611a7c57611a7c613436565b602090810291909101810151015160405163e985e9c560e01b81526001600160a01b037f0000000000000000000000001e0049783f008a0085193e00003d00cd54003c71811660048301523060248301529091169063e985e9c590604401602060405180830381865afa158015611af7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1b91906136c1565b611bc7578160c001518181518110611b3557611b35613436565b602090810291909101810151015160405163a22cb46560e01b81526001600160a01b037f0000000000000000000000001e0049783f008a0085193e00003d00cd54003c7181166004830152600160248301529091169063a22cb46590604401600060405180830381600087803b158015611bae57600080fd5b505af1158015611bc2573d6000803e3d6000fd5b505050505b611cc1565b60018260c001518281518110611be457611be4613436565b6020026020010151600001516005811115611c0157611c01612c81565b03611cc1578160c001518181518110611c1c57611c1c613436565b602090810291909101810151015160405163095ea7b360e01b81526001600160a01b037f0000000000000000000000001e0049783f008a0085193e00003d00cd54003c718116600483015260001960248301529091169063095ea7b3906044016020604051808303816000875af1158015611c9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cbf91906136c1565b505b600101611a1f565b5050565b6060806000611cdf60208287896133d8565b611ce891613402565b6000818152600260205260408120919250611d6c336001600160a01b037f00000000000000000000000000000000000000adc04c56bf30ac9d3c0aaf14dc1614801590611d69575082600301600081548110611d4657611d46613436565b600091825260209091206005909102015461010090046001600160a01b03163314155b90565b8254909150600190611d93904263ffffffff80831682106401000000009093041611151790565b83548b516000878152600460205260409020549290931b9390931792600292611dd392600160401b90920463ffffffff1691611dcf9190613462565b1190565b901b176000611de6604060208a8c6133d8565b611def91613402565b60018401549091506001600160a01b031615611e86576000611e15606060408b8d6133d8565b611e1e91613402565b90506000611e2f8a6060818e6133d8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050506001860154909150611e83906001600160a01b03168f8e8686868f6126b5565b50505b8115611fd45760ff82901b15611eb65760405163065ece9760e51b81523360048201526024015b60405180910390fd5b60fe82901b15611efb5782546040516309ed117960e11b815242600482015263ffffffff80831660248301526401000000009092049091166044820152606401611ead565b60fd82901b15611f51578951600085815260046020526040902054611f209190613462565b8354604051631921f9d960e11b81526004810192909252600160401b900463ffffffff166024820152604401611ead565b60fc82901b15611fd45789600081518110611f6e57611f6e613436565b60200260200101516020015183600301600081548110611f9057611f90613436565b600091825260209091206005909102015460405163422d340d60e11b81526001600160a01b0392831660048201526101009091049091166024820152604401611ead565b60028301546001600160401b03811115611ff057611ff0613420565b60405190808252806020026020018201604052801561202957816020015b6120166129e0565b81526020019060019003908161200e5790505b50955060005b600284015481101561220057600084600201828154811061205257612052613436565b600091825260209091206040805160a081019091526004909202018054829060ff16600581111561208557612085612c81565b600581111561209657612096612c81565b815281546001600160a01b0361010090910416602082015260018201546040820152600282015460608201526003909101546080909101529050600081602001516001600160a01b031663caa7a3bf308f6040518363ffffffff1660e01b81526004016121049291906145cc565b6020604051808303816000875af1158015612123573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061214791906145f8565b9050600060048351600581111561216057612160612c81565b1461218d5760058351600581111561217a5761217a612c81565b14612186578251612190565b6003612190565b60025b905060405180608001604052808260058111156121af576121af612c81565b815260200184602001516001600160a01b0316815260200183815260200184606001518152508a85815181106121e7576121e7613436565b602002602001018190525083600101935050505061202f565b5060038301546001600160401b0381111561221d5761221d613420565b60405190808252806020026020018201604052801561227657816020015b6040805160a08101825260008082526020808301829052928201819052606082018190526080820152825260001990920191018161223b5790505b50945060005b600384015481101561245357600084600301828154811061229f5761229f613436565b90600052602060002090600502016040518060c00160405290816000820160009054906101000a900460ff1660058111156122dc576122dc612c81565b60058111156122ed576122ed612c81565b815281546001600160a01b03610100909104811660208301526001830154604083015260028301546060830152600383015460808301526004928301541660a09091015290915060009081908351600581111561234c5761234c612c81565b14801561235b57506040830151155b1561238957600291508d848151811061237657612376613436565b60200260200101516040015190506123d2565b60058351600581111561239e5761239e612c81565b1480156123ad57506040830151155b156123c857600391508d848151811061237657612376613436565b5050805160408201515b6040518060a001604052808360058111156123ef576123ef612c81565b815260200184602001516001600160a01b03168152602001828152602001846060015181526020018460a001516001600160a01b031681525089858151811061243a5761243a613436565b602002602001018190525083600101935050505061227c565b5086156125f45789516000858152600460205260408120805490919061247a908490613462565b909155505084516000906001600160401b0381111561249b5761249b613420565b6040519080825280602002602001820160405280156124d457816020015b6124c16129e0565b8152602001906001900390816124b95790505b50905060005b86518110156125b757604051806080016040528088838151811061250057612500613436565b602002602001015160000151600581111561251d5761251d612c81565b815260200188838151811061253457612534613436565b6020026020010151602001516001600160a01b0316815260200188838151811061256057612560613436565b602002602001015160400151815260200188838151811061258357612583613436565b6020026020010151606001518152508282815181106125a4576125a4613436565b60209081029190910101526001016124da565b50847f22b74592c6fe41b9abd40d5613fc7f33b093a80c413d044512812b65efbc5e49836040516125ea91815260200190565b60405180910390a2505b50505050965096945050505050565b6000805b835481101561269057826001600160a01b031684828154811061262c5761262c613436565b600091825260209091206005909102015461010090046001600160a01b0316036126885783818154811061266257612662613436565b60009182526020909120600460059092020101546001600160a01b031691506102479050565b600101612607565b50604051639b80195960e01b81526001600160a01b0383166004820152602401611ead565b60006126c387878787612747565b90506126d08882856127ec565b6126ed57604051632057875960e21b815260040160405180910390fd5b60008181526020819052604090205460ff161561271d576040516306542de760e11b815260040160405180910390fd5b811561273d576000818152602081905260409020805460ff191660011790555b5050505050505050565b600061190160f01b6127576128db565b7fc7a2a262d4b4b848fc84384dbfb45673c0280e2483024db24804448579c6c19d87878787604051602001612790959493929190614611565b60408051601f198184030181529082905280516020918201206001600160f01b03199094169082015260228101919091526042810191909152606201604051602081830303815290604052805190602001209050949350505050565b6001600160a01b0390921691600083156128d45760405182516041811861287d576020840151604083015260408401518060608401527f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0811161287b57858352606085015160001a602084015260208360808560015afa503d87845114021561287b57600193505050506128d4565b505b630b135d3f60e11b80835260048301869052604060248401526044830182815260005b60208101905080870151818301528381106128a05750506020600060648401858a5afa60203d148260005114161693505050505b9392505050565b60007f000000000000000000000000000000000000000000000000000000000000000146146129b1576129ac604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f72bd9d4f5e0c77485716a81d0206989b5585b787318a1d712306f456f301ecfa918101919091527fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b360608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b905090565b507fd5e4205d2b2a3fdd82a9d84e8241d38424396c0e2410ae26f8424aaba50dc36090565b6129de61464f565b565b6040805160808101909152806000815260200160006001600160a01b0316815260200160008152602001600081525090565b600060208284031215612a2457600080fd5b81356001600160e01b0319811681146128d457600080fd5b6001600160a01b0381168114612a5157600080fd5b50565b8035612a5f81612a3c565b919050565b60008083601f840112612a7657600080fd5b5081356001600160401b03811115612a8d57600080fd5b602083019150836020828501011115612aa557600080fd5b9250929050565b600080600080600060808688031215612ac457600080fd5b8535612acf81612a3c565b94506020860135612adf81612a3c565b93506040860135925060608601356001600160401b03811115612b0157600080fd5b612b0d88828901612a64565b969995985093965092949392505050565b6000815180845260005b81811015612b4457602081850181015186830182015201612b28565b506000602082860101526020601f19601f83011685010191505092915050565b60006040808352612b7781840186612b1e565b6020848203818601528186518084528284019150828160051b85010183890160005b83811015612bd857868303601f19018552815180518452860151868401899052612bc589850182612b1e565b9587019593505090850190600101612b99565b50909a9950505050505050505050565b600060e08284031215612bfa57600080fd5b50919050565b600080600060408486031215612c1557600080fd5b83356001600160401b0380821115612c2c57600080fd5b612c3887838801612be8565b94506020860135915080821115612c4e57600080fd5b50612c5b86828701612a64565b9497909650939450505050565b600060208284031215612c7a57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60068110612ca757612ca7612c81565b9052565b600081518084526020808501945080840160005b83811015612d15578151612cd4888251612c97565b838101516001600160a01b03168885015260408082015190890152606080820151908901526080908101519088015260a09096019590820190600101612cbf565b509495945050505050565b600081518084526020808501945080840160005b83811015612d15578151612d49888251612c97565b808401516001600160a01b0390811689860152604080830151908a0152606080830151908a0152608080830151908a015260a091820151169088015260c09096019590820190600101612d34565b6060808252845163ffffffff9081168383015260208601518116608084015260408601511660a08301528401516001600160a01b03811660c08301526000905060808501516001600160a01b03811660e08401525060a085015160e0610100840152612e07610140840182612cab565b905060c0860151605f1984830301610120850152612e258282612d20565b9150508281036020840152612e3a8186612b1e565b915050826040830152949350505050565b60008083601f840112612e5d57600080fd5b5081356001600160401b03811115612e7457600080fd5b6020830191508360208260071b8501011115612aa557600080fd5b60008060008060008060008060a0898b031215612eab57600080fd5b8835612eb681612a3c565b97506020890135612ec681612a3c565b965060408901356001600160401b0380821115612ee257600080fd5b612eee8c838d01612e4b565b909850965060608b0135915080821115612f0757600080fd5b612f138c838d01612e4b565b909650945060808b0135915080821115612f2c57600080fd5b50612f398b828c01612a64565b999c989b5096995094979396929594505050565b600081518084526020808501945080840160005b83811015612d15578151612f76888251612c97565b808401516001600160a01b031688850152604080820151908901526060908101519088015260809096019590820190600101612f61565b60006040808352612fc081840186612f4d565b83810360208581019190915285518083528682019282019060005b81811015613032578451612ff0848251612c97565b848101516001600160a01b039081168587015287820151888601526060808301519086015260809182015116908401529383019360a090920191600101612fdb565b509098975050505050505050565b6000806000806060858703121561305657600080fd5b8435935060208501356001600160401b038082111561307457600080fd5b61308088838901612be8565b9450604087013591508082111561309657600080fd5b506130a387828801612a64565b95989497509550505050565b60008060008060008060006080888a0312156130ca57600080fd5b87356130d581612a3c565b965060208801356001600160401b03808211156130f157600080fd5b6130fd8b838c01612e4b565b909850965060408a013591508082111561311657600080fd5b6131228b838c01612e4b565b909650945060608a013591508082111561313b57600080fd5b506131488a828b01612a64565b989b979a50959850939692959293505050565b60008083601f84011261316d57600080fd5b5081356001600160401b0381111561318457600080fd5b6020830191508360208260051b8501011115612aa557600080fd5b60008060008060008060008060a0898b0312156131bb57600080fd5b88356131c681612a3c565b975060208901356131d681612a3c565b965060408901356001600160401b03808211156131f257600080fd5b6131fe8c838d0161315b565b909850965060608b013591508082111561321757600080fd5b612f138c838d0161315b565b60008060006040848603121561323857600080fd5b8335925060208401356001600160401b0381111561325557600080fd5b612c5b86828701612a64565b60008060008060008060a0878903121561327a57600080fd5b863561328581612a3c565b9550602087013561329581612a3c565b9450604087013593506060870135925060808701356001600160401b038111156132be57600080fd5b6132ca89828a01612a64565b979a9699509497509295939492505050565b600080600080600080600080600060a08a8c0312156132fa57600080fd5b89356001600160401b038082111561331157600080fd5b61331d8d838e01612e4b565b909b50995060208c013591508082111561333657600080fd5b818c0191508c601f83011261334a57600080fd5b81358181111561335957600080fd5b8d602060a08302850101111561336e57600080fd5b6020830199508098505060408c013591508082111561338c57600080fd5b6133988d838e01612a64565b909750955060608c01359150808211156133b157600080fd5b506133be8c828d0161315b565b9a9d999c50979a9699959894979660800135949350505050565b600080858511156133e857600080fd5b838611156133f557600080fd5b5050820193919092039150565b8035602083101561024757600019602084900360031b1b1692915050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156102475761024761344c565b60058110612ca757612ca7612c81565b6000815180845260208085019450848260051b86018286016000805b86811015613539578484038a52825160a08086018251875288830151600281106134cd576134cd612c81565b878a01526040838101519088015260608084015190880152608092830151928701919091528151908190529087019060c086019084905b808210156135245783518352928901929189019160019190910190613504565b50509a87019a945050918501916001016134a1565b509198975050505050505050565b608081526000610120865160a0608085015261356e82850182516001600160a01b03169052565b602081015161014061358a818701836001600160a01b03169052565b60408301516101608781015291506135a6610280870183612cab565b9150606083015161011f19878403016101808801526135c58382612d20565b92505060808301516135db6101a0880182613475565b5060a08301516101c087015260c08301516101e087015260e083015161020087015261010080840151610220880152848401516102408801528184015161026088015260208b0151945061363a60a08801866001600160781b03169052565b60408b01516001600160781b031660c088015260608b0151878403607f1990810160e08a0152909550935061366f8386612b1e565b945060808b01519250838786030181880152505061368d8382612b1e565b9250505082810360208401526136a38187613485565b91505083604083015261067e60608301846001600160a01b03169052565b6000602082840312156136d357600080fd5b815180151581146128d457600080fd5b6000808335601e198436030181126136fa57600080fd5b8301803591506001600160401b0382111561371457600080fd5b602001915060c081023603821315612aa557600080fd5b63ffffffff81168114612a5157600080fd5b8035612a5f8161372b565b60006020828403121561375a57600080fd5b81356128d48161372b565b60006020828403121561377757600080fd5b81356128d481612a3c565b60405160a081016001600160401b03811182821017156137a4576137a4613420565b60405290565b60405160c081016001600160401b03811182821017156137a4576137a4613420565b60405160e081016001600160401b03811182821017156137a4576137a4613420565b604051601f8201601f191681016001600160401b038111828210171561381657613816613420565b604052919050565b60006001600160401b0382111561383757613837613420565b5060051b60200190565b60068110612a5157600080fd5b600082601f83011261385f57600080fd5b8135602061387461386f8361381e565b6137ee565b82815260a0928302850182019282820191908785111561389357600080fd5b8387015b858110156139005781818a0312156138af5760008081fd5b6138b7613782565b81356138c281613841565b8152818601356138d181612a3c565b818701526040828101359082015260608083013590820152608080830135908201528452928401928101613897565b5090979650505050505050565b600082601f83011261391e57600080fd5b8135602061392e61386f8361381e565b82815260c0928302850182019282820191908785111561394d57600080fd5b8387015b858110156139005781818a0312156139695760008081fd5b6139716137aa565b813561397c81613841565b81528186013561398b81612a3c565b8187015260408281013590820152606080830135908201526080808301359082015260a0808301356139bc81612a3c565b908201528452928401928101613951565b600060e082360312156139df57600080fd5b6139e76137cc565b6139f08361373d565b81526139fe6020840161373d565b6020820152613a0f6040840161373d565b6040820152613a2060608401612a54565b6060820152613a3160808401612a54565b608082015260a08301356001600160401b0380821115613a5057600080fd5b613a5c3683870161384e565b60a084015260c0850135915080821115613a7557600080fd5b50613a823682860161390d565b60c08301525092915050565b600081356102478161372b565b6000813561024781612a3c565b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000808335601e19843603018112613adf57600080fd5b8301803591506001600160401b03821115613af957600080fd5b602001915060a081023603821315612aa557600080fd5b60068210613b2057613b20612c81565b60ff1981541660ff831681178255505050565b8054610100600160a81b03191660089290921b610100600160a81b0316919091179055565b8135613b6381613841565b613b6d8183613b10565b506020820135613b7c81612a3c565b613b868183613b33565b506040820135600182015560608201356002820155608082013560038201555050565b600160401b831115613bbd57613bbd613420565b805483825580841015613c375760026001600160fe1b038281168314613be557613be561344c565b8086168614613bf657613bf661344c565b5060008381526020812086831b81019084841b015b80821015613c32578282558260018301558284830155826003830155600482019150613c0b565b505050505b5060008181526020812083915b85811015613c6c57613c568383613b58565b60a0929092019160049190910190600101613c44565b505050505050565b8135613c7f81613841565b613c898183613b10565b506020820135613c9881612a3c565b613ca28183613b33565b5060408201356001820155606082013560028201556080820135600382015560a0820135613ccf81612a3c565b613cdc8160048401613aa8565b505050565b600160401b831115613cf557613cf5613420565b805483825580841015613d715760058181028181048314613d1857613d1861344c565b8582028281048714613d2c57613d2c61344c565b6000858152602081209283019291909101905b82821015613d6c578082558060018301558060028301558060038301558060048301558382019150613d3f565b505050505b5060008181526020812083915b85811015613c6c57613d908383613c74565b60c0929092019160059190910190600101613d7e565b8135613db18161372b565b63ffffffff8116905081548163ffffffff1982161783556020840135613dd68161372b565b67ffffffff000000008160201b16836001600160401b0319841617178455505050613e30613e0660408401613a8e565b82546bffffffff0000000000000000191660409190911b6bffffffff000000000000000016178255565b613e69613e3f60608401613a9b565b82546bffffffffffffffffffffffff1660609190911b6bffffffffffffffffffffffff1916178255565b613e81613e7860808401613a9b565b60018301613aa8565b613e8e60a0830183613ac8565b613e9c818360028601613ba9565b5050613eab60c08301836136e3565b613eb9818360038601613ce1565b50505050565b600181811c90821680613ed357607f821691505b602082108103612bfa57634e487b7160e01b600052602260045260246000fd5b601f821115613cdc57600081815260208120601f850160051c81016020861015613f1a5750805b601f850160051c820191505b81811015613c6c57828155600101613f26565b6001600160401b03831115613f5057613f50613420565b613f6483613f5e8354613ebf565b83613ef3565b6000601f841160018114613f985760008515613f805750838201355b600019600387901b1c1916600186901b178355613ff2565b600083815260209020601f19861690835b82811015613fc95786850135825560209485019460019092019101613fa9565b5086821015613fe65760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b60006001820161400b5761400b61344c565b5060010190565b6000808335601e1984360301811261402957600080fd5b83016020810192503590506001600160401b0381111561404857600080fd5b60a081023603821315612aa557600080fd5b8183526000602080850194508260005b85811015612d1557813561407d81613841565b6140878882612c97565b508282013561409581612a3c565b6001600160a01b03168388015260408281013590880152606080830135908801526080808301359088015260a0968701969091019060010161406a565b6000808335601e198436030181126140e957600080fd5b83016020810192503590506001600160401b0381111561410857600080fd5b60c081023603821315612aa557600080fd5b8183526000602080850194508260005b85811015612d1557813561413d81613841565b6141478882612c97565b508282013561415581612a3c565b6001600160a01b039081168885015260408381013590890152606080840135908901526080808401359089015260a0908382013561419281612a3c565b169088015260c096870196919091019060010161412a565b600081546141b781613ebf565b8085526020600183811680156141d457600181146141ee5761421c565b60ff1985168884015283151560051b88018301955061421c565b866000528260002060005b858110156142145781548a82018601529083019084016141f9565b890184019650505b505050505092915050565b60408152600083356142388161372b565b63ffffffff16604083015260208401356142518161372b565b63ffffffff1660608301526142686040850161373d565b63ffffffff16608083015261427f60608501612a54565b6001600160a01b031660a083015261429960808501612a54565b6001600160a01b031660c08301526142b460a0850185614012565b60e0808501526142c96101208501828461405a565b9150506142d960c08601866140d2565b848303603f19016101008601526142f183828461411a565b92505050828103602084015261067e81856141aa565b60006080828403121561431957600080fd5b604051608081018181106001600160401b038211171561433b5761433b613420565b604052823561434981613841565b8152602083013561435981612a3c565b6020820152604083810135908201526060928301359281019290925250919050565b81835260006001600160fb1b0383111561439457600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b0387811682528616602082015260a0604082018190526000906143da908301868861437b565b82810360608401526143ed81858761437b565b8381036080909401939093525050600081526020019695505050505050565b6000815480845260208085019450836000528060002060005b83811015612d1557815461443c8860ff8316612c97565b60081c6001600160a01b0316878401526001828101546040890152600283015460608901526003830154608089015260a0979097019660049092019101614425565b6000815480845260208085019450836000528060002060005b83811015612d155781546144ae8860ff8316612c97565b60081c6001600160a01b039081168885015260018381015460408a0152600284015460608a0152600384015460808a0152600484015490911660a089015260c09097019660059092019101614497565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000845463ffffffff808216604085015261455360608501828460201c1663ffffffff169052565b61456a60808501828460401c1663ffffffff169052565b5060601c60a083015260018501546001600160a01b031660c083015260e08083015261459d61012083016002870161440c565b828103603f19016101008401526145b7816003880161447e565b9050828103602084015261173b8185876144fe565b6001600160a01b03831681526040602082018190526000906145f090830184612f4d565b949350505050565b60006020828403121561460a57600080fd5b5051919050565b8581526001600160a01b038516602082015260a06040820181905260009061463b90830186612f4d565b606083019490945250608001529392505050565b634e487b7160e01b600052605160045260246000fdfea2646970667358221220328bc3ae7622530320e41d1d4e5ff20adf20548eb5147fb4f9fe9692f740e18b64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001e0049783f008a0085193e00003d00cd54003c710000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f000000000000000000000000000000000000000000adc04c56bf30ac9d3c0aaf14dc
-----Decoded View---------------
Arg [0] : conduit (address): 0x1E0049783F008A0085193E00003D00cd54003c71
Arg [1] : conduitKey (bytes32): 0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000
Arg [2] : seaport (address): 0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000001e0049783f008a0085193e00003d00cd54003c71
Arg [1] : 0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000
Arg [2] : 00000000000000000000000000000000000000adc04c56bf30ac9d3c0aaf14dc
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.