ETH Price: $2,135.10 (+3.60%)

Transaction Decoder

Block:
10959411 at Sep-29-2020 08:06:29 PM +UTC
Transaction Fee:
0.002331 ETH $4.98
Gas Used:
38,850 Gas / 60 Gwei

Emitted Events:

108 ERC1155Sale.CloseOrder( token=0xd07dc426...a461d2430, tokenId=494, owner=[Sender] 0xf64579f9f76e060e6e3fc88441d5147f722e9405, nonce=3 )

Account State Difference:

  Address   Before After State Difference Code
(zhizhu.top)
2,483.808168804218880919 Eth2,483.810499804218880919 Eth0.002331
0x295fE6bC...207E10339
0xF64579f9...f722e9405
3.473075557464440673 Eth
Nonce: 236
3.470744557464440673 Eth
Nonce: 237
0.002331

Execution Trace

ERC1155Sale.cancel( token=0xd07dc4262BCDbf85190C01c996b4C06a461d2430, tokenId=494 )
  • ERC1155SaleNonceHolder.getNonce( token=0xd07dc4262BCDbf85190C01c996b4C06a461d2430, tokenId=494, owner=0xF64579f9F76E060e6E3fC88441d5147f722e9405 ) => ( 2 )
  • ERC1155SaleNonceHolder.setNonce( token=0xd07dc4262BCDbf85190C01c996b4C06a461d2430, tokenId=494, owner=0xF64579f9F76E060e6E3fC88441d5147f722e9405, nonce=3 )
    File 1 of 2: ERC1155Sale
    pragma solidity ^0.5.0;
    pragma experimental ABIEncoderV2;
    
    /**
     * @dev Interface of the ERC165 standard, as defined in the
     * https://eips.ethereum.org/EIPS/eip-165[EIP].
     *
     * Implementers can declare support of contract interfaces, which can then be
     * queried by others ({ERC165Checker}).
     *
     * For an implementation, see {ERC165}.
     */
    interface IERC165 {
        /**
         * @dev Returns true if this contract implements the interface defined by
         * `interfaceId`. See the corresponding
         * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
         * to learn more about how these ids are created.
         *
         * This function call must use less than 30 000 gas.
         */
        function supportsInterface(bytes4 interfaceId) external view returns (bool);
    }
    
    /**
        @title ERC-1155 Multi Token Standard
        @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md
        Note: The ERC-165 identifier for this interface is 0xd9b67a26.
     */
    contract IERC1155 is IERC165 {
        /**
            @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
            The `_operator` argument MUST be msg.sender.
            The `_from` argument MUST be the address of the holder whose balance is decreased.
            The `_to` argument MUST be the address of the recipient whose balance is increased.
            The `_id` argument MUST be the token type being transferred.
            The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by.
            When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
            When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
        */
        event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value);
    
        /**
            @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard).
            The `_operator` argument MUST be msg.sender.
            The `_from` argument MUST be the address of the holder whose balance is decreased.
            The `_to` argument MUST be the address of the recipient whose balance is increased.
            The `_ids` argument MUST be the list of tokens being transferred.
            The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by.
            When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address).
            When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address).
        */
        event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values);
    
        /**
            @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absense of an event assumes disabled).
        */
        event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
    
        /**
            @dev MUST emit when the URI is updated for a token ID.
            URIs are defined in RFC 3986.
            The URI MUST point a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema".
        */
        event URI(string _value, uint256 indexed _id);
    
        /**
            @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call).
            @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
            MUST revert if `_to` is the zero address.
            MUST revert if balance of holder for token `_id` is lower than the `_value` sent.
            MUST revert on any other error.
            MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard).
            After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
            @param _from    Source address
            @param _to      Target address
            @param _id      ID of the token type
            @param _value   Transfer amount
            @param _data    Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to`
        */
        function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external;
    
        /**
            @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call).
            @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard).
            MUST revert if `_to` is the zero address.
            MUST revert if length of `_ids` is not the same as length of `_values`.
            MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient.
            MUST revert on any other error.
            MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard).
            Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc).
            After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard).
            @param _from    Source address
            @param _to      Target address
            @param _ids     IDs of each token type (order and length must match _values array)
            @param _values  Transfer amounts per token type (order and length must match _ids array)
            @param _data    Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to`
        */
        function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external;
    
        /**
            @notice Get the balance of an account's Tokens.
            @param _owner  The address of the token holder
            @param _id     ID of the Token
            @return        The _owner's balance of the Token type requested
         */
        function balanceOf(address _owner, uint256 _id) external view returns (uint256);
    
        /**
            @notice Get the balance of multiple account/token pairs
            @param _owners The addresses of the token holders
            @param _ids    ID of the Tokens
            @return        The _owner's balance of the Token types requested (i.e. balance for each (owner, id) pair)
         */
        function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);
    
        /**
            @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens.
            @dev MUST emit the ApprovalForAll event on success.
            @param _operator  Address to add to the set of authorized operators
            @param _approved  True if the operator is approved, false to revoke approval
        */
        function setApprovalForAll(address _operator, bool _approved) external;
    
        /**
            @notice Queries the approval status of an operator for a given owner.
            @param _owner     The owner of the Tokens
            @param _operator  Address of authorized operator
            @return           True if the operator is approved, false if not
        */
        function isApprovedForAll(address _owner, address _operator) external view returns (bool);
    }
    
    library UintLibrary {
        function toString(uint256 _i) internal pure returns (string memory) {
            if (_i == 0) {
                return "0";
            }
            uint j = _i;
            uint len;
            while (j != 0) {
                len++;
                j /= 10;
            }
            bytes memory bstr = new bytes(len);
            uint k = len - 1;
            while (_i != 0) {
                bstr[k--] = byte(uint8(48 + _i % 10));
                _i /= 10;
            }
            return string(bstr);
        }
    }
    
    library StringLibrary {
        using UintLibrary for uint256;
    
        function append(string memory _a, string memory _b) internal pure returns (string memory) {
            bytes memory _ba = bytes(_a);
            bytes memory _bb = bytes(_b);
            bytes memory bab = new bytes(_ba.length + _bb.length);
            uint k = 0;
            for (uint i = 0; i < _ba.length; i++) bab[k++] = _ba[i];
            for (uint i = 0; i < _bb.length; i++) bab[k++] = _bb[i];
            return string(bab);
        }
    
        function append(string memory _a, string memory _b, string memory _c) internal pure returns (string memory) {
            bytes memory _ba = bytes(_a);
            bytes memory _bb = bytes(_b);
            bytes memory _bc = bytes(_c);
            bytes memory bbb = new bytes(_ba.length + _bb.length + _bc.length);
            uint k = 0;
            for (uint i = 0; i < _ba.length; i++) bbb[k++] = _ba[i];
            for (uint i = 0; i < _bb.length; i++) bbb[k++] = _bb[i];
            for (uint i = 0; i < _bc.length; i++) bbb[k++] = _bc[i];
            return string(bbb);
        }
    
        function recover(string memory message, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
            bytes memory msgBytes = bytes(message);
            bytes memory fullMessage = concat(
                bytes("\x19Ethereum Signed Message:\n"),
                bytes(msgBytes.length.toString()),
                msgBytes,
                new bytes(0), new bytes(0), new bytes(0), new bytes(0)
            );
            return ecrecover(keccak256(fullMessage), v, r, s);
        }
    
        function concat(bytes memory _ba, bytes memory _bb, bytes memory _bc, bytes memory _bd, bytes memory _be, bytes memory _bf, bytes memory _bg) internal pure returns (bytes memory) {
            bytes memory resultBytes = new bytes(_ba.length + _bb.length + _bc.length + _bd.length + _be.length + _bf.length + _bg.length);
            uint k = 0;
            for (uint i = 0; i < _ba.length; i++) resultBytes[k++] = _ba[i];
            for (uint i = 0; i < _bb.length; i++) resultBytes[k++] = _bb[i];
            for (uint i = 0; i < _bc.length; i++) resultBytes[k++] = _bc[i];
            for (uint i = 0; i < _bd.length; i++) resultBytes[k++] = _bd[i];
            for (uint i = 0; i < _be.length; i++) resultBytes[k++] = _be[i];
            for (uint i = 0; i < _bf.length; i++) resultBytes[k++] = _bf[i];
            for (uint i = 0; i < _bg.length; i++) resultBytes[k++] = _bg[i];
            return resultBytes;
        }
    }
    
    library AddressLibrary {
        function toString(address _addr) internal pure returns (string memory) {
            bytes32 value = bytes32(uint256(_addr));
            bytes memory alphabet = "0123456789abcdef";
            bytes memory str = new bytes(42);
            str[0] = '0';
            str[1] = 'x';
            for (uint256 i = 0; i < 20; i++) {
                str[2+i*2] = alphabet[uint8(value[i + 12] >> 4)];
                str[3+i*2] = alphabet[uint8(value[i + 12] & 0x0f)];
            }
            return string(str);
        }
    }
    
    /*
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with GSN meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    contract Context {
        // Empty internal constructor, to prevent people from mistakenly deploying
        // an instance of this contract, which should be used via inheritance.
        constructor () internal { }
        // solhint-disable-previous-line no-empty-blocks
    
        function _msgSender() internal view returns (address payable) {
            return msg.sender;
        }
    
        function _msgData() internal view returns (bytes memory) {
            this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
            return msg.data;
        }
    }
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor () internal {
            address msgSender = _msgSender();
            _owner = msgSender;
            emit OwnershipTransferred(address(0), msgSender);
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(isOwner(), "Ownable: caller is not the owner");
            _;
        }
    
        /**
         * @dev Returns true if the caller is the current owner.
         */
        function isOwner() public view returns (bool) {
            return _msgSender() == _owner;
        }
    
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions anymore. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby removing any functionality that is only available to the owner.
         */
        function renounceOwnership() public onlyOwner {
            emit OwnershipTransferred(_owner, address(0));
            _owner = address(0);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Can only be called by the current owner.
         */
        function transferOwnership(address newOwner) public onlyOwner {
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         */
        function _transferOwnership(address newOwner) internal {
            require(newOwner != address(0), "Ownable: new owner is the zero address");
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    /**
     * @dev Wrappers over Solidity's arithmetic operations with added overflow
     * checks.
     *
     * Arithmetic operations in Solidity wrap on overflow. This can easily result
     * in bugs, because programmers usually assume that an overflow raises an
     * error, which is the standard behavior in high level programming languages.
     * `SafeMath` restores this intuition by reverting the transaction when an
     * operation overflows.
     *
     * Using this library instead of the unchecked operations eliminates an entire
     * class of bugs, so it's recommended to use it always.
     */
    library SafeMath {
        /**
         * @dev Returns the addition of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `+` operator.
         *
         * Requirements:
         * - Addition cannot overflow.
         */
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            return sub(a, b, "SafeMath: subtraction overflow");
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         * - Subtraction cannot overflow.
         *
         * _Available since v2.4.0._
         */
        function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b <= a, errorMessage);
            uint256 c = a - b;
    
            return c;
        }
    
        /**
         * @dev Returns the multiplication of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `*` operator.
         *
         * Requirements:
         * - Multiplication cannot overflow.
         */
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) {
                return 0;
            }
    
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            return div(a, b, "SafeMath: division by zero");
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         *
         * _Available since v2.4.0._
         */
        function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 0, errorMessage);
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    
            return c;
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            return mod(a, b, "SafeMath: modulo by zero");
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts with custom message when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         *
         * _Available since v2.4.0._
         */
        function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b != 0, errorMessage);
            return a % b;
        }
    }
    
    /**
     * @dev Implementation of the {IERC165} interface.
     *
     * Contracts may inherit from this and call {_registerInterface} to declare
     * their support of an interface.
     */
    contract ERC165 is IERC165 {
        /*
         * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
         */
        bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
    
        /**
         * @dev Mapping of interface ids to whether or not it's supported.
         */
        mapping(bytes4 => bool) private _supportedInterfaces;
    
        constructor () internal {
            // Derived contracts need only register support for their own interfaces,
            // we register support for ERC165 itself here
            _registerInterface(_INTERFACE_ID_ERC165);
        }
    
        /**
         * @dev See {IERC165-supportsInterface}.
         *
         * Time complexity O(1), guaranteed to always use less than 30 000 gas.
         */
        function supportsInterface(bytes4 interfaceId) external view returns (bool) {
            return _supportedInterfaces[interfaceId];
        }
    
        /**
         * @dev Registers the contract as an implementer of the interface defined by
         * `interfaceId`. Support of the actual ERC165 interface is automatic and
         * registering its interface id is not required.
         *
         * See {IERC165-supportsInterface}.
         *
         * Requirements:
         *
         * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
         */
        function _registerInterface(bytes4 interfaceId) internal {
            require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
            _supportedInterfaces[interfaceId] = true;
        }
    }
    
    contract HasSecondarySaleFees is ERC165 {
    
        event SecondarySaleFees(uint256 tokenId, address[] recipients, uint[] bps);
    
        /*
         * bytes4(keccak256('getFeeBps(uint256)')) == 0x0ebd4c7f
         * bytes4(keccak256('getFeeRecipients(uint256)')) == 0xb9c4d9fb
         *
         * => 0x0ebd4c7f ^ 0xb9c4d9fb == 0xb7799584
         */
        bytes4 private constant _INTERFACE_ID_FEES = 0xb7799584;
    
        constructor() public {
            _registerInterface(_INTERFACE_ID_FEES);
        }
    
        function getFeeRecipients(uint256 id) public view returns (address payable[] memory);
        function getFeeBps(uint256 id) public view returns (uint[] memory);
    }
    
    contract AbstractSale is Ownable {
        using UintLibrary for uint256;
        using AddressLibrary for address;
        using StringLibrary for string;
        using SafeMath for uint256;
    
        bytes4 private constant _INTERFACE_ID_FEES = 0xb7799584;
    
        uint public buyerFee = 0;
        address payable public beneficiary;
    
        /* An ECDSA signature. */
        struct Sig {
            /* v parameter */
            uint8 v;
            /* r parameter */
            bytes32 r;
            /* s parameter */
            bytes32 s;
        }
    
        constructor(address payable _beneficiary) public {
            beneficiary = _beneficiary;
        }
    
        function setBuyerFee(uint256 _buyerFee) public onlyOwner {
            buyerFee = _buyerFee;
        }
    
        function setBeneficiary(address payable _beneficiary) public onlyOwner {
            beneficiary = _beneficiary;
        }
    
        function prepareMessage(address token, uint256 tokenId, uint256 price, uint256 fee, uint256 nonce) internal pure returns (string memory) {
            string memory result = string(strConcat(
                    bytes(token.toString()),
                    bytes(". tokenId: "),
                    bytes(tokenId.toString()),
                    bytes(". price: "),
                    bytes(price.toString()),
                    bytes(". nonce: "),
                    bytes(nonce.toString())
                ));
            if (fee != 0) {
                return result.append(". fee: ", fee.toString());
            } else {
                return result;
            }
        }
    
        function strConcat(bytes memory _ba, bytes memory _bb, bytes memory _bc, bytes memory _bd, bytes memory _be, bytes memory _bf, bytes memory _bg) internal pure returns (bytes memory) {
            bytes memory resultBytes = new bytes(_ba.length + _bb.length + _bc.length + _bd.length + _be.length + _bf.length + _bg.length);
            uint k = 0;
            for (uint i = 0; i < _ba.length; i++) resultBytes[k++] = _ba[i];
            for (uint i = 0; i < _bb.length; i++) resultBytes[k++] = _bb[i];
            for (uint i = 0; i < _bc.length; i++) resultBytes[k++] = _bc[i];
            for (uint i = 0; i < _bd.length; i++) resultBytes[k++] = _bd[i];
            for (uint i = 0; i < _be.length; i++) resultBytes[k++] = _be[i];
            for (uint i = 0; i < _bf.length; i++) resultBytes[k++] = _bf[i];
            for (uint i = 0; i < _bg.length; i++) resultBytes[k++] = _bg[i];
            return resultBytes;
        }
    
        function transferEther(IERC165 token, uint256 tokenId, address payable owner, uint256 total, uint256 sellerFee) internal {
            uint value = transferFeeToBeneficiary(total, sellerFee);
            if (token.supportsInterface(_INTERFACE_ID_FEES)) {
                HasSecondarySaleFees withFees = HasSecondarySaleFees(address(token));
                address payable[] memory recipients = withFees.getFeeRecipients(tokenId);
                uint[] memory fees = withFees.getFeeBps(tokenId);
                require(fees.length == recipients.length);
                for (uint256 i = 0; i < fees.length; i++) {
                    (uint newValue, uint current) = subFee(value, total.mul(fees[i]).div(10000));
                    value = newValue;
                    recipients[i].transfer(current);
                }
            }
            owner.transfer(value);
        }
    
        function transferFeeToBeneficiary(uint total, uint sellerFee) internal returns (uint) {
            (uint value, uint sellerFeeValue) = subFee(total, total.mul(sellerFee).div(10000));
            uint buyerFeeValue = total.mul(buyerFee).div(10000);
            uint beneficiaryFee = buyerFeeValue.add(sellerFeeValue);
            if (beneficiaryFee > 0) {
                beneficiary.transfer(beneficiaryFee);
            }
            return value;
        }
    
        function subFee(uint value, uint fee) internal pure returns (uint newValue, uint realFee) {
            if (value > fee) {
                newValue = value - fee;
                realFee = fee;
            } else {
                newValue = 0;
                realFee = value;
            }
        }
    }
    
    /**
     * @dev Required interface of an ERC721 compliant contract.
     */
    contract IERC721 is IERC165 {
        event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
        event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
        event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
    
        /**
         * @dev Returns the number of NFTs in `owner`'s account.
         */
        function balanceOf(address owner) public view returns (uint256 balance);
    
        /**
         * @dev Returns the owner of the NFT specified by `tokenId`.
         */
        function ownerOf(uint256 tokenId) public view returns (address owner);
    
        /**
         * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
         * another (`to`).
         *
         *
         *
         * Requirements:
         * - `from`, `to` cannot be zero.
         * - `tokenId` must be owned by `from`.
         * - If the caller is not `from`, it must be have been allowed to move this
         * NFT by either {approve} or {setApprovalForAll}.
         */
        function safeTransferFrom(address from, address to, uint256 tokenId) public;
        /**
         * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
         * another (`to`).
         *
         * Requirements:
         * - If the caller is not `from`, it must be approved to move this NFT by
         * either {approve} or {setApprovalForAll}.
         */
        function transferFrom(address from, address to, uint256 tokenId) public;
        function approve(address to, uint256 tokenId) public;
        function getApproved(uint256 tokenId) public view returns (address operator);
    
        function setApprovalForAll(address operator, bool _approved) public;
        function isApprovedForAll(address owner, address operator) public view returns (bool);
    
    
        function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
    }
    
    /**
     * @title Roles
     * @dev Library for managing addresses assigned to a Role.
     */
    library Roles {
        struct Role {
            mapping (address => bool) bearer;
        }
    
        /**
         * @dev Give an account access to this role.
         */
        function add(Role storage role, address account) internal {
            require(!has(role, account), "Roles: account already has role");
            role.bearer[account] = true;
        }
    
        /**
         * @dev Remove an account's access to this role.
         */
        function remove(Role storage role, address account) internal {
            require(has(role, account), "Roles: account does not have role");
            role.bearer[account] = false;
        }
    
        /**
         * @dev Check if an account has this role.
         * @return bool
         */
        function has(Role storage role, address account) internal view returns (bool) {
            require(account != address(0), "Roles: account is the zero address");
            return role.bearer[account];
        }
    }
    
    contract OperatorRole is Context {
        using Roles for Roles.Role;
    
        event OperatorAdded(address indexed account);
        event OperatorRemoved(address indexed account);
    
        Roles.Role private _operators;
    
        constructor () internal {
    
        }
    
        modifier onlyOperator() {
            require(isOperator(_msgSender()), "OperatorRole: caller does not have the Operator role");
            _;
        }
    
        function isOperator(address account) public view returns (bool) {
            return _operators.has(account);
        }
    
        function _addOperator(address account) internal {
            _operators.add(account);
            emit OperatorAdded(account);
        }
    
        function _removeOperator(address account) internal {
            _operators.remove(account);
            emit OperatorRemoved(account);
        }
    }
    
    contract OwnableOperatorRole is Ownable, OperatorRole {
        function addOperator(address account) public onlyOwner {
            _addOperator(account);
        }
    
        function removeOperator(address account) public onlyOwner {
            _removeOperator(account);
        }
    }
    
    contract TransferProxy is OwnableOperatorRole {
    
        function erc721safeTransferFrom(IERC721 token, address from, address to, uint256 tokenId) external onlyOperator {
            token.safeTransferFrom(from, to, tokenId);
        }
    
        function erc1155safeTransferFrom(IERC1155 token, address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external onlyOperator {
            token.safeTransferFrom(_from, _to, _id, _value, _data);
        }
    }
    
    contract ERC1155SaleNonceHolder is OwnableOperatorRole {
        // keccak256(token, owner, tokenId) => nonce
        mapping(bytes32 => uint256) public nonces;
    
        // keccak256(token, owner, tokenId, nonce) => completed amount
        mapping(bytes32 => uint256) public completed;
    
        function getNonce(address token, uint256 tokenId, address owner) view public returns (uint256) {
            return nonces[getNonceKey(token, tokenId, owner)];
        }
    
        function setNonce(address token, uint256 tokenId, address owner, uint256 nonce) public onlyOperator {
            nonces[getNonceKey(token, tokenId, owner)] = nonce;
        }
    
        function getNonceKey(address token, uint256 tokenId, address owner) pure public returns (bytes32) {
            return keccak256(abi.encodePacked(token, tokenId, owner));
        }
    
        function getCompleted(address token, uint256 tokenId, address owner, uint256 nonce) view public returns (uint256) {
            return completed[getCompletedKey(token, tokenId, owner, nonce)];
        }
    
        function setCompleted(address token, uint256 tokenId, address owner, uint256 nonce, uint256 _completed) public onlyOperator {
            completed[getCompletedKey(token, tokenId, owner, nonce)] = _completed;
        }
    
        function getCompletedKey(address token, uint256 tokenId, address owner, uint256 nonce) pure public returns (bytes32) {
            return keccak256(abi.encodePacked(token, tokenId, owner, nonce));
        }
    }
    
    
    
    
    
    
    
    
    
    
    
    contract ERC1155Sale is Ownable, AbstractSale {
        using StringLibrary for string;
    
        event CloseOrder(address indexed token, uint256 indexed tokenId, address owner, uint256 nonce);
        event Buy(address indexed token, uint256 indexed tokenId, address owner, uint256 price, address buyer, uint256 value);
    
        bytes constant EMPTY = "";
    
        TransferProxy public transferProxy;
        ERC1155SaleNonceHolder public nonceHolder;
    
        constructor(TransferProxy _transferProxy, ERC1155SaleNonceHolder _nonceHolder, address payable beneficiary) AbstractSale(beneficiary) public {
            transferProxy = _transferProxy;
            nonceHolder = _nonceHolder;
        }
    
        function buy(IERC1155 token, uint256 tokenId, address payable owner, uint256 selling, uint256 buying, uint256 price, uint256 sellerFee, Sig memory signature) public payable {
            uint256 nonce = verifySignature(address(token), tokenId, owner, selling, price, sellerFee, signature);
            uint256 total = price.mul(buying);
            uint256 buyerFeeValue = total.mul(buyerFee).div(10000);
            require(total + buyerFeeValue == msg.value, "msg.value is incorrect");
            bool closed = verifyOpenAndModifyState(address(token), tokenId, owner, nonce, selling, buying);
    
            transferProxy.erc1155safeTransferFrom(token, owner, msg.sender, tokenId, buying, EMPTY);
    
            transferEther(token, tokenId, owner, total, sellerFee);
            emit Buy(address(token), tokenId, owner, price, msg.sender, buying);
            if (closed) {
                emit CloseOrder(address(token), tokenId, owner, nonce + 1);
            }
        }
    
        function cancel(address token, uint256 tokenId) public payable {
            uint nonce = nonceHolder.getNonce(token, tokenId, msg.sender);
            nonceHolder.setNonce(token, tokenId, msg.sender, nonce + 1);
    
            emit CloseOrder(token, tokenId, msg.sender, nonce + 1);
        }
    
        function verifySignature(address token, uint256 tokenId, address payable owner, uint256 selling, uint256 price, uint256 sellerFee, Sig memory signature) view internal returns (uint256 nonce) {
            nonce = nonceHolder.getNonce(token, tokenId, owner);
            require(prepareMessage(token, tokenId, price, selling, sellerFee, nonce).recover(signature.v, signature.r, signature.s) == owner, "incorrect signature");
        }
    
        function verifyOpenAndModifyState(address token, uint256 tokenId, address payable owner, uint256 nonce, uint256 selling, uint256 buying) internal returns (bool) {
            uint comp = nonceHolder.getCompleted(token, tokenId, owner, nonce).add(buying);
            require(comp <= selling);
            nonceHolder.setCompleted(token, tokenId, owner, nonce, comp);
    
            if (comp == selling) {
                nonceHolder.setNonce(token, tokenId, owner, nonce + 1);
                return true;
            }
            return false;
        }
    
        function prepareMessage(address token, uint256 tokenId, uint256 price, uint256 value, uint256 fee, uint256 nonce) internal pure returns (string memory) {
            return prepareMessage(token, tokenId, price, fee, nonce).append(". value: ", value.toString());
        }
    }

    File 2 of 2: ERC1155SaleNonceHolder
    pragma solidity ^0.5.0;
    
    /*
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with GSN meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    contract Context {
        // Empty internal constructor, to prevent people from mistakenly deploying
        // an instance of this contract, which should be used via inheritance.
        constructor () internal { }
        // solhint-disable-previous-line no-empty-blocks
    
        function _msgSender() internal view returns (address payable) {
            return msg.sender;
        }
    
        function _msgData() internal view returns (bytes memory) {
            this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
            return msg.data;
        }
    }
    
    /**
     * @title Roles
     * @dev Library for managing addresses assigned to a Role.
     */
    library Roles {
        struct Role {
            mapping (address => bool) bearer;
        }
    
        /**
         * @dev Give an account access to this role.
         */
        function add(Role storage role, address account) internal {
            require(!has(role, account), "Roles: account already has role");
            role.bearer[account] = true;
        }
    
        /**
         * @dev Remove an account's access to this role.
         */
        function remove(Role storage role, address account) internal {
            require(has(role, account), "Roles: account does not have role");
            role.bearer[account] = false;
        }
    
        /**
         * @dev Check if an account has this role.
         * @return bool
         */
        function has(Role storage role, address account) internal view returns (bool) {
            require(account != address(0), "Roles: account is the zero address");
            return role.bearer[account];
        }
    }
    
    contract OperatorRole is Context {
        using Roles for Roles.Role;
    
        event OperatorAdded(address indexed account);
        event OperatorRemoved(address indexed account);
    
        Roles.Role private _operators;
    
        constructor () internal {
    
        }
    
        modifier onlyOperator() {
            require(isOperator(_msgSender()), "OperatorRole: caller does not have the Operator role");
            _;
        }
    
        function isOperator(address account) public view returns (bool) {
            return _operators.has(account);
        }
    
        function _addOperator(address account) internal {
            _operators.add(account);
            emit OperatorAdded(account);
        }
    
        function _removeOperator(address account) internal {
            _operators.remove(account);
            emit OperatorRemoved(account);
        }
    }
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor () internal {
            address msgSender = _msgSender();
            _owner = msgSender;
            emit OwnershipTransferred(address(0), msgSender);
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            require(isOwner(), "Ownable: caller is not the owner");
            _;
        }
    
        /**
         * @dev Returns true if the caller is the current owner.
         */
        function isOwner() public view returns (bool) {
            return _msgSender() == _owner;
        }
    
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions anymore. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby removing any functionality that is only available to the owner.
         */
        function renounceOwnership() public onlyOwner {
            emit OwnershipTransferred(_owner, address(0));
            _owner = address(0);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Can only be called by the current owner.
         */
        function transferOwnership(address newOwner) public onlyOwner {
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         */
        function _transferOwnership(address newOwner) internal {
            require(newOwner != address(0), "Ownable: new owner is the zero address");
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    contract OwnableOperatorRole is Ownable, OperatorRole {
        function addOperator(address account) public onlyOwner {
            _addOperator(account);
        }
    
        function removeOperator(address account) public onlyOwner {
            _removeOperator(account);
        }
    }
    
    contract ERC1155SaleNonceHolder is OwnableOperatorRole {
        // keccak256(token, owner, tokenId) => nonce
        mapping(bytes32 => uint256) public nonces;
    
        // keccak256(token, owner, tokenId, nonce) => completed amount
        mapping(bytes32 => uint256) public completed;
    
        function getNonce(address token, uint256 tokenId, address owner) view public returns (uint256) {
            return nonces[getNonceKey(token, tokenId, owner)];
        }
    
        function setNonce(address token, uint256 tokenId, address owner, uint256 nonce) public onlyOperator {
            nonces[getNonceKey(token, tokenId, owner)] = nonce;
        }
    
        function getNonceKey(address token, uint256 tokenId, address owner) pure public returns (bytes32) {
            return keccak256(abi.encodePacked(token, tokenId, owner));
        }
    
        function getCompleted(address token, uint256 tokenId, address owner, uint256 nonce) view public returns (uint256) {
            return completed[getCompletedKey(token, tokenId, owner, nonce)];
        }
    
        function setCompleted(address token, uint256 tokenId, address owner, uint256 nonce, uint256 _completed) public onlyOperator {
            completed[getCompletedKey(token, tokenId, owner, nonce)] = _completed;
        }
    
        function getCompletedKey(address token, uint256 tokenId, address owner, uint256 nonce) pure public returns (bytes32) {
            return keccak256(abi.encodePacked(token, tokenId, owner, nonce));
        }
    }