ETH Price: $1,812.61 (+10.29%)
Gas: 0.14 GWei

Contract

0x2D4FB6F3F9dc2ec67676bE55D5301b2BE2193032

Overview

ETH Balance

Linea Mainnet LogoLinea Mainnet LogoLinea Mainnet Logo0 ETH

ETH Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

> 10 Internal Transactions found.

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
41401462024-04-30 7:58:42358 days ago1714463922
0x2D4FB6F3...BE2193032
0.0001 ETH
41401322024-04-30 7:58:00358 days ago1714463880
0x2D4FB6F3...BE2193032
0.00008 ETH
41401312024-04-30 7:57:57358 days ago1714463877
0x2D4FB6F3...BE2193032
0.0001 ETH
41401282024-04-30 7:57:48358 days ago1714463868
0x2D4FB6F3...BE2193032
0.0001 ETH
41401162024-04-30 7:57:12358 days ago1714463832
0x2D4FB6F3...BE2193032
0.0001 ETH
41400972024-04-30 7:56:15358 days ago1714463775
0x2D4FB6F3...BE2193032
0.0001 ETH
41400862024-04-30 7:55:42358 days ago1714463742
0x2D4FB6F3...BE2193032
0.0001 ETH
41400802024-04-30 7:55:24358 days ago1714463724
0x2D4FB6F3...BE2193032
0.0001 ETH
41400752024-04-30 7:55:09358 days ago1714463709
0x2D4FB6F3...BE2193032
0.000094 ETH
41400722024-04-30 7:55:00358 days ago1714463700
0x2D4FB6F3...BE2193032
0.00008 ETH
41400682024-04-30 7:54:48358 days ago1714463688
0x2D4FB6F3...BE2193032
0.0001999 ETH
41400572024-04-30 7:54:15358 days ago1714463655
0x2D4FB6F3...BE2193032
0.0001 ETH
41400422024-04-30 7:53:30358 days ago1714463610
0x2D4FB6F3...BE2193032
0.0001 ETH
41400232024-04-30 7:52:33358 days ago1714463553
0x2D4FB6F3...BE2193032
0.0001 ETH
41400022024-04-30 7:51:30358 days ago1714463490
0x2D4FB6F3...BE2193032
0.0001 ETH
41399842024-04-30 7:50:36358 days ago1714463436
0x2D4FB6F3...BE2193032
0.00008 ETH
41399832024-04-30 7:50:33358 days ago1714463433
0x2D4FB6F3...BE2193032
0.0001 ETH
41399672024-04-30 7:49:45358 days ago1714463385
0x2D4FB6F3...BE2193032
0.0001 ETH
41399662024-04-30 7:49:42358 days ago1714463382
0x2D4FB6F3...BE2193032
0.0001 ETH
41399482024-04-30 7:48:48358 days ago1714463328
0x2D4FB6F3...BE2193032
0.0001 ETH
41399302024-04-30 7:47:54358 days ago1714463274
0x2D4FB6F3...BE2193032
0.0001 ETH
41398982024-04-30 7:46:18358 days ago1714463178
0x2D4FB6F3...BE2193032
0.0003499 ETH
41398972024-04-30 7:46:15358 days ago1714463175
0x2D4FB6F3...BE2193032
0.0001 ETH
41398812024-04-30 7:45:27358 days ago1714463127
0x2D4FB6F3...BE2193032
0.0001 ETH
41398802024-04-30 7:45:24358 days ago1714463124
0x2D4FB6F3...BE2193032
0.0000355 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BatchSignedERC721OrdersFeature

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 5 : BatchSignedERC721OrdersFeature.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2022 Element.Market Intl.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

*/

pragma solidity ^0.8.17;

import "../../storage/LibCommonNftOrdersStorage.sol";
import "../../storage/LibERC721OrdersStorage.sol";
import "../interfaces/IBatchSignedERC721OrdersFeature.sol";


contract BatchSignedERC721OrdersFeature is IBatchSignedERC721OrdersFeature {

    uint256 internal constant MASK_192 = (1 << 192) - 1;
    uint256 internal constant MASK_160 = (1 << 160) - 1;
    uint256 internal constant MASK_64 = (1 << 64) - 1;
    uint256 internal constant MASK_40 = (1 << 40) - 1;
    uint256 internal constant MASK_32 = (1 << 32) - 1;
    uint256 internal constant MASK_16 = (1 << 16) - 1;

    uint256 internal constant MASK_INDEX_LIST_PART1 = ((1 << 96) - 1) << 160;
    uint256 internal constant MASK_INDEX_LIST_PART2 = ((1 << 32) - 1) << 128;

    uint256 internal constant NONCE_RANGE_LIMIT = 1 << 248;
    uint256 internal constant MAX_ERC20_AMOUNT = (1 << 224) - 1;

    // Storage ID.
    uint256 constant STORAGE_ID_COMMON_NFT_ORDERS = 4 << 128;
    uint256 constant STORAGE_ID_ERC721_ORDERS = 5 << 128;

    // Topic for ERC721SellOrderFilled.
    bytes32 internal constant _TOPIC_SELL_ORDER_FILLED = 0x9c248aa1a265aa616f707b979d57f4529bb63a4fc34dc7fc61fdddc18410f74e;

    // keccak256("")
    bytes32 internal constant _EMPTY_ARRAY_KECCAK256 = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

    // keccak256(abi.encodePacked(
    //    "BatchSignedERC721Orders(address maker,uint256 listingTime,uint256 expiryTime,uint256 startNonce,address erc20Token,address platformFeeRecipient,BasicCollection[] basicCollections,Collection[] collections,uint256 hashNonce)",
    //    "BasicCollection(address nftAddress,bytes32 fee,bytes32[] items)",
    //    "Collection(address nftAddress,bytes32 fee,OrderItem[] items)",
    //    "OrderItem(uint256 erc20TokenAmount,uint256 nftId)"
    // ))
    bytes32 internal constant _BATCH_SIGNED_ERC721_ORDERS_TYPE_HASH = 0x2d8cbbbc696e7292c3b5beb38e1363d34ff11beb8c3456c14cb938854597b9ed;
    // keccak256("BasicCollection(address nftAddress,bytes32 fee,bytes32[] items)")
    bytes32 internal constant _BASIC_COLLECTION_TYPE_HASH = 0x12ad29288fd70022f26997a9958d9eceb6e840ceaa79b72ea5945ba87e4d33b0;
    // keccak256(abi.encodePacked(
    //    "Collection(address nftAddress,bytes32 fee,OrderItem[] items)",
    //    "OrderItem(uint256 erc20TokenAmount,uint256 nftId)"
    // ))
    bytes32 internal constant _COLLECTION_TYPE_HASH = 0xb9f488d48cec782be9ecdb74330c9c6a33c236a8022d8a91a4e4df4e81b51620;
    // keccak256("OrderItem(uint256 erc20TokenAmount,uint256 nftId)")
    bytes32 internal constant _ORDER_ITEM_TYPE_HASH = 0x5f93394997caa49a9382d44a75e3ce6a460f32b39870464866ac994f8be97afe;

    // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
    bytes32 internal constant DOMAIN = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
    // keccak256("ElementEx")
    bytes32 internal constant NAME = 0x27b14c20196091d9cd90ca9c473d3ad1523b00ddf487a9b7452a8a119a16b98c;
    // keccak256("1.0.0")
    bytes32 internal constant VERSION = 0x06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c;

    /// @dev The implementation address of this feature.
    address internal immutable _IMPL;
    /// @dev The WETH token contract.
    address internal immutable _WETH;

    constructor(address weth) {
        require(address(weth) != address(0), "INVALID_WETH_ADDRESS");
        _WETH = weth;
        _IMPL = address(this);
    }

    function fillBatchSignedERC721Order(BatchSignedERC721OrderParameter calldata /* parameter */, bytes calldata collections) external override payable {
        uint256 ethBalanceBefore = address(this).balance - msg.value;
        uint256 offsetCollectionsBytes;
        assembly {
            offsetCollectionsBytes := collections.offset
        }

        // Validate order.
        bytes32 orderHash = _validateOrder(offsetCollectionsBytes);

        assembly {
            // memory[0x0 - 0x20] orderHash
            mstore(0, orderHash)

            /////////////////////////// memory[0x380 - 0x420] for delegateCall  ///////////
            // memory[0x380 - 0x3a0] erc20TokenFromDelegateCall
            // memory[0x3a0 - 0x3c0] platformFeeRecipientFromDelegateCall
            // memory[0x3c0 - 0x3e0] royaltyFeeRecipientFromDelegateCall
            mstore(0x380, 0)
            mstore(0x3a0, 0)
            mstore(0x3c0, 0)
        }

        // Fill order.
        _fillBatchSignedERC721Order(offsetCollectionsBytes);

        // Refund ETH.
        assembly {
            if eq(selfbalance(), ethBalanceBefore) {
                return(0, 0)
            }
            if gt(selfbalance(), ethBalanceBefore) {
                if iszero(call(gas(), caller(), sub(selfbalance(), ethBalanceBefore), 0, 0, 0, 0)) {
                    _revertRefundETHFailed()
                }
                return(0, 0)
            }
            _revertRefundETHFailed()

            function _revertRefundETHFailed() {
                // revert("fillBatchSignedERC721Order: failed to refund ETH.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003166696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x6661696c656420746f20726566756e64204554482e0000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }
        }
    }

    /// @param additional1 [96 bits(withdrawETHAmount) + 160 bits(erc20Token)]
    /// @param additional2 [8 bits(revertIfIncomplete) + 88 bits(unused) + 160 bits(royaltyFeeRecipient)]
    function fillBatchSignedERC721Orders(
        BatchSignedERC721OrderParameters[] calldata parameters,
        uint256 additional1,
        uint256 additional2
    ) external override payable {
        require(parameters.length > 0, "fillBatchSignedERC721Orders: invalid parameters.");

        uint256 ethBalanceBefore = address(this).balance - msg.value;
        uint256 platformFeeRecipient = parameters[0].data3 & MASK_160;
        address impl = _IMPL;
        address weth = _WETH;

        assembly {
            let withdrawETHAmount := shr(160, additional1)
            let erc20Token := and(additional1, MASK_160)
            let royaltyFeeRecipient := and(additional2, MASK_160)
            let platformFeeGlobalAccum
            let royaltyFeeGlobalAccum
            let someSuccess

            // Withdraw ETH if needed.
            if withdrawETHAmount {
                // Step1: transfer WETH from msg.sender to address(this).
                _transferERC20(weth, address(), withdrawETHAmount)

                // Step2: withdraw ETH.
                // selector for `withdraw(uint256)`.
                mstore(0, 0x2e1a7d4d)
                mstore(0x20, withdrawETHAmount)
                if iszero(call(gas(), weth, 0, 0x1c, 0x24, 0, 0)) {
                    _revertWithdrawETHFailed()
                }
            }

            /////////////////////////// memory[0 - 0x40] for delegatecall output  /////////////
            // memory[0 - 0x20] output [platformFeeGlobal]
            // memory[0x20 - 0x40] output [royaltyFeeGlobal]

            /////////////////////////// memory[0x40 - ] for delegatecall input /////////////
            // memory[0x40 - 0x60] selector for `delegateCallFillBatchSignedERC721Order(BatchSignedERC721OrderParameter,address,address,address,bytes)`
            mstore(0x40, 0xdc055ecc)
            // memory[0x60 - 0x100] parameter
            // memory[0x100 - 0x120] erc20Token
            mstore(0x100, erc20Token)
            // memory[0x120 - 0x140] platformFeeRecipient
            mstore(0x120, platformFeeRecipient)
            // memory[0x140 - 0x160] royaltyFeeRecipient
            mstore(0x140, royaltyFeeRecipient)
            // memory[0x160 - 0x180] collections.offset
            mstore(0x160, 0x120)
            // memory[0x180 - 0x1a0] collections.length
            // memory[0x1a0 - ] collections.data

            let ptrEnd := add(parameters.offset, mul(parameters.length, 0x20))
            for { let ptr := parameters.offset } lt(ptr, ptrEnd) { ptr := add(ptr, 0x20) } {
                let ptrData := add(parameters.offset, calldataload(ptr))

                // memory[0x40 - 0x60] selector for `delegateCallFillBatchSignedERC721Order`
                // memory[0x60 - 0x100] parameter
                calldatacopy(0x60, ptrData, 0xa0 /* 5 * 32*/)
                // memory[0x100 - 0x120] erc20Token
                // memory[0x120 - 0x140] platformFeeRecipient
                // memory[0x140 - 0x160] royaltyFeeRecipient
                // memory[0x160 - 0x180] collections.offset
                // memory[0x180 - 0x1a0] collections.length
                let collectionsLength := calldataload(add(ptrData, 0xc0))
                if mod(collectionsLength, 0x20) {
                    _revertInvalidCollectionsBytes()
                }
                mstore(0x180, collectionsLength)

                // memory[0x1a0 - ] collections.data
                calldatacopy(0x1a0, add(ptrData, 0xe0), collectionsLength)

                // 0x144 = 0x4(selector) + 0xa0(parameter) + 0x20(erc20Token) + 0x20(platformFeeRecipient) + 0x20(royaltyFeeRecipient) + 0x20(collections.offset) + 0x20(collections.length)
                switch delegatecall(gas(), impl, 0x5c, add(0x144, collectionsLength), 0, 0x40)
                case 0 {
                    // Check revertIfIncomplete flag if failed.
                    if byte(0, additional2) {
                        returndatacopy(0, 0, returndatasize())
                        revert(0, returndatasize())
                    }
                }
                default {
                    // Success.
                    someSuccess := 1

                    // memory[0 - 0x20] output [platformFeeGlobal]
                    // memory[0x20 - 0x40] output [royaltyFeeGlobal]
                    platformFeeGlobalAccum := add(platformFeeGlobalAccum, mload(0))
                    royaltyFeeGlobalAccum := add(royaltyFeeGlobalAccum, mload(0x20))
                }
            } // end for

            if platformFeeGlobalAccum {
                _transferERC20(erc20Token, platformFeeRecipient, platformFeeGlobalAccum)
            }

            if royaltyFeeGlobalAccum {
                _transferERC20(erc20Token, royaltyFeeRecipient, royaltyFeeGlobalAccum)
            }

            if iszero(someSuccess) {
                _revertNoOrderFilled()
            }

            // Refund ETH.
            if eq(selfbalance(), ethBalanceBefore) {
                return(0, 0)
            }
            if gt(selfbalance(), ethBalanceBefore) {
                if iszero(call(gas(), caller(), sub(selfbalance(), ethBalanceBefore), 0, 0, 0, 0)) {
                    _revertRefundETHFailed()
                }
                return(0, 0)
            }
            _revertRefundETHFailed()

            ///////////////////////////////// functions  /////////////////////////////////
            function _transferERC20(_erc20Token, _to, _amount) {
                switch _erc20Token
                case 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE {
                    if iszero(call(gas(), _to, _amount, 0, 0, 0, 0)) {
                        _revertTransferETHFailed()
                    }
                }

                default {
                    if iszero(extcodesize(_erc20Token)) {
                        _revertInvalidERC20Token()
                    }

                    // selector for `transferFrom(address,address,uint256)`
                    mstore(0, 0x23b872dd)
                    mstore(0x20, caller())
                    mstore(0x40, _to)
                    mstore(0x60, _amount)

                    if iszero(call(gas(), _erc20Token, 0, 0x1c, 0x64, 0, 0x20)) {
                        _revertTransferERC20Failed()
                    }

                    // Check for ERC20 success. ERC20 tokens should return a boolean, but some don't.
                    // We accept 0-length return data as success, or at least 32 bytes that starts with
                    // a 32-byte boolean true.
                    if returndatasize() {
                        if lt(returndatasize(), 0x20) {
                            _revertTransferERC20Failed()
                        }
                        if iszero(eq(mload(0), 1)) {
                            _revertTransferERC20Failed()
                        }
                    }
                }
            }

            function _revertTransferETHFailed() {
                // revert("fillBatchSignedERC721Orders: failed to transfer ETH.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003466696c6c42617463685369676e65644552433732314f72646572733a)
                mstore(0x60, 0x206661696c656420746f207472616e73666572204554482e0000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertTransferERC20Failed() {
                // revert("fillBatchSignedERC721Orders: failed to transfer ERC20.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003666696c6c42617463685369676e65644552433732314f72646572733a)
                mstore(0x60, 0x206661696c656420746f207472616e736665722045524332302e000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertWithdrawETHFailed() {
                // revert("fillBatchSignedERC721Orders: failed to withdraw ETH.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003466696c6c42617463685369676e65644552433732314f72646572733a)
                mstore(0x60, 0x206661696c656420746f207769746864726177204554482e0000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertInvalidCollectionsBytes() {
                // revert("fillBatchSignedERC721Orders: invalid collectionsBytes.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003666696c6c42617463685369676e65644552433732314f72646572733a)
                mstore(0x60, 0x20696e76616c696420636f6c6c656374696f6e7342797465732e000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertNoOrderFilled() {
                // revert("fillBatchSignedERC721Orders: no order filled.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000002d66696c6c42617463685369676e65644552433732314f72646572733a)
                mstore(0x60, 0x206e6f206f726465722066696c6c65642e000000000000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertRefundETHFailed() {
                // revert("fillBatchSignedERC721Orders: failed to refund ETH.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003266696c6c42617463685369676e65644552433732314f72646572733a)
                mstore(0x60, 0x206661696c656420746f20726566756e64204554482e00000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertInvalidERC20Token() {
                // revert("invalid erc20 token")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x00000013696e76616c696420657263323020746f6b656e000000000000000000)
                mstore(0x60, 0)
                revert(0, 0x64)
            }
        }
    }

    // @Note `delegateCallFillBatchSignedERC721Order` is a external function, but must delegatecall from an external exchange,
    //        and should not be registered in the external exchange.
    function delegateCallFillBatchSignedERC721Order(
        BatchSignedERC721OrderParameter calldata /* parameter */,
        address erc20TokenFromDelegateCall,
        address platformFeeRecipientFromDelegateCall,
        address royaltyFeeRecipientFromDelegateCall,
        bytes calldata collections
    ) external payable {
        address impl = _IMPL;
        uint256 offsetCollectionsBytes;
        assembly {
            if eq(impl, address()) {
                // revert("delegateCallFillBatchSignedERC721Order: must delegateCall from an external exchange.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000005464656c656761746543616c6c46696c6c42617463685369676e656445)
                mstore(0x60, 0x52433732314f726465723a206d7573742064656c656761746543616c6c206672)
                mstore(0x80, 0x6f6d20616e2065787465726e616c2065786368616e67652e0000000000000000)
                mstore(0xa0, 0)
                revert(0, 0xa4)
            }

            offsetCollectionsBytes := collections.offset
        }

        // Validate order.
        bytes32 orderHash = _validateOrder(offsetCollectionsBytes);

        assembly {
            // memory[0x0 - 0x20] orderHash
            mstore(0, orderHash)

            /////////////////////////// memory[0x380 - 0x420] for delegateCall  ///////////
            // memory[0x380 - 0x3a0] erc20TokenFromDelegateCall
            // memory[0x3a0 - 0x3c0] platformFeeRecipientFromDelegateCall
            // memory[0x3c0 - 0x3e0] royaltyFeeRecipientFromDelegateCall
            mstore(0x380, erc20TokenFromDelegateCall)
            mstore(0x3a0, platformFeeRecipientFromDelegateCall)
            mstore(0x3c0, royaltyFeeRecipientFromDelegateCall)
        }

        // Fill order.
        _fillBatchSignedERC721Order(offsetCollectionsBytes);

        assembly {
            // Return platformFeeGlobal and royaltyFeeGlobal.
            // memory[0x3e0 - 0x400] platformFeeGlobal
            // memory[0x400 - 0x420] royaltyFeeGlobal
            return(0x3e0, 0x40)
        }
    }

    /// data1 [[8 bits(signatureType) + 8 bits(reserved) + 40 bits(startNonce) + 8 bits(v) + 32 bits(listingTime) + 160 bits(maker)]
    /// data2 [64 bits(taker part1) + 32 bits(expiryTime) + 160 bits(erc20Token)]
    /// data3 [96 bits(taker part2) + 160 bits(platformFeeRecipient)]
    function _fillBatchSignedERC721Order(uint256 offsetCollectionsBytes) internal {
        assembly {
            /////////////////////////// memory[0x0 - 0x1c0] for emitEvent data ////////////////////////
            // memory[0x0 - 0x20] orderHash
            // memory[0x20 - 0x40] maker
            mstore(0x20, and(calldataload(0x4), MASK_160)) // maker = data1 & MASK_160
            // memory[0x40 - 0x60] taker
            mstore(0x40, or(shl(96, shr(192, calldataload(0x24))), shr(160, calldataload(0x44)))) // taker = ((data2 >> 192) << 96) | (data3 >> 160)
            if iszero(mload(0x40)) {
                mstore(0x40, caller())
            }

            // memory[0x60 - 0x80] nonce
            // memory[0x80 - 0xa0] erc20Token
            mstore(0x80, and(calldataload(0x24), MASK_160)) // erc20Token = data2 & MASK_160
            // memory[0xa0 - 0xc0] erc20TokenAmount
            // memory[0xc0 - 0xe0] fees.offset
            mstore(0xc0, 0x120 /* 9 * 32 */)
            // memory[0xe0 - 0x100] nftAddress
            // memory[0x100 - 0x120] nftId
            // memory[0x120 - 0x140] fees.length
            // memory[0x140 - 0x1c0] fees.data

            /////////////////////////// memory[0x1c0 - 0x240] for transferERC721 //////////
            // memory[0x1c0 - 0x1e0] selector for `transferFrom(address,address,uint256)`
            mstore(0x1c0, 0x23b872dd)
            // memory[0x1e0 - 0x200] maker
            mstore(0x1e0, mload(0x20))
            // memory[0x200 - 0x220] taker
            mstore(0x200, mload(0x40))
            // memory[0x220 - 0x240] nftId

            /////////////////////////// memory[0x240 - 0x300] for nonceVector /////////////
            // Note: nonceRange = nonce >> 8
            // Note: nonceVector = LibERC721OrdersStorage.orderStatusByMaker[maker][nonceRange]
            // Note: nonceVector.slot = keccak256(nonceRange, keccak256(maker, LibERC721OrdersStorage.storageId))

            // memory[0x240 - 0x260] shouldStoreNonceVectorToStorage flag
            mstore(0x240, 0)
            // memory[0x260 - 0x280] nonceMask
            // memory[0x280 - 0x2a0] nonceVector.slot
            // memory[0x2a0 - 0x2c0] nonceVector
            // memory[0x2c0 - 0x2e0] nonceRange
            mstore(0x2c0, NONCE_RANGE_LIMIT)
            // memory[0x2e0 - 0x300] keccak256(maker, LibERC721OrdersStorage.storageId)
            mstore(0x2e0, mload(0x20))
            mstore(0x300, STORAGE_ID_ERC721_ORDERS)
            mstore(0x2e0, keccak256(0x2e0, 0x40))

            /////////////////////////// memory[0x300 - 0x380] for collection //////////////
            // memory[0x300 - 0x320] collection.head2
            // memory[0x320 - 0x340] collection.platformFeePercentage
            // memory[0x340 - 0x360] collection.royaltyFeePercentage
            // memory[0x360 - 0x380] someSuccess flag
            mstore(0x360, 0)

            /////////////////////////// memory[0x380 - 0x420] for delegateCall  ///////////
            // memory[0x380 - 0x3a0] erc20TokenFromDelegateCall
            // memory[0x3a0 - 0x3c0] platformFeeRecipientFromDelegateCall
            // memory[0x3c0 - 0x3e0] royaltyFeeRecipientFromDelegateCall
            // memory[0x3e0 - 0x400] platformFeeGlobal
            mstore(0x3e0, 0)
            // memory[0x400 - 0x420] royaltyFeeGlobal
            mstore(0x400, 0)

            /////////////////////////// memory[0x420 - 0x4a0] for transferERC20 ///////////
            // memory[0x420 - 0x440] selector for `transferFrom(address,address,uint256)`
            mstore(0x420, 0x23b872dd)
            // memory[0x440 - 0x460] msg.sender
            mstore(0x440, caller())
            // memory[0x460 - 0x480] to
            // memory[0x480 - 0x4a0] amount

            /////////////////////////// global variables /////////////////////////////////
            let nonceVectorForCheckingNonReentrant

            // collectionStartNonce = (data1 >> 200) & MASK_40
            let collectionStartNonce := and(shr(200, calldataload(0x4)), MASK_40)

            // platformFeeRecipient = data3 & MASK_160
            let platformFeeRecipient := and(calldataload(0x44), MASK_160)

            // Total erc20 amount.
            let totalERC20AmountToPlatform
            let totalERC20AmountToMaker

            let ptrEnd := add(offsetCollectionsBytes, calldataload(sub(offsetCollectionsBytes, 0x20)))
            for { let offsetCollection := offsetCollectionsBytes } lt(offsetCollection, ptrEnd) {} {
                // memory[0xe0 - 0x100] nftAddress
                // head1 [96 bits(filledIndexList part1) + 160 bits(nftAddress)]
                mstore(0xe0, and(calldataload(offsetCollection), MASK_160)) // nftAddress = head1 & MASK_160

                // memory[0x300 - 0x320] collection.head2
                // collectionType: 0 - basicCollection, 1 - collection
                // head2 [8 bits(collectionType) + 8 bits(itemsCount) + 8 bits(filledCount) + 8 bits(unused) + 32 bits(filledIndexList part2)
                //        + 16 bits(platformFeePercentage) + 16 bits(royaltyFeePercentage) + 160 bits(royaltyFeeRecipient)]
                mstore(0x300, calldataload(add(offsetCollection, 0x20)))

                // filledIndexList [96 bits(filledIndexList part1) + 32 bits(filledIndexList part2) + 128 bits(unused)]
                // filledIndexList = (head1 & MASK_INDEX_LIST_PART1) | ((head2 >> 64) & MASK_INDEX_LIST_PART2)
                let filledIndexList := or(and(calldataload(offsetCollection), MASK_INDEX_LIST_PART1), and(shr(64, mload(0x300)), MASK_INDEX_LIST_PART2))
                let filledCount := byte(2, mload(0x300))
                let itemsCount := byte(1, mload(0x300))
                if filledCount {
                    if gt(filledCount, itemsCount) {
                        _revertInvalidFilledIndex()
                    }
                    if gt(filledCount, 128) {
                        _revertInvalidFilledIndex()
                    }
                    if iszero(extcodesize(mload(0xe0))) {
                        _revertInvalidERC721Token()
                    }
                }

                // memory[0x140 - 0x160] platformFeeRecipient
                mstore(0x140, platformFeeRecipient)
                // memory[0x320 - 0x340] collection.platformFeePercentage
                switch platformFeeRecipient
                // if (platformFeeRecipient == address(0) platformFeePercentage = 0
                case 0 { mstore(0x320, 0) }
                // else platformFeePercentage = collection.platformFeePercentage
                default { mstore(0x320, and(shr(176, mload(0x300)), MASK_16)) }

                // memory[0x180 - 0x1a0] royaltyFeeRecipient
                mstore(0x180, and(mload(0x300), MASK_160))
                // memory[0x340 - 0x360] collection.royaltyFeePercentage
                switch mload(0x180)
                // if (royaltyFeeRecipient == address(0) royaltyFeePercentage = 0
                case 0 { mstore(0x340, 0) }
                // else royaltyFeePercentage = collection.royaltyFeePercentage
                default { mstore(0x340, and(shr(160, mload(0x300)), MASK_16)) }

                // Check fees.
                if gt(add(mload(0x320), mload(0x340)), 10000) {
                    revertFeesPercentageExceedsLimit()
                }

                let totalERC20AmountToRoyalty

                // switch collectionType
                switch byte(0, mload(0x300))

                // basicCollection
                case 0 {
                    for { } filledCount { } {
                        filledCount := sub(filledCount, 1)

                        let filledIndex := byte(filledCount, filledIndexList)
                        if iszero(lt(filledIndex, itemsCount)) {
                            _revertInvalidFilledIndex()
                        }

                        // memory[0x60 - 0x80] nonce
                        // memory[0x240 - 0x260] shouldStoreNonceVectorToStorage flag
                        // memory[0x260 - 0x280] nonceMask
                        // memory[0x280 - 0x2a0] nonceVector.slot
                        // memory[0x2a0 - 0x2c0] nonceVector
                        // memory[0x2c0 - 0x2e0] nonceRange
                        // memory[0x2e0 - 0x300] keccak256(maker, LibERC721OrdersStorage.storageId)

                        // nonce = add(collectionStartNonce, filledIndex)
                        mstore(0x60, add(collectionStartNonce, filledIndex))

                        // if (nonceRange != newNonceRange)
                        if iszero(eq(mload(0x2c0), shr(8, mload(0x60)))) {
                            // Store nonce to storage if needed.
                            if mload(0x240) {
                                // Revert if reentrant.
                                if iszero(eq(nonceVectorForCheckingNonReentrant, sload(mload(0x280)))) {
                                    _revertReentrantCall()
                                }

                                // Store nonce to storage at one time.
                                sstore(mload(0x280), mload(0x2a0))
                                // Clear store nonceVector flag.
                                mstore(0x240, 0)
                            }

                            // nonceRange = nonce >> 8
                            mstore(0x2c0, shr(8, mload(0x60)))
                            // Calculate nonceVector.slot and store to memory.
                            mstore(0x280, keccak256(0x2c0, 0x40))
                            // Load nonceVector from storage.
                            nonceVectorForCheckingNonReentrant := sload(mload(0x280))
                            // Store nonceVector to memory.
                            mstore(0x2a0, nonceVectorForCheckingNonReentrant)
                        }

                        // memory[0x260 - 0x280] nonceMask
                        // nonceMask = 1 << (nonce & 0xff)
                        mstore(0x260, shl(and(mload(0x60), 0xff), 1))

                        // if order is not filled.
                        // if (nonceVector & nonceMask == 0)
                        if iszero(and(mload(0x2a0), mload(0x260))) {
                            // orderItem [96 bits(erc20TokenAmount) + 160 bits(nftId)]
                            let orderItem := calldataload(add(add(offsetCollection, 0x40), mul(filledIndex, 0x20)))

                            // memory[0xe0 - 0x100] nftAddress
                            // memory[0x1c0 - 0x1e0] selector for `transferFrom(address,address,uint256)`
                            // memory[0x1e0 - 0x200] maker
                            // memory[0x200 - 0x220] taker
                            // memory[0x220 - 0x240] nftId
                            mstore(0x220, and(orderItem, MASK_160))

                            // transferERC721
                            // 0x1dc = 0x1c0 + 28
                            if call(gas(), mload(0xe0), 0, 0x1dc, 0x64, 0, 0) {
                                // Set store nonceVector flag.
                                mstore(0x240, 1)

                                // Update nonceVector.
                                // nonceVector |= nonceMask
                                mstore(0x2a0, or(mload(0x2a0), mload(0x260)))

                                // Calculate fees.
                                // memory[0xa0 - 0xc0] erc20TokenAmount
                                mstore(0xa0, shr(160, orderItem)) // erc20TokenAmount = orderItem >> 160

                                // memory[0x140 - 0x1c0] fees.data
                                // memory[0x140 - 0x160] platformFeeRecipient
                                // memory[0x160 - 0x180] platformFeeAmount
                                // memory[0x180 - 0x1a0] royaltyFeeRecipient
                                // memory[0x1a0 - 0x1c0] royaltyFeeAmount

                                // memory[0x320 - 0x340] platformFeePercentage
                                // platformFeeAmount = erc20TokenAmount * platformFeePercentage / 10000
                                mstore(0x160, div(mul(mload(0xa0), mload(0x320)), 10000))

                                // memory[0x340 - 0x360] royaltyFeePercentage
                                // royaltyFeeAmount = erc20TokenAmount * royaltyFeePercentage / 10000
                                mstore(0x1a0, div(mul(mload(0xa0), mload(0x340)), 10000))

                                // Update total erc20 amount.
                                // totalERC20AmountToMaker += erc20TokenAmount - (platformFeeAmount + royaltyFeeAmount)
                                totalERC20AmountToMaker := add(totalERC20AmountToMaker, sub(mload(0xa0), add(mload(0x160), mload(0x1a0))))
                                // totalERC20AmountToPlatform += platformFeeAmount
                                totalERC20AmountToPlatform := add(totalERC20AmountToPlatform, mload(0x160))
                                // totalERC20AmountToRoyalty += royaltyFeeAmount
                                totalERC20AmountToRoyalty := add(totalERC20AmountToRoyalty, mload(0x1a0))

                                // Emit event
                                // memory[0 - 0x20] orderHash
                                // memory[0x20 - 0x40] maker
                                // memory[0x40 - 0x60] taker
                                // memory[0x60 - 0x80] nonce
                                // memory[0x80 - 0xa0] erc20Token
                                // memory[0xa0 - 0xc0] erc20TokenAmount
                                // memory[0xc0 - 0xe0] fees.offset
                                // memory[0xe0 - 0x100] nftAddress
                                // memory[0x100 - 0x120] nftId
                                mstore(0x100, mload(0x220))

                                // fees
                                switch platformFeeRecipient
                                case 0 {
                                    // memory[0x180 - 0x1a0] royaltyFeeRecipient
                                    switch mload(0x180)
                                    case 0 {
                                        // memory[0x120 - 0x140] fees.length
                                        mstore(0x120, 0)
                                        // emit event
                                        log1(0, 320 /* 10 * 32 */, _TOPIC_SELL_ORDER_FILLED)
                                    }
                                    default {
                                        // memory[0x120 - 0x140] fees.length
                                        mstore(0x120, 1)
                                        // Copy royaltyFeeRecipient to memory[0x140 - 0x160]
                                        mstore(0x140, mload(0x180))
                                        // Copy royaltyFeeAmount to memory[0x160 - 0x180]
                                        mstore(0x160, mload(0x1a0))
                                        // emit event
                                        log1(0, 384 /* 12 * 32 */, _TOPIC_SELL_ORDER_FILLED)
                                    }
                                }
                                default {
                                    // memory[0x180 - 0x1a0] royaltyFeeRecipient
                                    switch mload(0x180)
                                    case 0 {
                                        // memory[0x120 - 0x140] fees.length
                                        mstore(0x120, 1)
                                        // emit event
                                        log1(0, 384 /* 12 * 32 */, _TOPIC_SELL_ORDER_FILLED)
                                    }
                                    default {
                                        // memory[0x120 - 0x140] fees.length
                                        mstore(0x120, 2)
                                        // emit event
                                        log1(0, 448 /* 14 * 32 */, _TOPIC_SELL_ORDER_FILLED)
                                    }
                                }

                                // Set someSuccess flag.
                                mstore(0x360, 1)
                            }
                        }
                    } // end for
                    // Update offsetCollection.
                    offsetCollection := add(add(offsetCollection, 0x40), mul(itemsCount, 0x20))
                } // end basicCollection

                // collection
                default {
                    for { } filledCount { } {
                        filledCount := sub(filledCount, 1)

                        let filledIndex := byte(filledCount, filledIndexList)
                        if iszero(lt(filledIndex, itemsCount)) {
                            _revertInvalidFilledIndex()
                        }

                        // memory[0x60 - 0x80] nonce
                        // memory[0x240 - 0x260] shouldStoreNonceVectorToStorage flag
                        // memory[0x260 - 0x280] nonceMask
                        // memory[0x280 - 0x2a0] nonceVector.slot
                        // memory[0x2a0 - 0x2c0] nonceVector
                        // memory[0x2c0 - 0x2e0] nonceRange
                        // memory[0x2e0 - 0x300] keccak256(maker, LibERC721OrdersStorage.storageId)

                        // nonce = add(collectionStartNonce, filledIndex)
                        mstore(0x60, add(collectionStartNonce, filledIndex))

                        // if (nonceRange != newNonceRange)
                        if iszero(eq(mload(0x2c0), shr(8, mload(0x60)))) {
                            // Store nonce to storage if needed.
                            if mload(0x240) {
                                // Revert if reentrant.
                                if iszero(eq(nonceVectorForCheckingNonReentrant, sload(mload(0x280)))) {
                                    _revertReentrantCall()
                                }

                                // Store nonce to storage at one time.
                                sstore(mload(0x280), mload(0x2a0))
                                // Clear store nonceVector flag.
                                mstore(0x240, 0)
                            }

                            // nonceRange = nonce >> 8
                            mstore(0x2c0, shr(8, mload(0x60)))
                            // Calculate nonceVector.slot and store to memory.
                            mstore(0x280, keccak256(0x2c0, 0x40))
                            // Load nonceVector from storage.
                            nonceVectorForCheckingNonReentrant := sload(mload(0x280))
                            // Store nonceVector to memory.
                            mstore(0x2a0, nonceVectorForCheckingNonReentrant)
                        }

                        // memory[0x260 - 0x280] nonceMask
                        // nonceMask = 1 << (nonce & 0xff)
                        mstore(0x260, shl(and(mload(0x60), 0xff), 1))

                        // if order is not filled.
                        // if (nonceVector & nonceMask == 0)
                        if iszero(and(mload(0x2a0), mload(0x260))) {
                            // struct OrderItem {
                            //     uint256 erc20TokenAmount;
                            //     uint256 nftId;
                            // }
                            let offsetOrderItem := add(add(offsetCollection, 0x40), mul(filledIndex, 0x40))
                            if gt(calldataload(offsetOrderItem), MAX_ERC20_AMOUNT) {
                                _revertERC20AmountExceedsLimit()
                            }

                            // memory[0xe0 - 0x100] nftAddress
                            // memory[0x1c0 - 0x1e0] selector for `transferFrom(address,address,uint256)`
                            // memory[0x1e0 - 0x200] maker
                            // memory[0x200 - 0x220] taker
                            // memory[0x220 - 0x240] nftId
                            mstore(0x220, calldataload(add(offsetOrderItem, 0x20)))

                            // transferERC721
                            // 0x1dc = 0x1c0 + 28
                            if call(gas(), mload(0xe0), 0, 0x1dc, 0x64, 0, 0) {
                                // Set store nonceVector flag.
                                mstore(0x240, 1)

                                // Update nonceVector.
                                // nonceVector |= nonceMask
                                mstore(0x2a0, or(mload(0x2a0), mload(0x260)))

                                // Calculate fees.
                                // memory[0xa0 - 0xc0] erc20TokenAmount
                                mstore(0xa0, calldataload(offsetOrderItem))

                                // memory[0x140 - 0x1c0] fees.data
                                // memory[0x140 - 0x160] platformFeeRecipient
                                // memory[0x160 - 0x180] platformFeeAmount
                                // memory[0x180 - 0x1a0] royaltyFeeRecipient
                                // memory[0x1a0 - 0x1c0] royaltyFeeAmount

                                // memory[0x320 - 0x340] platformFeePercentage
                                // platformFeeAmount = erc20TokenAmount * platformFeePercentage / 10000
                                mstore(0x160, div(mul(mload(0xa0), mload(0x320)), 10000))

                                // memory[0x340 - 0x360] royaltyFeePercentage
                                // royaltyFeeAmount = erc20TokenAmount * royaltyFeePercentage / 10000
                                mstore(0x1a0, div(mul(mload(0xa0), mload(0x340)), 10000))

                                // Update total erc20 amount.
                                // totalERC20AmountToMaker += erc20TokenAmount - (platformFeeAmount + royaltyFeeAmount)
                                totalERC20AmountToMaker := add(totalERC20AmountToMaker, sub(mload(0xa0), add(mload(0x160), mload(0x1a0))))
                                // totalERC20AmountToPlatform += platformFeeAmount
                                totalERC20AmountToPlatform := add(totalERC20AmountToPlatform, mload(0x160))
                                // totalERC20AmountToRoyalty += royaltyFeeAmount
                                totalERC20AmountToRoyalty := add(totalERC20AmountToRoyalty, mload(0x1a0))

                                // Emit event
                                // memory[0 - 0x20] orderHash
                                // memory[0x20 - 0x40] maker
                                // memory[0x40 - 0x60] taker
                                // memory[0x60 - 0x80] nonce
                                // memory[0x80 - 0xa0] erc20Token
                                // memory[0xa0 - 0xc0] erc20TokenAmount
                                // memory[0xc0 - 0xe0] fees.offset
                                // memory[0xe0 - 0x100] nftAddress
                                // memory[0x100 - 0x120] nftId
                                mstore(0x100, mload(0x220))

                                // fees
                                switch platformFeeRecipient
                                case 0 {
                                    // memory[0x180 - 0x1a0] royaltyFeeRecipient
                                    switch mload(0x180)
                                    case 0 {
                                        // memory[0x120 - 0x140] fees.length
                                        mstore(0x120, 0)
                                        // emit event
                                        log1(0, 320 /* 10 * 32 */, _TOPIC_SELL_ORDER_FILLED)
                                    }
                                    default {
                                        // memory[0x120 - 0x140] fees.length
                                        mstore(0x120, 1)
                                        // Copy royaltyFeeRecipient to memory[0x140 - 0x160]
                                        mstore(0x140, mload(0x180))
                                        // Copy royaltyFeeAmount to memory[0x160 - 0x180]
                                        mstore(0x160, mload(0x1a0))
                                        // emit event
                                        log1(0, 384 /* 12 * 32 */, _TOPIC_SELL_ORDER_FILLED)
                                    }
                                }
                                default {
                                    // memory[0x180 - 0x1a0] royaltyFeeRecipient
                                    switch mload(0x180)
                                    case 0 {
                                        // memory[0x120 - 0x140] fees.length
                                        mstore(0x120, 1)
                                        // emit event
                                        log1(0, 384 /* 12 * 32 */, _TOPIC_SELL_ORDER_FILLED)
                                    }
                                    default {
                                        // memory[0x120 - 0x140] fees.length
                                        mstore(0x120, 2)
                                        // emit event
                                        log1(0, 448 /* 14 * 32 */, _TOPIC_SELL_ORDER_FILLED)
                                    }
                                }

                                // Set someSuccess flag.
                                mstore(0x360, 1)
                            }
                        }
                    } // end for
                    // Update offsetCollection.
                    offsetCollection := add(add(offsetCollection, 0x40), mul(itemsCount, 0x40))
                } // end collection

                // Update collectionStartNonce.
                // collectionStartNonce += itemsCount
                // memory[0x300 - 0x320] collection.head2
                collectionStartNonce := add(collectionStartNonce, itemsCount)

                // Pay royaltyFee together.
                if totalERC20AmountToRoyalty {
                    // memory[0x80 - 0xa0] erc20Token
                    // memory[0x180 - 0x1a0] royaltyFeeRecipient
                    // memory[0x380 - 0x3a0] erc20TokenFromDelegateCall
                    // memory[0x3c0 - 0x3e0] royaltyFeeRecipientFromDelegateCall
                    switch and(eq(mload(0x80), mload(0x380)), eq(mload(0x180), mload(0x3c0)))
                    case 1 {
                        // memory[0x400 - 0x420] royaltyFeeGlobal
                        mstore(0x400, add(mload(0x400), totalERC20AmountToRoyalty))
                    }
                    default {
                        _transferERC20(mload(0x180), totalERC20AmountToRoyalty)
                    }
                }
            } // end for

            // Store nonce to storage if needed.
            if mload(0x240) {
                // Revert if reentrant.
                if iszero(eq(nonceVectorForCheckingNonReentrant, sload(mload(0x280)))) {
                    _revertReentrantCall()
                }

                // Store nonce to storage at one time.
                // memory[0x280 - 0x2a0] nonceVector.slot
                // memory[0x2a0 - 0x2c0] nonceVector
                sstore(mload(0x280), mload(0x2a0))
            }

            // Pay to maker at one time.
            if totalERC20AmountToMaker {
                // memory[0x20 - 0x40] maker
                _transferERC20(mload(0x20), totalERC20AmountToMaker)
            }

            // Pay to platform at one time.
            if totalERC20AmountToPlatform {
                // memory[0x80 - 0xa0] erc20Token
                // memory[0x380 - 0x3a0] erc20TokenFromDelegateCall
                // memory[0x3a0 - 0x3c0] platformFeeRecipientFromDelegateCall
                switch and(eq(mload(0x80), mload(0x380)), eq(platformFeeRecipient, mload(0x3a0)))
                case 1 {
                    // memory[0x3e0 - 0x400] platformFeeGlobal
                    mstore(0x3e0, add(mload(0x3e0), totalERC20AmountToPlatform))
                }
                default {
                    _transferERC20(platformFeeRecipient, totalERC20AmountToPlatform)
                }
            }

            // Revert if none of the orders is filled.
            // memory[0x360 - 0x380] someSuccess flag
            if iszero(mload(0x360)) {
                _revertNoOrderFilled()
            }

            ///////////////////////////////// functions  /////////////////////////////////
            function _transferERC20(_to, _amount) {
                // memory[0x80 - 0xa0] erc20Token
                switch mload(0x80)
                case 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE {
                    if iszero(call(gas(), _to, _amount, 0, 0, 0, 0)) {
                        _revertTransferETHFailed()
                    }
                }
                default {
                    if iszero(extcodesize(mload(0x80))) {
                        _revertInvalidERC20Token()
                    }

                    // memory[0x420 - 0x440] selector for `transferFrom(address,address,uint256)`
                    // memory[0x440 - 0x460] msg.sender
                    // memory[0x460 - 0x480] to
                    mstore(0x460, _to)
                    // memory[0x480 - 0x4a0] amount
                    mstore(0x480, _amount)

                    // memory[0x80 - 0xa0] erc20Token
                    // 0x43c = 0x420 + 28
                    if iszero(call(gas(), mload(0x80), 0, 0x43c, 0x64, 0x480, 0x20)) {
                        _revertTransferERC20Failed()
                    }

                    // Check for ERC20 success. ERC20 tokens should return a boolean, but some don't.
                    // We accept 0-length return data as success, or at least 32 bytes that starts with
                    // a 32-byte boolean true.
                    if returndatasize() {
                        if lt(returndatasize(), 0x20) {
                            _revertTransferERC20Failed()
                        }
                        if iszero(eq(mload(0x480), 1)) {
                            _revertTransferERC20Failed()
                        }
                    }
                }
            }

            function revertFeesPercentageExceedsLimit() {
                // revert("fillBatchSignedERC721Order: total fees percentage exceeds the limit.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000004466696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x746f74616c20666565732070657263656e746167652065786365656473207468)
                mstore(0x80, 0x65206c696d69742e000000000000000000000000000000000000000000000000)
                mstore(0xa0, 0)
                revert(0, 0xa4)
            }

            function _revertInvalidFilledIndex() {
                // revert("fillBatchSignedERC721Order: invalid filledIndex.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003066696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x696e76616c69642066696c6c6564496e6465782e000000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertReentrantCall() {
                // revert("fillBatchSignedERC721Order: reentrant call.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000002b66696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x7265656e7472616e742063616c6c2e0000000000000000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertERC20AmountExceedsLimit() {
                // revert("fillBatchSignedERC721Order: erc20TokenAmount exceeds limit.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003b66696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x6572633230546f6b656e416d6f756e742065786365656473206c696d69742e00)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertNoOrderFilled() {
                // revert("fillBatchSignedERC721Order: no order filled.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000002c66696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x6e6f206f726465722066696c6c65642e00000000000000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertTransferETHFailed() {
                // revert("fillBatchSignedERC721Order: failed to transfer ETH.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003366696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x6661696c656420746f207472616e73666572204554482e000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertTransferERC20Failed() {
                // revert("fillBatchSignedERC721Order: failed to transfer ERC20.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003566696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x6661696c656420746f207472616e736665722045524332302e00000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertInvalidERC20Token() {
                // revert("invalid erc20 token")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x00000013696e76616c696420657263323020746f6b656e000000000000000000)
                mstore(0x60, 0)
                revert(0, 0x64)
            }

            function _revertInvalidERC721Token() {
                // revert("invalid erc271 token")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x00000014696e76616c69642065726337323120746f6b656e0000000000000000)
                mstore(0x60, 0)
                revert(0, 0x64)
            }
        }
    }

    /// data1 [8 bits(signatureType) + 8 bits(reserved) + 40 bits(startNonce) + 8 bits(v) + 32 bits(listingTime) + 160 bits(maker)]
    /// data2 [64 bits(taker part1) + 32 bits(expiryTime) + 160 bits(erc20Token)]
    function _validateOrder(uint256 offsetCollectionsBytes) internal view returns (bytes32 orderHash) {
        address maker;
        uint8 signatureType;
        uint8 v;

        assembly {
            let data1 := calldataload(0x4)
            let data2 := calldataload(0x24)
            signatureType := byte(0, data1)
            v := byte(7, data1)

            // Check for listingTime.
            // if ((data1 >> 160) & MASK_32 > block.timestamp)
            if gt(and(shr(160, data1), MASK_32), timestamp()) {
                // revert("fillBatchSignedERC721Order: failed to check for listingTime.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003c66696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x6661696c656420746f20636865636b20666f72206c697374696e6754696d652e)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            // Check for expiryTime.
            // if ((data2 >> 160) & MASK_32 <= block.timestamp)
            if iszero(gt(and(shr(160, data2), MASK_32), timestamp())) {
                // revert("fillBatchSignedERC721Order: failed to check for expiryTime.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003b66696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x6661696c656420746f20636865636b20666f722065787069727954696d652e00)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            // Check for erc20Token.
            if iszero(and(data2, MASK_160)) {
                // revert("fillBatchSignedERC721Order: invalid erc20Token.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000002f66696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x696e76616c6964206572633230546f6b656e2e00000000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            // Check maker.
            maker := and(data1, MASK_160)
            if iszero(maker) {
                // revert("fillBatchSignedERC721Order: invalid maker.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000002a66696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x696e76616c6964206d616b65722e000000000000000000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }
        }

        // Get order hash.
        orderHash = _getEIP712Hash(_getStructHash(offsetCollectionsBytes));

        if (signatureType == 0) {
            bytes32 r;
            bytes32 s;
            assembly {
                // Must reset memory status before the `require` sentence.
                mstore(0x40, 0x80)
                mstore(0x60, 0)

                // Get r and v.
                r := calldataload(0x64)
                s := calldataload(0x84)
            }
            require(maker == ecrecover(orderHash, v, r, s), "fillBatchSignedERC721Order: failed to validate signature.");
        } else if (signatureType == 3) {
            assembly {
                // selector for `isValidSignature(bytes32,bytes)`
                mstore(0, 0x1626ba7e)
                mstore(0x20, orderHash)
                mstore(0x40, 0x40)
                mstore(0x60, 0x41)
                calldatacopy(0x80, 0x64, 64)
                mstore(0xc0, shl(248, v))

                if iszero(extcodesize(maker)) {
                    _revertInvalidMaker()
                }

                // Call signer with `isValidSignature` to validate signature.
                if iszero(staticcall(gas(), maker, 0x1c, 0xa5, 0, 0x20)) {
                    _revertInvalidSignature()
                }

                // Check for returnData.
                if iszero(eq(mload(0), 0x1626ba7e00000000000000000000000000000000000000000000000000000000)) {
                    _revertInvalidSignature()
                }

                function _revertInvalidMaker() {
                    // revert("fillBatchSignedERC721Order: invalid maker.")
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                    mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                    mstore(0x40, 0x0000002a66696c6c42617463685369676e65644552433732314f726465723a20)
                    mstore(0x60, 0x696e76616c6964206d616b65722e000000000000000000000000000000000000)
                    mstore(0x80, 0)
                    revert(0, 0x84)
                }

                function _revertInvalidSignature() {
                    // revert("fillBatchSignedERC721Order: invalid signature.")
                    mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                    mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                    mstore(0x40, 0x0000003266696c6c42617463685369676e65644552433732314f726465723a20)
                    mstore(0x60, 0x696e76616c6964207369676e61747572652e0000000000000000000000000000)
                    mstore(0x80, 0)
                    revert(0, 0x84)
                }
            }
        } else {
            assembly {
                // revert("fillBatchSignedERC721Order: invalid signatureType.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003266696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x696e76616c6964207369676e6174757265547970652e00000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }
        }
    }

    function _getEIP712Hash(bytes32 structHash) internal view returns (bytes32 eip712Hash) {
        assembly {
            // EIP712_DOMAIN_SEPARATOR = keccak256(abi.encode(
            //     DOMAIN,
            //     NAME,
            //     VERSION,
            //     block.chainid,
            //     address(this)
            // ));
            mstore(0, DOMAIN)
            mstore(0x20, NAME)
            mstore(0x40, VERSION)
            mstore(0x60, chainid())
            mstore(0x80, address())

            // eip712Hash = keccak256(abi.encodePacked(
            //     hex"1901",
            //     EIP712_DOMAIN_SEPARATOR,
            //     structHash
            // ));
            mstore(0xa0, 0x1901000000000000000000000000000000000000000000000000000000000000)
            mstore(0xa2, keccak256(0, 0xa0))
            mstore(0xc2, structHash)
            eip712Hash := keccak256(0xa0, 0x42)
        }
    }

    /// data1 [[8 bits(signatureType) + 8 bits(reserved) + 40 bits(startNonce) + 8 bits(v) + 32 bits(listingTime) + 160 bits(maker)]
    /// data2 [64 bits(taker part1) + 32 bits(expiryTime) + 160 bits(erc20Token)]
    /// data3 [96 bits(taker part2) + 160 bits(platformFeeRecipient)]
    function _getStructHash(uint256 offsetCollectionsBytes) internal view returns (bytes32 structHash) {
        // structHash = keccak256(abi.encode(
        //     _BATCH_SIGNED_ERC721_ORDERS_TYPE_HASH, // offset: 0x0
        //     maker,       // offset: 0x20
        //     listingTime, // offset: 0x40
        //     expiryTime,  // offset: 0x60
        //     startNonce,  // offset: 0x80
        //     erc20Token,  // offset: 0xa0
        //     platformFeeRecipient,    // offset: 0xc0
        //     basicCollectionsHash,    // offset: 0xe0
        //     collectionsHash,         // offset: 0x100
        //     hashNonce    // offset: 0x120
        // ));

        // Store basicCollectionsHash to memory[0xe0] and store collectionsHash to memory[0x100].
        _storeCollectionsHashToMemory(offsetCollectionsBytes);

        assembly {
            let data1 := calldataload(0x4)
            let data2 := calldataload(0x24)
            let data3 := calldataload(0x44)
            let maker := and(data1, MASK_160)

            // _BATCH_SIGNED_ERC721_ORDERS_TYPE_HASH
            mstore(0, _BATCH_SIGNED_ERC721_ORDERS_TYPE_HASH)

            // maker
            mstore(0x20, maker)

            // listingTime = (data1 >> 160) & MASK_32
            mstore(0x40, and(shr(160, data1), MASK_32))

            // expiryTime = (data2 >> 160) & MASK_32
            mstore(0x60, and(shr(160, data2), MASK_32))

            // startNonce = (data1 >> 200) & MASK_40
            mstore(0x80, and(shr(200, data1), MASK_40))

            // erc20Token = data2 & MASK_160
            mstore(0xa0, and(data2, MASK_160))

            // platformFeeRecipient = data3 & MASK_160
            mstore(0xc0, and(data3, MASK_160))

            // 0xe0 basicCollectionsHash
            // 0x100 collectionsHash

            // 0x120 hashNonce
            // hashNonce.slot = keccak256(abi.encode(maker, STORAGE_ID_COMMON_NFT_ORDERS))
            // hashNonce = sload(hashNonce.slot)
            mstore(0x120, maker)
            mstore(0x140, STORAGE_ID_COMMON_NFT_ORDERS)
            mstore(0x120, sload(keccak256(0x120, 0x40)))

            structHash := keccak256(0, 0x140 /* 10 * 32 */)
        }
    }

    function _storeCollectionsHashToMemory(uint256 offsetCollectionsBytes) internal pure {
        assembly {
            let isBasicCollectionsEnded
            let basicCollectionsHash
            let ptrCollectionHash

            let offsetCollection := offsetCollectionsBytes
            let ptrEnd := add(offsetCollectionsBytes, calldataload(sub(offsetCollectionsBytes, 0x20)))
            for {} lt(offsetCollection, ptrEnd) {} {
                // head1 [96 bits(filledIndexList part1) + 160 bits(nftAddress)]
                // nftAddress = head1 & MASK_160
                let nftAddress := and(calldataload(offsetCollection), MASK_160)
                if iszero(nftAddress) {
                    _revertInvalidNftAddress()
                }

                // collectionType: 0 - basicCollection, 1 - collection
                // head2 [8 bits(collectionType) + 8 bits(itemsCount) + 8 bits(filledCount) + 8 bits(unused) + 32 bits(filledIndexList part2)
                //        + 16 bits(platformFeePercentage) + 16 bits(royaltyFeePercentage) + 160 bits(royaltyFeeRecipient)]
                let head2 := calldataload(add(offsetCollection, 0x20))

                let itemsCount := byte(1, head2)
                if iszero(itemsCount) {
                    _revertInvalidItemCount()
                }

                let filledCount := byte(2, head2)
                if or(gt(filledCount, itemsCount), gt(filledCount, 16)) {
                    _revertInvalidFilledCount()
                }

                // basicCollection
                if iszero(byte(0, head2)) {
                    if isBasicCollectionsEnded {
                        _revertInvalidCollectionsBytes()
                    }

                    // typeHash = _BASIC_COLLECTION_TYPE_HASH
                    mstore(ptrCollectionHash, _BASIC_COLLECTION_TYPE_HASH)

                    // nftAddress
                    mstore(add(ptrCollectionHash, 0x20), nftAddress)

                    // fee = head2 & MASK_192
                    mstore(add(ptrCollectionHash, 0x40), and(head2, MASK_192))

                    // itemsHash
                    let ptrItemsHash := add(ptrCollectionHash, 0x60)
                    let itemsBytesLength := mul(itemsCount, 0x20)

                    // offset: 0x0 - head1
                    //         0x20 - head2
                    //         0x40 - items.data
                    let offsetItems := add(offsetCollection, 0x40)
                    calldatacopy(ptrItemsHash, offsetItems, itemsBytesLength)

                    // Calculate and store itemsHash.
                    mstore(ptrItemsHash, keccak256(ptrItemsHash, itemsBytesLength))

                    // keccak256(abi.encode(_BASIC_COLLECTION_TYPE_HASH, nftAddress, fee, itemsHash))
                    mstore(ptrCollectionHash, keccak256(ptrCollectionHash, 0x80))

                    // Update offset.
                    ptrCollectionHash := add(ptrCollectionHash, 0x20)
                    offsetCollection := add(offsetItems, itemsBytesLength)
                    continue
                }

                // Get basicCollectionsHash.
                if iszero(isBasicCollectionsEnded) {
                    // Set flag.
                    isBasicCollectionsEnded := 1

                    switch ptrCollectionHash
                    case 0 {
                        // basicCollections is empty.
                        basicCollectionsHash := _EMPTY_ARRAY_KECCAK256
                    }
                    default {
                        // Calculate basicCollectionsHash.
                        basicCollectionsHash := keccak256(0, ptrCollectionHash)
                        ptrCollectionHash := 0
                    }
                }

                // collection
                // typeHash = _COLLECTION_TYPE_HASH
                mstore(ptrCollectionHash, _COLLECTION_TYPE_HASH)

                // nftAddress
                mstore(add(ptrCollectionHash, 0x20), nftAddress)

                // fee = head2 & MASK_192
                mstore(add(ptrCollectionHash, 0x40), and(head2, MASK_192))

                // itemsHash
                let ptrItemsHash := add(ptrCollectionHash, 0x60)
                let itemsBytesLength := mul(itemsCount, 0x40)

                // offset: 0x0 - head1
                //         0x20 - head2
                //         0x40 - items.data
                let offsetItems := add(offsetCollection, 0x40)

                // Copy items to memory [ptrItemsHash + 0x20].
                // Reserve a slot(0x20) to store _ORDER_ITEM_TYPE_HASH.
                calldatacopy(add(ptrItemsHash, 0x20), offsetItems, itemsBytesLength)

                let ptrItemHashData := ptrItemsHash
                let ptrItemEnd := add(ptrItemsHash, mul(itemsCount, 0x20))
                for { let ptrItem := ptrItemsHash } lt(ptrItem, ptrItemEnd) {} {
                    mstore(ptrItemHashData, _ORDER_ITEM_TYPE_HASH)
                    mstore(ptrItem, keccak256(ptrItemHashData, 0x60))

                    ptrItem := add(ptrItem, 0x20)
                    ptrItemHashData := add(ptrItemHashData, 0x40)
                }

                // Calculate and store itemsHash.
                mstore(ptrItemsHash, keccak256(ptrItemsHash, mul(itemsCount, 0x20)))

                // keccak256(abi.encode(_COLLECTION_TYPE_HASH, nftAddress, fee, itemsHash))
                mstore(ptrCollectionHash, keccak256(ptrCollectionHash, 0x80))

                // Update offset.
                ptrCollectionHash := add(ptrCollectionHash, 0x20)
                offsetCollection := add(offsetItems, itemsBytesLength)
            }

            // if (offsetCollection != ptrEnd) revert()
            if iszero(eq(offsetCollection, ptrEnd)) {
                _revertInvalidCollectionsBytes()
            }

            switch isBasicCollectionsEnded
            // Order.collections is empty.
            case 0 {
                // Order.basicCollections is empty.
                if iszero(ptrCollectionHash) {
                    _revertInvalidCollectionsBytes()
                }

                // Store basicCollectionsHash to memory[0xe0].
                mstore(0xe0, keccak256(0, ptrCollectionHash))

                // Store collectionsHash to memory[0x100].
                mstore(0x100, _EMPTY_ARRAY_KECCAK256)
            }
            // Order.collections is not empty.
            default {
                // Store basicCollectionsHash to memory[0xe0].
                mstore(0xe0, basicCollectionsHash)

                // Store collectionsHash to memory[0x100].
                mstore(0x100, keccak256(0, ptrCollectionHash))
            }

            ///////////////////////////////// functions  /////////////////////////////////
            function _revertInvalidNftAddress() {
                // revert("fillBatchSignedERC721Order: invalid nftAddress.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000002f66696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x696e76616c6964206e6674416464726573732e00000000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertInvalidItemCount() {
                // revert("fillBatchSignedERC721Order: invalid itemCount.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000002e66696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x696e76616c6964206974656d436f756e742e0000000000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertInvalidFilledCount() {
                // revert("fillBatchSignedERC721Order: invalid filledCount.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003066696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x696e76616c69642066696c6c6564436f756e742e000000000000000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }

            function _revertInvalidCollectionsBytes() {
                // revert("fillBatchSignedERC721Order: invalid collectionsBytes.")
                mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
                mstore(0x20, 0x0000002000000000000000000000000000000000000000000000000000000000)
                mstore(0x40, 0x0000003566696c6c42617463685369676e65644552433732314f726465723a20)
                mstore(0x60, 0x696e76616c696420636f6c6c656374696f6e7342797465732e00000000000000)
                mstore(0x80, 0)
                revert(0, 0x84)
            }
        }
    }
}

File 2 of 5 : IBatchSignedERC721OrdersFeature.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2022 Element.Market Intl.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

*/


pragma solidity ^0.8.17;


interface IBatchSignedERC721OrdersFeature {

    /// @param fee [16 bits(platformFeePercentage) + 16 bits(royaltyFeePercentage) + 160 bits(royaltyFeeRecipient)].
    /// @param items [96 bits(erc20TokenAmount) + 160 bits(nftId)].
    /// struct BasicCollection {
    ///     address nftAddress;
    ///     bytes32 fee;
    ///     bytes32[] items;
    /// }
    ///
    /// struct OrderItem {
    ///     uint256 erc20TokenAmount;
    ///     uint256 nftId;
    /// }
    ///
    /// @param fee [16 bits(platformFeePercentage) + 16 bits(royaltyFeePercentage) + 160 bits(royaltyFeeRecipient)].
    /// struct Collection {
    ///     address nftAddress;
    ///     bytes32 fee;
    ///     OrderItem[] items;
    /// }
    ///
    /// struct BatchSignedERC721Orders {
    ///     address maker;
    ///     uint256 listingTime;
    ///     uint256 expiryTime;
    ///     uint256 startNonce;
    ///     address erc20Token;
    ///     address platformFeeRecipient;
    ///     BasicCollection[] basicCollections;
    ///     Collection[] collections;
    ///     uint256 hashNonce;
    /// }

    /// @param data1 [8 bits(signatureType) + 8 bits(reserved) + 40 bits(startNonce) + 8 bits(v) + 32 bits(listingTime) + 160 bits(maker)]
    /// @param data2 [64 bits(taker part1) + 32 bits(expiryTime) + 160 bits(erc20Token)]
    /// @param data3 [96 bits(taker part2) + 160 bits(platformFeeRecipient)]
    struct BatchSignedERC721OrderParameter {
        uint256 data1;
        uint256 data2;
        uint256 data3;
        bytes32 r;
        bytes32 s;
    }

    function fillBatchSignedERC721Order(BatchSignedERC721OrderParameter calldata parameter, bytes calldata collections) external payable;

    /// @param data1 [8 bits(signatureType) + 8 bits(reserved) + 40 bits(startNonce) + 8 bits(v) + 32 bits(listingTime) + 160 bits(maker)]
    /// @param data2 [64 bits(taker part1) + 32 bits(expiryTime) + 160 bits(erc20Token)]
    /// @param data3 [96 bits(taker part2) + 160 bits(platformFeeRecipient)]
    struct BatchSignedERC721OrderParameters {
        uint256 data1;
        uint256 data2;
        uint256 data3;
        bytes32 r;
        bytes32 s;
        bytes collections;
    }

    /// @param additional1 [96 bits(withdrawETHAmount) + 160 bits(erc20Token)]
    /// @param additional2 [8 bits(revertIfIncomplete) + 88 bits(unused) + 160 bits(royaltyFeeRecipient)]
    function fillBatchSignedERC721Orders(
        BatchSignedERC721OrderParameters[] calldata parameters,
        uint256 additional1,
        uint256 additional2
    ) external payable;
}

File 3 of 5 : LibCommonNftOrdersStorage.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Copyright 2022 Element.Market

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

*/

pragma solidity ^0.8.17;

import "./LibStorage.sol";


library LibCommonNftOrdersStorage {

    /// @dev Storage bucket for this feature.
    struct Storage {
        /* Track per-maker nonces that can be incremented by the maker to cancel orders in bulk. */
        // The current nonce for the maker represents the only valid nonce that can be signed by the maker
        // If a signature was signed with a nonce that's different from the one stored in nonces, it
        // will fail validation.
        mapping(address => uint256) hashNonces;
    }

    /// @dev Get the storage bucket for this contract.
    function getStorage() internal pure returns (Storage storage stor) {
        uint256 storageSlot = LibStorage.STORAGE_ID_COMMON_NFT_ORDERS;
        // Dip into assembly to change the slot pointed to by the local
        // variable `stor`.
        // See https://solidity.readthedocs.io/en/v0.6.8/assembly.html?highlight=slot#access-to-external-variables-functions-and-libraries
        assembly { stor.slot := storageSlot }
    }
}

File 4 of 5 : LibERC721OrdersStorage.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Modifications Copyright 2022 Element.Market
  Copyright 2020 ZeroEx Intl.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

*/

pragma solidity ^0.8.17;

import "./LibStorage.sol";


/// @dev Storage helpers for `ERC721OrdersFeature`.
library LibERC721OrdersStorage {

    /// @dev Storage bucket for this feature.
    struct Storage {
        // maker => nonce range => order status bit vector
        mapping(address => mapping(uint248 => uint256)) orderStatusByMaker;
        // order hash => preSigned
        mapping(bytes32 => uint256) preSigned;
        // order hash => filledAmount
        mapping(bytes32 => uint128) filledAmount;
    }

    /// @dev Get the storage bucket for this contract.
    function getStorage() internal pure returns (Storage storage stor) {
        uint256 storageSlot = LibStorage.STORAGE_ID_ERC721_ORDERS;
        // Dip into assembly to change the slot pointed to by the local
        // variable `stor`.
        // See https://solidity.readthedocs.io/en/v0.6.8/assembly.html?highlight=slot#access-to-external-variables-functions-and-libraries
        assembly { stor.slot := storageSlot }
    }
}

File 5 of 5 : LibStorage.sol
// SPDX-License-Identifier: Apache-2.0
/*

  Modifications Copyright 2022 Element.Market
  Copyright 2020 ZeroEx Intl.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

*/

pragma solidity ^0.8.17;


/// @dev Common storage helpers
library LibStorage {

    /// @dev What to bit-shift a storage ID by to get its slot.
    ///      This gives us a maximum of 2**128 inline fields in each bucket.
    uint256 constant STORAGE_ID_PROXY = 1 << 128;
    uint256 constant STORAGE_ID_SIMPLE_FUNCTION_REGISTRY = 2 << 128;
    uint256 constant STORAGE_ID_OWNABLE = 3 << 128;
    uint256 constant STORAGE_ID_COMMON_NFT_ORDERS = 4 << 128;
    uint256 constant STORAGE_ID_ERC721_ORDERS = 5 << 128;
    uint256 constant STORAGE_ID_ERC1155_ORDERS = 6 << 128;
    uint256 constant STORAGE_ID_REENTRANCY_GUARD = 7 << 128;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"components":[{"internalType":"uint256","name":"data1","type":"uint256"},{"internalType":"uint256","name":"data2","type":"uint256"},{"internalType":"uint256","name":"data3","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct IBatchSignedERC721OrdersFeature.BatchSignedERC721OrderParameter","name":"","type":"tuple"},{"internalType":"address","name":"erc20TokenFromDelegateCall","type":"address"},{"internalType":"address","name":"platformFeeRecipientFromDelegateCall","type":"address"},{"internalType":"address","name":"royaltyFeeRecipientFromDelegateCall","type":"address"},{"internalType":"bytes","name":"collections","type":"bytes"}],"name":"delegateCallFillBatchSignedERC721Order","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"data1","type":"uint256"},{"internalType":"uint256","name":"data2","type":"uint256"},{"internalType":"uint256","name":"data3","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct IBatchSignedERC721OrdersFeature.BatchSignedERC721OrderParameter","name":"","type":"tuple"},{"internalType":"bytes","name":"collections","type":"bytes"}],"name":"fillBatchSignedERC721Order","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"data1","type":"uint256"},{"internalType":"uint256","name":"data2","type":"uint256"},{"internalType":"uint256","name":"data3","type":"uint256"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"bytes","name":"collections","type":"bytes"}],"internalType":"struct IBatchSignedERC721OrdersFeature.BatchSignedERC721OrderParameters[]","name":"parameters","type":"tuple[]"},{"internalType":"uint256","name":"additional1","type":"uint256"},{"internalType":"uint256","name":"additional2","type":"uint256"}],"name":"fillBatchSignedERC721Orders","outputs":[],"stateMutability":"payable","type":"function"}]

60c060405234801561001057600080fd5b5060405162001e7438038062001e74833981016040819052610031916100a0565b6001600160a01b03811661008b5760405162461bcd60e51b815260206004820152601460248201527f494e56414c49445f574554485f41444452455353000000000000000000000000604482015260640160405180910390fd5b6001600160a01b031660a052306080526100d0565b6000602082840312156100b257600080fd5b81516001600160a01b03811681146100c957600080fd5b9392505050565b60805160a051611d77620000fd600039600061014601526000818161012501526106bb0152611d776000f3fe6080604052600436106100345760003560e01c8063149b8ce614610039578063a4d730411461004e578063dc055ecc14610061575b600080fd5b61004c610047366004611ae8565b610074565b005b61004c61005c366004611bcb565b6105e6565b61004c61006f366004611c3b565b6106b9565b826100df5760405162461bcd60e51b815260206004820152603060248201527f66696c6c42617463685369676e65644552433732314f72646572733a20696e7660448201526f30b634b2103830b930b6b2ba32b9399760811b60648201526084015b60405180910390fd5b60006100eb3447611cc4565b905060006001600160a01b038686600081811061010a5761010a611ceb565b905060200281019061011c9190611d01565b604001351690507f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000060a086901c6001600160a01b038088169087166000808085156101b15761018d8630896102c4565b632e1a7d4d600052856020526000806024601c60008b5af16101b1576101b1610429565b63dc055ecc6040528461010052886101205283610140526101206101605260208d028e0195508d5b868110156102585780358f0160a08160603760c081013560208106156102015761020161048b565b80610180528060e083016101a037604060008261014401605c8e5af4801561023a5760019450600051870196506020518601955061024d565b8e60001a1561024d573d6000803e3d6000fd5b5050506020016101d9565b50821561026a5761026a838a876102c4565b811561027b5761027b8285876102c4565b80610288576102886104ed565b50505050505083470361029757005b834711156102b757600080600080874703335af161004c5761004c610543565b6102bf610543565b6105dc565b8073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811461034957813b6102ee576102ee61059e565b6323b872dd600052336020528260405283606052602060006064601c6000865af161031b5761031b6103c7565b3d156103445760203d1015610332576103326103c7565b600160005114610344576103446103c7565b61035f565b60008060008087875af161035f5761035f610365565b50505050565b62461bcd60e51b600052600160e51b6020527c3466696c6c42617463685369676e65644552433732314f72646572733a6040527f206661696c656420746f207472616e73666572204554482e0000000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3666696c6c42617463685369676e65644552433732314f72646572733a6040527f206661696c656420746f207472616e736665722045524332302e000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3466696c6c42617463685369676e65644552433732314f72646572733a6040527f206661696c656420746f207769746864726177204554482e0000000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3666696c6c42617463685369676e65644552433732314f72646572733a6040527f20696e76616c696420636f6c6c656374696f6e7342797465732e000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c2d66696c6c42617463685369676e65644552433732314f72646572733a604052701037379037b93232b9103334b63632b21760791b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3266696c6c42617463685369676e65644552433732314f72646572733a60405275103330b4b632b2103a37903932b33ab7321022aa241760511b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c13696e76616c696420657263323020746f6b656e000000000000000000604052600060605260646000fd5b5050505050505050565b60006105f23447611cc4565b90508260006106008261079b565b90508060005260006103805260006103a05260006103c05261062182610c76565b82470361062a57005b8247111561064a57600080600080864703335af161004c5761004c610657565b610652610657565b6106b1565b62461bcd60e51b600052600160e51b6020527c3166696c6c42617463685369676e65644552433732314f726465723a20604052743330b4b632b2103a37903932b33ab7321022aa241760591b606052600060805260846000fd5b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000060003082036107695762461bcd60e51b600052600160e51b6020527c5464656c656761746543616c6c46696c6c42617463685369676e6564456040527f52433732314f726465723a206d7573742064656c656761746543616c6c2066726060527f6f6d20616e2065787465726e616c2065786368616e67652e0000000000000000608052600060a05260a46000fd5b508260006107768261079b565b9050806000528761038052866103a052856103c05261079482610c76565b60406103e0f35b60008060043580821a90600781901a906024354260a083901c63ffffffff1611156108225762461bcd60e51b600052600160e51b6020527c3c66696c6c42617463685369676e65644552433732314f726465723a206040527f6661696c656420746f20636865636b20666f72206c697374696e6754696d652e606052600060805260846000fd5b4263ffffffff8260a01c16116108945762461bcd60e51b600052600160e51b6020527c3b66696c6c42617463685369676e65644552433732314f726465723a206040527f6661696c656420746f20636865636b20666f722065787069727954696d652e00606052600060805260846000fd5b6001600160a01b0381166108fa5762461bcd60e51b600052600160e51b6020527c2f66696c6c42617463685369676e65644552433732314f726465723a206040527234b73b30b634b21032b93199182a37b5b2b71760691b606052600060805260846000fd5b506001600160a01b031692508261095e5762461bcd60e51b600052600160e51b6020527c2a66696c6c42617463685369676e65644552433732314f726465723a206040526d34b73b30b634b21036b0b5b2b91760911b606052600060805260846000fd5b610a0161096a8661168d565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000527f27b14c20196091d9cd90ca9c473d3ad1523b00ddf487a9b7452a8a119a16b98c6020527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c604052466060523060805261190160f01b60a05260a060002060a2528160c252604260a0209050919050565b93508160ff16600003610af8576000606081905260805260a0604081905284905260ff811660c05260643560e081905260843561010081905260016101206020604051602081039080840390855afa158015610a61573d6000803e3d6000fd5b505050602060405103516001600160a01b0316856001600160a01b031614610af15760405162461bcd60e51b815260206004820152603960248201527f66696c6c42617463685369676e65644552433732314f726465723a206661696c60448201527f656420746f2076616c6964617465207369676e61747572652e0000000000000060648201526084016100d6565b5050610c6e565b8160ff16600303610c1257631626ba7e60005283602052604080526041606052604060646080378060f81b60c052823b610b3457610b34610b68565b6020600060a5601c865afa610b4b57610b4b610bbb565b630b135d3f60e11b60005114610b6357610b63610bbb565b610c6e565b62461bcd60e51b600052600160e51b6020527c2a66696c6c42617463685369676e65644552433732314f726465723a206040526d34b73b30b634b21036b0b5b2b91760911b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3266696c6c42617463685369676e65644552433732314f726465723a206040527134b73b30b634b21039b4b3b730ba3ab9329760711b606052600060805260846000fd5b62461bcd60e51b6000908152600160e51b6020527c3266696c6c42617463685369676e65644552433732314f726465723a206040527534b73b30b634b21039b4b3b730ba3ab932aa3cb8329760511b6060526080819052608490fd5b505050919050565b6001600160a01b036004351660205260443560a01c60243560c01c60601b17604052604051610ca457336040525b6001600160a01b036024351660805261012060c0526323b872dd6101c0526020516101e05260405161020052600061024052600160f81b6102c0526020516102e052600560801b6103005260406102e0206102e05260006103605260006103e0526000610400526323b872dd610420523361044052600064ffffffffff60043560c81c166001600160a01b036044351660008060208603358601865b81811015611291576001600160a01b0381351660e05260208101356103005263ffffffff60801b6103005160401c166001600160a01b0319823516176103005160021a6103005160011a8115610dc15780821115610da057610da0611427565b6080821115610db157610db1611427565b60e0513b610dc157610dc161164f565b87610140528760008114610de35761ffff6103005160b01c1661032052610dea565b6000610320525b50610300516001600160a01b03166101808190528015610e185761ffff6103005160a01c1661034052610e1f565b6000610340525b506127106103405161032051011115610e3a57610e3a6113b6565b60006103005160001a60008114611052575b83156110425760018403935084841a838110610e6a57610e6a611427565b808c0160605260605160081c6102c05114610ecc576102405115610eab5761028051548d14610e9b57610e9b611480565b6102a05161028051556000610240525b60605160081c6102c05260406102c0206102805261028051549c508c6102a0525b600160ff606051161b61026052610260516102a0511661103c576040810260408801016001600160e01b0381351115610f0757610f076114d4565b60208101356102205260008060646101dc600060e0515af11561103a57600161024052610260516102a051176102a052803560a0526127106103205160a0510204610160526127106103405160a05102046101a0526101a051610160510160a051038a019950610160518b019a506101a0518401935061022051610100528b60008114610fda57610180518015610fb857600261012052600080516020611d228339815191526101c06000a1610fd4565b600161012052600080516020611d228339815191526101806000a15b50611032565b6101805180156110145760016101205261018051610140526101a05161016052600080516020611d228339815191526101806000a1611030565b600061012052600080516020611d228339815191526101406000a15b505b506001610360525b505b50610e4c565b6040830260408701019550611244565b83156112385760018403935084841a83811061107057611070611427565b808c0160605260605160081c6102c051146110d25761024051156110b15761028051548d146110a1576110a1611480565b6102a05161028051556000610240525b60605160081c6102c05260406102c0206102805261028051549c508c6102a0525b600160ff606051161b61026052610260516102a0511661123257602081026040880101356001600160a01b0381166102205260008060646101dc600060e0515af11561123057600161024052610260516102a051176102a0528060a01c60a0526127106103205160a0510204610160526127106103405160a05102046101a0526101a051610160510160a051038a019950610160518b019a506101a0518401935061022051610100528b600081146111d0576101805180156111ae57600261012052600080516020611d228339815191526101c06000a16111ca565b600161012052600080516020611d228339815191526101806000a15b50611228565b61018051801561120a5760016101205261018051610140526101a05161016052600080516020611d228339815191526101806000a1611226565b600061012052600080516020611d228339815191526101406000a15b505b506001610360525b505b50611052565b60208302604087010195505b50988101988015611288576103c05161018051146103805160805114166001811461127b57611276826101805161131c565b611286565b816104005101610400525b505b50505050610d40565b505061024051156112b957610280515485146112af576112af611480565b6102a05161028051555b80156112cb576112cb8160205161131c565b508015611305576103a0518214610380516080511416600181146112f8576112f3828461131c565b611303565b816103e051016103e0525b505b505050506103605161131957611319611536565b50565b60805173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81146113a0576080513b61134a5761134a61059e565b816104605282610480526020610480606461043c60006080515af1611371576113716115ed565b3d1561139b5760203d1015611388576113886115ed565b6001610480511461139b5761139b6115ed565b505050565b60008060008086865af161139b5761139b61158b565b62461bcd60e51b600052600160e51b6020527c4466696c6c42617463685369676e65644552433732314f726465723a206040527f746f74616c20666565732070657263656e7461676520657863656564732074686060526732903634b6b4ba1760c11b608052600060a05260a46000fd5b62461bcd60e51b600052600160e51b6020527c3066696c6c42617463685369676e65644552433732314f726465723a206040527334b73b30b634b2103334b63632b224b73232bc1760611b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c2b66696c6c42617463685369676e65644552433732314f726465723a206040526e3932b2b73a3930b73a1031b0b6361760891b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3b66696c6c42617463685369676e65644552433732314f726465723a206040527f6572633230546f6b656e416d6f756e742065786365656473206c696d69742e00606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c2c66696c6c42617463685369676e65644552433732314f726465723a206040526f37379037b93232b9103334b63632b21760811b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3366696c6c42617463685369676e65644552433732314f726465723a206040527f6661696c656420746f207472616e73666572204554482e000000000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3566696c6c42617463685369676e65644552433732314f726465723a206040527f6661696c656420746f207472616e736665722045524332302e00000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c14696e76616c69642065726337323120746f6b656e0000000000000000604052600060605260646000fd5b60006116988261173f565b6004356024356044356001600160a01b0383167f2d8cbbbc696e7292c3b5beb38e1363d34ff11beb8c3456c14cb938854597b9ed6000528060205263ffffffff8460a01c1660405263ffffffff8360a01c1660605264ffffffffff8460c81c166080526001600160a01b03831660a0526001600160a01b03821660c052806101205250505050600160821b6101405260406101202054610120526101406000209050919050565b600080600083602085033585015b80821015611912576001600160a01b038235168061176d5761176d61197e565b60208301358060011a80611783576117836119d6565b8160021a60108111828211171561179c5761179c611a2d565b508160001a6118195787156117b3576117b3611a86565b7f12ad29288fd70022f26997a9958d9eceb6e840ceaa79b72ea5945ba87e4d33b086528260208701526001600160c01b03821660408701526060860160208202604087018181843781832090925260808820885260209097019601945061174d92505050565b8761185b57600197508580156118355760009687209750611859565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47097505b505b7fb9f488d48cec782be9ecdb74330c9c6a33c236a8022d8a91a4e4df4e81b5162086528260208701526001600160c01b0382166040870152606086019250604081029150604085018281602086013783602083028501855b818110156118f2577f5f93394997caa49a9382d44a75e3ce6a460f32b39870464866ac994f8be97afe83526060832081526040909201916020016118b3565b50505060209182028420909352608086208652949094019301915061174d565b80821461192157611921611a86565b5050826000811461193d578260e0528160002061010052611977565b8161194a5761194a611a86565b8160002060e0527fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470610100525b5050505050565b62461bcd60e51b600052600160e51b6020527c2f66696c6c42617463685369676e65644552433732314f726465723a206040527234b73b30b634b21037333a20b2323932b9b99760691b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c2e66696c6c42617463685369676e65644552433732314f726465723a206040527134b73b30b634b21034ba32b6a1b7bab73a1760711b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3066696c6c42617463685369676e65644552433732314f726465723a206040527334b73b30b634b2103334b63632b221b7bab73a1760611b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3566696c6c42617463685369676e65644552433732314f726465723a206040527f696e76616c696420636f6c6c656374696f6e7342797465732e00000000000000606052600060805260846000fd5b60008060008060608587031215611afe57600080fd5b843567ffffffffffffffff80821115611b1657600080fd5b818701915087601f830112611b2a57600080fd5b813581811115611b3957600080fd5b8860208260051b8501011115611b4e57600080fd5b6020928301999098509187013596604001359550909350505050565b600060a08284031215611b7c57600080fd5b50919050565b60008083601f840112611b9457600080fd5b50813567ffffffffffffffff811115611bac57600080fd5b602083019150836020828501011115611bc457600080fd5b9250929050565b600080600060c08486031215611be057600080fd5b611bea8585611b6a565b925060a084013567ffffffffffffffff811115611c0657600080fd5b611c1286828701611b82565b9497909650939450505050565b80356001600160a01b0381168114611c3657600080fd5b919050565b6000806000806000806101208789031215611c5557600080fd5b611c5f8888611b6a565b9550611c6d60a08801611c1f565b9450611c7b60c08801611c1f565b9350611c8960e08801611c1f565b925061010087013567ffffffffffffffff811115611ca657600080fd5b611cb289828a01611b82565b979a9699509497509295939492505050565b81810381811115611ce557634e487b7160e01b600052601160045260246000fd5b92915050565b634e487b7160e01b600052603260045260246000fd5b6000823560be19833603018112611d1757600080fd5b919091019291505056fe9c248aa1a265aa616f707b979d57f4529bb63a4fc34dc7fc61fdddc18410f74ea26469706673582212207e6d7da2e62429583e7fb05fc6c74592fddb9eeaca0eda3b830e4aa3be0884c964736f6c63430008110033000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f

Deployed Bytecode

0x6080604052600436106100345760003560e01c8063149b8ce614610039578063a4d730411461004e578063dc055ecc14610061575b600080fd5b61004c610047366004611ae8565b610074565b005b61004c61005c366004611bcb565b6105e6565b61004c61006f366004611c3b565b6106b9565b826100df5760405162461bcd60e51b815260206004820152603060248201527f66696c6c42617463685369676e65644552433732314f72646572733a20696e7660448201526f30b634b2103830b930b6b2ba32b9399760811b60648201526084015b60405180910390fd5b60006100eb3447611cc4565b905060006001600160a01b038686600081811061010a5761010a611ceb565b905060200281019061011c9190611d01565b604001351690507f0000000000000000000000002d4fb6f3f9dc2ec67676be55d5301b2be21930327f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f60a086901c6001600160a01b038088169087166000808085156101b15761018d8630896102c4565b632e1a7d4d600052856020526000806024601c60008b5af16101b1576101b1610429565b63dc055ecc6040528461010052886101205283610140526101206101605260208d028e0195508d5b868110156102585780358f0160a08160603760c081013560208106156102015761020161048b565b80610180528060e083016101a037604060008261014401605c8e5af4801561023a5760019450600051870196506020518601955061024d565b8e60001a1561024d573d6000803e3d6000fd5b5050506020016101d9565b50821561026a5761026a838a876102c4565b811561027b5761027b8285876102c4565b80610288576102886104ed565b50505050505083470361029757005b834711156102b757600080600080874703335af161004c5761004c610543565b6102bf610543565b6105dc565b8073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee811461034957813b6102ee576102ee61059e565b6323b872dd600052336020528260405283606052602060006064601c6000865af161031b5761031b6103c7565b3d156103445760203d1015610332576103326103c7565b600160005114610344576103446103c7565b61035f565b60008060008087875af161035f5761035f610365565b50505050565b62461bcd60e51b600052600160e51b6020527c3466696c6c42617463685369676e65644552433732314f72646572733a6040527f206661696c656420746f207472616e73666572204554482e0000000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3666696c6c42617463685369676e65644552433732314f72646572733a6040527f206661696c656420746f207472616e736665722045524332302e000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3466696c6c42617463685369676e65644552433732314f72646572733a6040527f206661696c656420746f207769746864726177204554482e0000000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3666696c6c42617463685369676e65644552433732314f72646572733a6040527f20696e76616c696420636f6c6c656374696f6e7342797465732e000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c2d66696c6c42617463685369676e65644552433732314f72646572733a604052701037379037b93232b9103334b63632b21760791b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3266696c6c42617463685369676e65644552433732314f72646572733a60405275103330b4b632b2103a37903932b33ab7321022aa241760511b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c13696e76616c696420657263323020746f6b656e000000000000000000604052600060605260646000fd5b5050505050505050565b60006105f23447611cc4565b90508260006106008261079b565b90508060005260006103805260006103a05260006103c05261062182610c76565b82470361062a57005b8247111561064a57600080600080864703335af161004c5761004c610657565b610652610657565b6106b1565b62461bcd60e51b600052600160e51b6020527c3166696c6c42617463685369676e65644552433732314f726465723a20604052743330b4b632b2103a37903932b33ab7321022aa241760591b606052600060805260846000fd5b505050505050565b7f0000000000000000000000002d4fb6f3f9dc2ec67676be55d5301b2be219303260003082036107695762461bcd60e51b600052600160e51b6020527c5464656c656761746543616c6c46696c6c42617463685369676e6564456040527f52433732314f726465723a206d7573742064656c656761746543616c6c2066726060527f6f6d20616e2065787465726e616c2065786368616e67652e0000000000000000608052600060a05260a46000fd5b508260006107768261079b565b9050806000528761038052866103a052856103c05261079482610c76565b60406103e0f35b60008060043580821a90600781901a906024354260a083901c63ffffffff1611156108225762461bcd60e51b600052600160e51b6020527c3c66696c6c42617463685369676e65644552433732314f726465723a206040527f6661696c656420746f20636865636b20666f72206c697374696e6754696d652e606052600060805260846000fd5b4263ffffffff8260a01c16116108945762461bcd60e51b600052600160e51b6020527c3b66696c6c42617463685369676e65644552433732314f726465723a206040527f6661696c656420746f20636865636b20666f722065787069727954696d652e00606052600060805260846000fd5b6001600160a01b0381166108fa5762461bcd60e51b600052600160e51b6020527c2f66696c6c42617463685369676e65644552433732314f726465723a206040527234b73b30b634b21032b93199182a37b5b2b71760691b606052600060805260846000fd5b506001600160a01b031692508261095e5762461bcd60e51b600052600160e51b6020527c2a66696c6c42617463685369676e65644552433732314f726465723a206040526d34b73b30b634b21036b0b5b2b91760911b606052600060805260846000fd5b610a0161096a8661168d565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6000527f27b14c20196091d9cd90ca9c473d3ad1523b00ddf487a9b7452a8a119a16b98c6020527f06c015bd22b4c69690933c1058878ebdfef31f9aaae40bbe86d8a09fe1b2972c604052466060523060805261190160f01b60a05260a060002060a2528160c252604260a0209050919050565b93508160ff16600003610af8576000606081905260805260a0604081905284905260ff811660c05260643560e081905260843561010081905260016101206020604051602081039080840390855afa158015610a61573d6000803e3d6000fd5b505050602060405103516001600160a01b0316856001600160a01b031614610af15760405162461bcd60e51b815260206004820152603960248201527f66696c6c42617463685369676e65644552433732314f726465723a206661696c60448201527f656420746f2076616c6964617465207369676e61747572652e0000000000000060648201526084016100d6565b5050610c6e565b8160ff16600303610c1257631626ba7e60005283602052604080526041606052604060646080378060f81b60c052823b610b3457610b34610b68565b6020600060a5601c865afa610b4b57610b4b610bbb565b630b135d3f60e11b60005114610b6357610b63610bbb565b610c6e565b62461bcd60e51b600052600160e51b6020527c2a66696c6c42617463685369676e65644552433732314f726465723a206040526d34b73b30b634b21036b0b5b2b91760911b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3266696c6c42617463685369676e65644552433732314f726465723a206040527134b73b30b634b21039b4b3b730ba3ab9329760711b606052600060805260846000fd5b62461bcd60e51b6000908152600160e51b6020527c3266696c6c42617463685369676e65644552433732314f726465723a206040527534b73b30b634b21039b4b3b730ba3ab932aa3cb8329760511b6060526080819052608490fd5b505050919050565b6001600160a01b036004351660205260443560a01c60243560c01c60601b17604052604051610ca457336040525b6001600160a01b036024351660805261012060c0526323b872dd6101c0526020516101e05260405161020052600061024052600160f81b6102c0526020516102e052600560801b6103005260406102e0206102e05260006103605260006103e0526000610400526323b872dd610420523361044052600064ffffffffff60043560c81c166001600160a01b036044351660008060208603358601865b81811015611291576001600160a01b0381351660e05260208101356103005263ffffffff60801b6103005160401c166001600160a01b0319823516176103005160021a6103005160011a8115610dc15780821115610da057610da0611427565b6080821115610db157610db1611427565b60e0513b610dc157610dc161164f565b87610140528760008114610de35761ffff6103005160b01c1661032052610dea565b6000610320525b50610300516001600160a01b03166101808190528015610e185761ffff6103005160a01c1661034052610e1f565b6000610340525b506127106103405161032051011115610e3a57610e3a6113b6565b60006103005160001a60008114611052575b83156110425760018403935084841a838110610e6a57610e6a611427565b808c0160605260605160081c6102c05114610ecc576102405115610eab5761028051548d14610e9b57610e9b611480565b6102a05161028051556000610240525b60605160081c6102c05260406102c0206102805261028051549c508c6102a0525b600160ff606051161b61026052610260516102a0511661103c576040810260408801016001600160e01b0381351115610f0757610f076114d4565b60208101356102205260008060646101dc600060e0515af11561103a57600161024052610260516102a051176102a052803560a0526127106103205160a0510204610160526127106103405160a05102046101a0526101a051610160510160a051038a019950610160518b019a506101a0518401935061022051610100528b60008114610fda57610180518015610fb857600261012052600080516020611d228339815191526101c06000a1610fd4565b600161012052600080516020611d228339815191526101806000a15b50611032565b6101805180156110145760016101205261018051610140526101a05161016052600080516020611d228339815191526101806000a1611030565b600061012052600080516020611d228339815191526101406000a15b505b506001610360525b505b50610e4c565b6040830260408701019550611244565b83156112385760018403935084841a83811061107057611070611427565b808c0160605260605160081c6102c051146110d25761024051156110b15761028051548d146110a1576110a1611480565b6102a05161028051556000610240525b60605160081c6102c05260406102c0206102805261028051549c508c6102a0525b600160ff606051161b61026052610260516102a0511661123257602081026040880101356001600160a01b0381166102205260008060646101dc600060e0515af11561123057600161024052610260516102a051176102a0528060a01c60a0526127106103205160a0510204610160526127106103405160a05102046101a0526101a051610160510160a051038a019950610160518b019a506101a0518401935061022051610100528b600081146111d0576101805180156111ae57600261012052600080516020611d228339815191526101c06000a16111ca565b600161012052600080516020611d228339815191526101806000a15b50611228565b61018051801561120a5760016101205261018051610140526101a05161016052600080516020611d228339815191526101806000a1611226565b600061012052600080516020611d228339815191526101406000a15b505b506001610360525b505b50611052565b60208302604087010195505b50988101988015611288576103c05161018051146103805160805114166001811461127b57611276826101805161131c565b611286565b816104005101610400525b505b50505050610d40565b505061024051156112b957610280515485146112af576112af611480565b6102a05161028051555b80156112cb576112cb8160205161131c565b508015611305576103a0518214610380516080511416600181146112f8576112f3828461131c565b611303565b816103e051016103e0525b505b505050506103605161131957611319611536565b50565b60805173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81146113a0576080513b61134a5761134a61059e565b816104605282610480526020610480606461043c60006080515af1611371576113716115ed565b3d1561139b5760203d1015611388576113886115ed565b6001610480511461139b5761139b6115ed565b505050565b60008060008086865af161139b5761139b61158b565b62461bcd60e51b600052600160e51b6020527c4466696c6c42617463685369676e65644552433732314f726465723a206040527f746f74616c20666565732070657263656e7461676520657863656564732074686060526732903634b6b4ba1760c11b608052600060a05260a46000fd5b62461bcd60e51b600052600160e51b6020527c3066696c6c42617463685369676e65644552433732314f726465723a206040527334b73b30b634b2103334b63632b224b73232bc1760611b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c2b66696c6c42617463685369676e65644552433732314f726465723a206040526e3932b2b73a3930b73a1031b0b6361760891b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3b66696c6c42617463685369676e65644552433732314f726465723a206040527f6572633230546f6b656e416d6f756e742065786365656473206c696d69742e00606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c2c66696c6c42617463685369676e65644552433732314f726465723a206040526f37379037b93232b9103334b63632b21760811b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3366696c6c42617463685369676e65644552433732314f726465723a206040527f6661696c656420746f207472616e73666572204554482e000000000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3566696c6c42617463685369676e65644552433732314f726465723a206040527f6661696c656420746f207472616e736665722045524332302e00000000000000606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c14696e76616c69642065726337323120746f6b656e0000000000000000604052600060605260646000fd5b60006116988261173f565b6004356024356044356001600160a01b0383167f2d8cbbbc696e7292c3b5beb38e1363d34ff11beb8c3456c14cb938854597b9ed6000528060205263ffffffff8460a01c1660405263ffffffff8360a01c1660605264ffffffffff8460c81c166080526001600160a01b03831660a0526001600160a01b03821660c052806101205250505050600160821b6101405260406101202054610120526101406000209050919050565b600080600083602085033585015b80821015611912576001600160a01b038235168061176d5761176d61197e565b60208301358060011a80611783576117836119d6565b8160021a60108111828211171561179c5761179c611a2d565b508160001a6118195787156117b3576117b3611a86565b7f12ad29288fd70022f26997a9958d9eceb6e840ceaa79b72ea5945ba87e4d33b086528260208701526001600160c01b03821660408701526060860160208202604087018181843781832090925260808820885260209097019601945061174d92505050565b8761185b57600197508580156118355760009687209750611859565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47097505b505b7fb9f488d48cec782be9ecdb74330c9c6a33c236a8022d8a91a4e4df4e81b5162086528260208701526001600160c01b0382166040870152606086019250604081029150604085018281602086013783602083028501855b818110156118f2577f5f93394997caa49a9382d44a75e3ce6a460f32b39870464866ac994f8be97afe83526060832081526040909201916020016118b3565b50505060209182028420909352608086208652949094019301915061174d565b80821461192157611921611a86565b5050826000811461193d578260e0528160002061010052611977565b8161194a5761194a611a86565b8160002060e0527fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470610100525b5050505050565b62461bcd60e51b600052600160e51b6020527c2f66696c6c42617463685369676e65644552433732314f726465723a206040527234b73b30b634b21037333a20b2323932b9b99760691b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c2e66696c6c42617463685369676e65644552433732314f726465723a206040527134b73b30b634b21034ba32b6a1b7bab73a1760711b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3066696c6c42617463685369676e65644552433732314f726465723a206040527334b73b30b634b2103334b63632b221b7bab73a1760611b606052600060805260846000fd5b62461bcd60e51b600052600160e51b6020527c3566696c6c42617463685369676e65644552433732314f726465723a206040527f696e76616c696420636f6c6c656374696f6e7342797465732e00000000000000606052600060805260846000fd5b60008060008060608587031215611afe57600080fd5b843567ffffffffffffffff80821115611b1657600080fd5b818701915087601f830112611b2a57600080fd5b813581811115611b3957600080fd5b8860208260051b8501011115611b4e57600080fd5b6020928301999098509187013596604001359550909350505050565b600060a08284031215611b7c57600080fd5b50919050565b60008083601f840112611b9457600080fd5b50813567ffffffffffffffff811115611bac57600080fd5b602083019150836020828501011115611bc457600080fd5b9250929050565b600080600060c08486031215611be057600080fd5b611bea8585611b6a565b925060a084013567ffffffffffffffff811115611c0657600080fd5b611c1286828701611b82565b9497909650939450505050565b80356001600160a01b0381168114611c3657600080fd5b919050565b6000806000806000806101208789031215611c5557600080fd5b611c5f8888611b6a565b9550611c6d60a08801611c1f565b9450611c7b60c08801611c1f565b9350611c8960e08801611c1f565b925061010087013567ffffffffffffffff811115611ca657600080fd5b611cb289828a01611b82565b979a9699509497509295939492505050565b81810381811115611ce557634e487b7160e01b600052601160045260246000fd5b92915050565b634e487b7160e01b600052603260045260246000fd5b6000823560be19833603018112611d1757600080fd5b919091019291505056fe9c248aa1a265aa616f707b979d57f4529bb63a4fc34dc7fc61fdddc18410f74ea26469706673582212207e6d7da2e62429583e7fb05fc6c74592fddb9eeaca0eda3b830e4aa3be0884c964736f6c63430008110033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f

-----Decoded View---------------
Arg [0] : weth (address): 0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f


Block Transaction Gas Used Reward
view all blocks sequenced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.