Contract 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde3 3

Txn Hash Method
Block
From
To
Value [Txn Fee]
0x88c11301be6a1b3b31bcb7ce153e3087e212623998ef717e643a7a4c3433c849Cancel Order229722392022-11-29 1:27:213 hrs 5 mins ago0xf2d850d518e4e165c17e6a9c7aa1ffdb00ca0244 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.00172381 27.5
0xb5ae7dd0beafd091cbcb3e70289d17536ad34a990f1c106429f9c8165d44d43eCancel Order229716762022-11-29 1:08:203 hrs 24 mins ago0x53517ff84cb2b4b8345543af5992a3a53e099e8b IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018287225 27.5
0x53376d7faaaa43070afc882b4d7f6976e44e422b58b1573ba203c0664e8295ddCancel Order229716532022-11-29 1:07:343 hrs 25 mins ago0x53517ff84cb2b4b8345543af5992a3a53e099e8b IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018283925 27.5
0x9070ac8751d1ce4a1368fa3775d73935f356443e151899d322b922de82913895Cancel Order229716522022-11-29 1:07:323 hrs 25 mins ago0x53517ff84cb2b4b8345543af5992a3a53e099e8b IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018283925 27.5
0x51d66dd8524ad3998802519da28f976a6a91fdfa3d7c615e9b422e915973b2c4Cancel Order229715672022-11-29 1:04:423 hrs 28 mins ago0x53517ff84cb2b4b8345543af5992a3a53e099e8b IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018280625 27.5
0xa892db0e2341eaece6b44adb5653ddfb34587a7448752984199af180159308beCancel Order229715662022-11-29 1:04:403 hrs 28 mins ago0x53517ff84cb2b4b8345543af5992a3a53e099e8b IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018287225 27.5
0xc31c0a5d58adfb5de5ab58d88b42ea14a92994fa8be70101a5a27e43109f4824Fill Order229704802022-11-29 0:27:504 hrs 4 mins ago0x8058337cf6fa1132c0fb8421c37a4b8d301d0d3f IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde31.79 AVAX0.005864595 27.5
0x89cb90069adbbfc6046097c85a5dd3141a5ba9cc73d6acfbd79eb3cb17484e43Fill Order229704312022-11-29 0:26:104 hrs 6 mins ago0xbcbf76d9737facdf17d22b27d5e6ac5dced59312 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde31.25 AVAX0.0062982425 27.5
0xc04928faf95a83062ac3a191602ee6c04e2f2f5e48da60ea86a0787875123448Cancel Order229696982022-11-29 0:01:414 hrs 31 mins ago0xa6dce92c19784b1e8b1cf559b9266a43e6d4c813 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0017314825 27.5
0x6f003b34642df0b5db964fa3ae1d8d10a27c33da7448e726148c1df770c7209cCancel Order229693762022-11-28 23:50:494 hrs 41 mins ago0xa6dce92c19784b1e8b1cf559b9266a43e6d4c813 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.00172414 27.5
0x49d7ee9505b75e1e63f336878b022945eeaba6a005099b12b66163828071c991Cancel Order229692422022-11-28 23:46:184 hrs 46 mins ago0x64e09f9f0bf2e8efc5d0e60413cce3a68dd643fc IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018280625 27.5
0x2f2b7e21206ab7051d5524b140a410bf2e16deb6077316d04b5e875e4594c668Cancel Order229692162022-11-28 23:45:344 hrs 47 mins ago0x64e09f9f0bf2e8efc5d0e60413cce3a68dd643fc IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018280625 27.5
0xce231584bee84c59639130d84cebaa7a6c9b09fcd3c05ca46e7c4a65215d5330Fill Order229690772022-11-28 23:40:414 hrs 52 mins ago0x760d6ed654e0d753779cdfd5214dc9f8c7e46552 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde31.6 AVAX0.004574295 27.5
0x7f5c6ac2e9b211498a2520f15234f2b1676cfcdd5bfc117cceed360aeb7ab236Cancel Order229690472022-11-28 23:39:414 hrs 53 mins ago0x64e09f9f0bf2e8efc5d0e60413cce3a68dd643fc IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018283925 27.5
0x906e843608e11b33f2821ccc8c24dc7b9fbc6eeb1abfef5646a5fc6e9dffb3feCancel Order229689892022-11-28 23:37:444 hrs 55 mins ago0x64e09f9f0bf2e8efc5d0e60413cce3a68dd643fc IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018277325 27.5
0xcf905c1957a475c1b4ddfd21db46c96fe25a93ff0dcef0a97c167857283803a6Cancel Order229689412022-11-28 23:36:064 hrs 56 mins ago0x64e09f9f0bf2e8efc5d0e60413cce3a68dd643fc IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018280625 27.5
0x1ac63da3d16e32694033d9084224a584629a51a45c9b06f1fd433c54cf5266faFill Order229681062022-11-28 23:07:185 hrs 25 mins ago0x93fc1eeab6c4cc7d381f12c434539e0925f6f6e4 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.00579645 27.5
0x5bec04664e2462556f02116a0b7bbf97f091362e4a889c87f7425106c2d52383Fill Order229680302022-11-28 23:04:475 hrs 27 mins ago0x93fc1eeab6c4cc7d381f12c434539e0925f6f6e4 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.005328565 27.5
0xc912c848e2f5d4663d2d45143daaace7e86f12f250fc82c7d0e995751f921b86Fill Order229680022022-11-28 23:03:505 hrs 28 mins ago0x93fc1eeab6c4cc7d381f12c434539e0925f6f6e4 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.005798815 27.5
0xe0708ad6ee527078c8e6dab8340b65c79678821dba3a15473852861174f73121Cancel Order229675212022-11-28 22:47:185 hrs 45 mins ago0xa087d8415a3e6926c4df3656a163d3836c2dc786 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018280625 27.5
0x7bd113d2c981c0ee4be9ac41310fbdf71d505ea071a0dc94d4b9489aedc82d69Cancel Order229672742022-11-28 22:38:545 hrs 53 mins ago0x391374b8b57b3054bd60d751a55974cdad851fe6 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.0018277325 27.5
0xa8ae222661ee16a42d7845d371526bb8862472a30ed3e735f1133c51ce57d8ebFill Order229672682022-11-28 22:38:425 hrs 54 mins ago0x34b1ba641c98e0de455209d7a8ae5d5d6573f2a9 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde31.5 AVAX0.00465668527.5
0xa9febafb6082bca1f0bd229bf9e921b3fb6906785974778501eb8f06036af7e7Fill Order229672492022-11-28 22:38:045 hrs 54 mins ago0x34b1ba641c98e0de455209d7a8ae5d5d6573f2a9 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde31.4 AVAX0.00512693527.5
0xfcd795b41a25bbd148afd2a9a9525ef11f63aedb011249f7c7bdb448f29e839fCancel Order229671332022-11-28 22:34:015 hrs 58 mins ago0x553a2c0c2ad990cb28706ecf6e79b4c246a76fe1 IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.001836065 27.5
0xb1542513799f18fe89794eb5d787932e324bce0037ac81781cd2f32fc3977c83Cancel Order229667322022-11-28 22:20:186 hrs 12 mins ago0x22bf820f942913223b88b80d715f5fcd229683fe IN  0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30 AVAX0.00172348 27.5
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x9f171ece6d67d022501d9297c05dd61e56825c551.86 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30xb090fc5d0c06804dfbf06efb59ce1f291f13162a0.1 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x1249cae9fabbdc18f5368355ac1febd06b4263740.04 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0x3fb1d0a5be1f60c44775b6fef5c8a5dc41253a2b 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde32 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x925d09963efa7ffb0ab52139e0b2595ca7421f8f1.86 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30xb090fc5d0c06804dfbf06efb59ce1f291f13162a0.1 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x1249cae9fabbdc18f5368355ac1febd06b4263740.04 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0x3fb1d0a5be1f60c44775b6fef5c8a5dc41253a2b 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde32 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x925d09963efa7ffb0ab52139e0b2595ca7421f8f1.86 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30xb090fc5d0c06804dfbf06efb59ce1f291f13162a0.1 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x1249cae9fabbdc18f5368355ac1febd06b4263740.04 AVAX
0xca7ea417af216604c2401b6ba007524c554c8b23f9ee60eff2d5e522a44e6643229720192022-11-29 1:19:553 hrs 12 mins ago 0x3fb1d0a5be1f60c44775b6fef5c8a5dc41253a2b 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde32 AVAX
0x0f4f56040458a88abe9ae315d4a501f5b2697153d6c6bb16602fbc5fe0b84cae229711832022-11-29 0:51:473 hrs 40 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30xa8fadd3315d2b10d6710554cca6a06bc42d6d77a0.4368 AVAX
0x0f4f56040458a88abe9ae315d4a501f5b2697153d6c6bb16602fbc5fe0b84cae229711832022-11-29 0:51:473 hrs 40 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x66c5fb50df8181fc0af155528807a3ac850bae7a0.0336 AVAX
0x0f4f56040458a88abe9ae315d4a501f5b2697153d6c6bb16602fbc5fe0b84cae229711832022-11-29 0:51:473 hrs 40 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x1249cae9fabbdc18f5368355ac1febd06b4263740.0096 AVAX
0x0f4f56040458a88abe9ae315d4a501f5b2697153d6c6bb16602fbc5fe0b84cae229711832022-11-29 0:51:473 hrs 40 mins ago 0x3fb1d0a5be1f60c44775b6fef5c8a5dc41253a2b 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30.48 AVAX
0x0f4f56040458a88abe9ae315d4a501f5b2697153d6c6bb16602fbc5fe0b84cae229711832022-11-29 0:51:473 hrs 40 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30xa8fadd3315d2b10d6710554cca6a06bc42d6d77a0.4095 AVAX
0x0f4f56040458a88abe9ae315d4a501f5b2697153d6c6bb16602fbc5fe0b84cae229711832022-11-29 0:51:473 hrs 40 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x66c5fb50df8181fc0af155528807a3ac850bae7a0.0315 AVAX
0x0f4f56040458a88abe9ae315d4a501f5b2697153d6c6bb16602fbc5fe0b84cae229711832022-11-29 0:51:473 hrs 40 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x1249cae9fabbdc18f5368355ac1febd06b4263740.009 AVAX
0x0f4f56040458a88abe9ae315d4a501f5b2697153d6c6bb16602fbc5fe0b84cae229711832022-11-29 0:51:473 hrs 40 mins ago 0x3fb1d0a5be1f60c44775b6fef5c8a5dc41253a2b 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30.45 AVAX
0x1f0a1679cdff193cea1b878af0dd6b7121f35502c4c062fe1077211e434dc018229704992022-11-29 0:28:284 hrs 4 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30xa449dbe957ae86b7734af1ccf60614c29f7b44c11.767 AVAX
0x1f0a1679cdff193cea1b878af0dd6b7121f35502c4c062fe1077211e434dc018229704992022-11-29 0:28:284 hrs 4 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30xb090fc5d0c06804dfbf06efb59ce1f291f13162a0.095 AVAX
0x1f0a1679cdff193cea1b878af0dd6b7121f35502c4c062fe1077211e434dc018229704992022-11-29 0:28:284 hrs 4 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30x1249cae9fabbdc18f5368355ac1febd06b4263740.038 AVAX
0x1f0a1679cdff193cea1b878af0dd6b7121f35502c4c062fe1077211e434dc018229704992022-11-29 0:28:284 hrs 4 mins ago 0x3fb1d0a5be1f60c44775b6fef5c8a5dc41253a2b 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde31.9 AVAX
0x1f0a1679cdff193cea1b878af0dd6b7121f35502c4c062fe1077211e434dc018229704992022-11-29 0:28:284 hrs 4 mins ago 0xbf6bfe5d6b86308cf3b7f147dd03ef11f80bfde30xdd60008f599b5e86ff4c28cbc2a1d2acf1b2afed1.767 AVAX
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
NiftyProtocol

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 21 : NiftyProtocol.sol
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./Refundable.sol";
import "./ExchangeCore.sol";

contract NiftyProtocol is
    Ownable,
    Refundable,
    ExchangeCore
{
    string public name = "Nifty Protocol";

    constructor (uint256 chainId) LibEIP712ExchangeDomain(chainId) {}
    
    /// @dev Fills the input order.
    /// @param order Order struct containing order specifications.
    /// @param signature Proof that order has been created by maker.
    /// @return fulfilled boolean
    function fillOrder(
        LibOrder.Order memory order,
        bytes memory signature,
        bytes32 marketplaceIdentifier
    )
        override
        external
        payable
        refundFinalBalanceNoReentry
        returns (bool fulfilled)
    {
        return _fillOrder(
            order,
            signature,
            msg.sender,
            marketplaceIdentifier
        );
    }

    /// @dev Fills the input order.
    /// @param order Order struct containing order specifications.
    /// @param signature Proof that order has been created by maker.
    /// @param takerAddress address to fulfill the order for / gift.
    /// @return fulfilled boolean
    function fillOrderFor(
        LibOrder.Order memory order,
        bytes memory signature,
        bytes32 marketplaceIdentifier,
        address takerAddress
    )
        override
        external
        payable
        refundFinalBalanceNoReentry
        returns (bool fulfilled)
    {
        return _fillOrder(
            order,
            signature,
            takerAddress,
            marketplaceIdentifier
        );
    }

    /// @dev After calling, the order can not be filled anymore.
    /// @param order Order struct containing order specifications.
    function cancelOrder(LibOrder.Order memory order)
        override
        external
    {
        _cancelOrder(order);
    }

    /// @dev Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch
    ///      and senderAddress equal to msg.sender (or null address if msg.sender == makerAddress).
    /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled.
    function cancelOrdersUpTo(uint256 targetOrderEpoch)
        override
        external
    {
        address makerAddress = msg.sender;
        // orderEpoch is initialized to 0, so to cancelUpTo we need salt + 1
        uint256 newOrderEpoch = targetOrderEpoch + 1;
        uint256 oldOrderEpoch = orderEpoch[makerAddress];

        // Ensure orderEpoch is monotonically increasing
        if (newOrderEpoch <= oldOrderEpoch) {
            revert('EXCHANGE: order epoch error');
        }

        // Update orderEpoch
        orderEpoch[makerAddress] = newOrderEpoch;
        emit CancelUpTo(
            makerAddress,
            newOrderEpoch
        );
    }

    /// @dev Gets information about an order: status, hash, and amount filled.
    /// @param order Order to gather information on.
    /// @return orderInfo Information about the order and its state.
    ///         See LibOrder.OrderInfo for a complete description.
    function getOrderInfo(LibOrder.Order memory order)
        override
        public
        view
        returns (LibOrder.OrderInfo memory orderInfo)
    {
        return _getOrderInfo(order);
    }

    function returnAllETHToOwner() external payable onlyOwner {
        payable(msg.sender).transfer(address(this).balance);
    }

    function returnERC20ToOwner(address ERC20Token) external payable onlyOwner {
        IERC20 CustomToken = IERC20(ERC20Token);
        CustomToken.transferFrom(address(this), msg.sender, CustomToken.balanceOf(address(this)));
    }

    receive() external payable {}
}

File 2 of 21 : LibOrder.sol
pragma solidity ^0.8.4;

import "./LibEIP712.sol";


library LibOrder {

    using LibOrder for Order;

    // Hash for the EIP712 Order Schema:
    // keccak256(abi.encodePacked(
    //     "Order(",
    //     "address makerAddress,",
    //     "address takerAddress,",
    //     "address royaltiesAddress,",
    //     "address senderAddress,",
    //     "uint256 makerAssetAmount,",
    //     "uint256 takerAssetAmount,",
    //     "uint256 royaltiesAmount,",
    //     "uint256 expirationTimeSeconds,",
    //     "uint256 salt,",
    //     "bytes makerAssetData,",
    //     "bytes takerAssetData",
    //     ")"
    // ))
    bytes32 constant internal _EIP712_ORDER_SCHEMA_HASH =
        0x85eeee70c9e228559a0ea5492e9915b70dab1efedd40807802f996020d88dc2e;

    // A valid order remains fillable until it is expired, fully filled, or cancelled.
    // An order's status is unaffected by external factors, like account balances.
    enum OrderStatus {
        INVALID,                     // Default value
        INVALID_MAKER_ASSET_AMOUNT,  // Order does not have a valid maker asset amount
        INVALID_TAKER_ASSET_AMOUNT,  // Order does not have a valid taker asset amount
        INVALID_ROYALTIES,           // Order does not have a valid royalties
        FILLABLE,                    // Order is fillable
        EXPIRED,                     // Order has already expired
        FILLED,                      // Order is fully filled
        CANCELLED                    // Order has been cancelled
    }

    enum OrderType {
        INVALID,                     // Default value
        LIST,
        OFFER,
        SWAP
    }

    // solhint-disable max-line-length
    /// @dev Canonical order structure.
    struct Order {
        address makerAddress;           // Address that created the order.
        address takerAddress;           // Address that is allowed to fill the order. If set to 0, any address is allowed to fill the order.
        address royaltiesAddress;       // Address that will recieve fees when order is filled.
        address senderAddress;          // Address that is allowed to call Exchange contract methods that affect this order. If set to 0, any address is allowed to call these methods.
        uint256 makerAssetAmount;       // Amount of makerAsset being offered by maker. Must be greater than 0.
        uint256 takerAssetAmount;       // Amount of takerAsset being bid on by maker. Must be greater than 0.
        uint256 royaltiesAmount;        // Fee paid to royaltiesAddress when order is filled.
        uint256 expirationTimeSeconds;  // Timestamp in seconds at which order expires.
        uint256 salt;                   // Arbitrary number to facilitate uniqueness of the order's hash.
        bytes makerAssetData;           // Encoded data that can be decoded by a specified proxy contract when transferring makerAsset. The leading bytes4 references the id of the asset proxy.
        bytes takerAssetData;           // Encoded data that can be decoded by a specified proxy contract when transferring takerAsset. The leading bytes4 references the id of the asset proxy.
    }
    // solhint-enable max-line-length

    /// @dev Order information returned by `getOrderInfo()`.
    struct OrderInfo {
        OrderStatus orderStatus;              // Status that describes order's validity and fillability.
        OrderType orderType;                  // type that describes order's side.
        bytes32 orderHash;                    // EIP712 typed data hash of the order (see LibOrder.getTypedDataHash).
        bool filled;                          // order has already been filled.
    }

    /// @dev Calculates the EIP712 typed data hash of an order with a given domain separator.
    /// @param order The order structure.
    /// @return orderHash EIP712 typed data hash of the order.
    function getTypedDataHash(Order memory order, bytes32 eip712ExchangeDomainHash)
        internal
        pure
        returns (bytes32 orderHash)
    {
        orderHash = LibEIP712.hashMessage(
            eip712ExchangeDomainHash,
            order.getStructHash()
        );
        return orderHash;
    }

    /// @dev Calculates EIP712 hash of the order struct.
    /// @param order The order structure.
    /// @return result EIP712 hash of the order struct.
    function getStructHash(Order memory order)
        internal
        pure
        returns (bytes32 result)
    {
        bytes32 schemaHash = _EIP712_ORDER_SCHEMA_HASH;
        bytes memory makerAssetData = order.makerAssetData;
        bytes memory takerAssetData = order.takerAssetData;

        // Assembly for more efficiently computing:
        // keccak256(abi.encodePacked(
        //     EIP712_ORDER_SCHEMA_HASH,
        //     uint256(order.makerAddress),
        //     uint256(order.takerAddress),
        //     uint256(order.royaltiesAddress),
        //     uint256(order.senderAddress),
        //     order.makerAssetAmount,
        //     order.takerAssetAmount,
        //     order.royaltiesAmount,
        //     order.expirationTimeSeconds,
        //     order.salt,
        //     keccak256(order.makerAssetData),
        //     keccak256(order.takerAssetData)
        // ));

        assembly {
            // Assert order offset (this is an internal error that should never be triggered)
            if lt(order, 32) {
                invalid()
            }

            // Calculate memory addresses that will be swapped out before hashing
            let pos1 := sub(order, 32)
            let pos2 := add(order, 288)
            let pos3 := add(order, 320)

            // Backup
            let temp1 := mload(pos1)
            let temp2 := mload(pos2)
            let temp3 := mload(pos3)

            // Hash in place
            mstore(pos1, schemaHash)
            mstore(pos2, keccak256(add(makerAssetData, 32), mload(makerAssetData)))        // store hash of makerAssetData
            mstore(pos3, keccak256(add(takerAssetData, 32), mload(takerAssetData)))        // store hash of takerAssetData
            result := keccak256(pos1, 384)

            // Restore
            mstore(pos1, temp1)
            mstore(pos2, temp2)
            mstore(pos3, temp3)
        }
        return result;
    }
}

File 3 of 21 : LibEIP712.sol
pragma solidity ^0.8.4;


library LibEIP712 {

    // Hash of the EIP712 Domain Separator Schema
    // keccak256(abi.encodePacked(
    //     "EIP712Domain(",
    //     "string name,",
    //     "string version,",
    //     "uint256 chainId,",
    //     "address verifyingContract",
    //     ")"
    // ))
    bytes32 constant internal SCHEMA_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;

    /// @dev Calculates a EIP712 domain separator.
    /// @param name The EIP712 domain name.
    /// @param version The EIP712 domain version.
    /// @param verifyingContract The EIP712 verifying contract.
    /// @return result EIP712 domain separator.
    function hashDomain(
        string memory name,
        string memory version,
        uint256 chainId,
        address verifyingContract
    )
        internal
        pure
        returns (bytes32 result)
    {
        bytes32 schemaHash = SCHEMA_HASH;

        // Assembly for more efficient computing:
        // keccak256(abi.encodePacked(
        //     SCHEMA_HASH,
        //     keccak256(bytes(name)),
        //     keccak256(bytes(version)),
        //     chainId,
        //     uint256(verifyingContract)
        // ))

        assembly {
            // Calculate hashes of dynamic data
            let nameHash := keccak256(add(name, 32), mload(name))
            let versionHash := keccak256(add(version, 32), mload(version))

            // Load free memory pointer
            let memPtr := mload(64)

            // Store params in memory
            mstore(memPtr, schemaHash)
            mstore(add(memPtr, 32), nameHash)
            mstore(add(memPtr, 64), versionHash)
            mstore(add(memPtr, 96), chainId)
            mstore(add(memPtr, 128), verifyingContract)

            // Compute hash
            result := keccak256(memPtr, 160)
        }
        return result;
    }

    /// @dev Calculates EIP712 encoding for a hash struct with a given domain hash.
    /// @param domainHash Hash of the domain domain separator data, computed
    ///                         with getDomainHash().
    /// @param hashStruct The EIP712 hash struct.
    /// @return result EIP712 hash applied to the given EIP712 Domain.
    function hashMessage(bytes32 domainHash, bytes32 hashStruct)
        internal
        pure
        returns (bytes32 result)
    {
        // Assembly for more efficient computing:
        // keccak256(abi.encodePacked(
        //     EIP191_HEADER,
        //     EIP712_DOMAIN_HASH,
        //     hashStruct
        // ));

        assembly {
            // Load free memory pointer
            let memPtr := mload(64)

            mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000)  // EIP191 header
            mstore(add(memPtr, 2), domainHash)                                            // EIP712 domain hash
            mstore(add(memPtr, 34), hashStruct)                                                 // Hash of struct

            // Compute hash
            result := keccak256(memPtr, 66)
        }
        return result;
    }
}

File 4 of 21 : LibBytes.sol
pragma solidity ^0.8.4;


library LibBytes {

    using LibBytes for bytes;

    /// @dev Returns a slice from a byte array without preserving the input.
    /// @param b The byte array to take a slice from. Will be destroyed in the process.
    /// @param from The starting index for the slice (inclusive).
    /// @param to The final index for the slice (exclusive).
    /// @return result The slice containing bytes at indices [from, to)
    /// @dev When `from == 0`, the original array will match the slice. In other cases its state will be corrupted.
    function sliceDestructive(
        bytes memory b,
        uint256 from,
        uint256 to
    )
        internal
        pure
        returns (bytes memory result)
    {
        // Ensure that the from and to positions are valid positions for a slice within
        // the byte array that is being used.
        if (from > to) {
            revert('LIB BYTES: from less than or equals to required');
        }
        if (to > b.length) {
            revert('LIB BYTES: to less than or equals length required');
        }

        // Create a new bytes structure around [from, to) in-place.
        assembly {
            result := add(b, from)
            mstore(result, sub(to, from))
        }
        return result;
    }

    /// @dev Reads an address from a position in a byte array.
    /// @param b Byte array containing an address.
    /// @param index Index in byte array of address.
    /// @return result address from byte array.
    function readAddress(
        bytes memory b,
        uint256 index
    )
        internal
        pure
        returns (address result)
    {
        if (b.length < index + 20) {
            revert('LIB BYTES: length greater than or equals twenty required');
        }

        // Add offset to index:
        // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
        // 2. Account for size difference between address length and 32-byte storage word (subtract 12 from index)
        index += 20;

        // Read address from array memory
        assembly {
            // 1. Add index to address of bytes array
            // 2. Load 32-byte word from memory
            // 3. Apply 20-byte mask to obtain address
            result := and(mload(add(b, index)), 0xffffffffffffffffffffffffffffffffffffffff)
        }
        return result;
    }

    /// @dev Reads a bytes32 value from a position in a byte array.
    /// @param b Byte array containing a bytes32 value.
    /// @param index Index in byte array of bytes32 value.
    /// @return result bytes32 value from byte array.
    function readBytes32(
        bytes memory b,
        uint256 index
    )
        internal
        pure
        returns (bytes32 result)
    {
        if (b.length < index + 32) {
            revert('LIB BYTES: length greater than or equals thirty two required');
        }

        // Arrays are prefixed by a 256 bit length parameter
        index += 32;

        // Read the bytes32 from array memory
        assembly {
            result := mload(add(b, index))
        }
        return result;
    }

    /// @dev Reads a uint256 value from a position in a byte array.
    /// @param b Byte array containing a uint256 value.
    /// @param index Index in byte array of uint256 value.
    /// @return result uint256 value from byte array.
    function readUint256(
        bytes memory b,
        uint256 index
    )
        internal
        pure
        returns (uint256 result)
    {
        result = uint256(readBytes32(b, index));
        return result;
    }

    /// @dev Reads an unpadded bytes4 value from a position in a byte array.
    /// @param b Byte array containing a bytes4 value.
    /// @param index Index in byte array of bytes4 value.
    /// @return result bytes4 value from byte array.
    function readBytes4(
        bytes memory b,
        uint256 index
    )
        internal
        pure
        returns (bytes4 result)
    {
        if (b.length < index + 4) {
            revert('LIB BYTES: length greater than or equals four required');
        }

        // Arrays are prefixed by a 32 byte length field
        index += 32;

        // Read the bytes4 from array memory
        assembly {
            result := mload(add(b, index))
            // Solidity does not require us to clean the trailing bytes.
            // We do it anyway
            result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
        }
        return result;
    }
}

File 5 of 21 : ISignatureValidator.sol
pragma solidity ^0.8.4;

import "../libs/LibOrder.sol";


interface ISignatureValidator {

   // Allowed signature types.
    enum SignatureType {
        Illegal,                     // 0x00, default value
        Invalid,                     // 0x01
        EIP712,                      // 0x02
        EthSign,                     // 0x03
        NSignatureTypes              // 0x06, number of signature types. Always leave at end.
    }

    /// @dev Verifies that a hash has been signed by the given signer.
    /// @param hash Any 32-byte hash.
    /// @param signature Proof that the hash has been signed by signer.
    /// @return isValid `true` if the signature is valid for the given hash and signer.
    function isValidHashSignature(
        bytes32 hash,
        address signerAddress,
        bytes memory signature
    )
        external
        view
        returns (bool isValid);

    /// @dev Verifies that a signature for an order is valid.
    /// @param order The order.
    /// @param signature Proof that the order has been signed by signer.
    /// @return isValid true if the signature is valid for the given order and signer.
    function isValidOrderSignature(
        LibOrder.Order memory order,
        bytes memory signature
    )
        external
        view
        returns (bool isValid);
}

File 6 of 21 : IProtocolFees.sol
pragma solidity ^0.8.4;


interface IProtocolFees {

    // Logs updates to the protocol fee multiplier.
    event ProtocolFeeMultiplier(uint256 oldProtocolFeeMultiplier, uint256 updatedProtocolFeeMultiplier);

    // Logs updates to the protocol fixed fee.
    event ProtocolFixedFee(uint256 oldProtocolFixedFee, uint256 updatedProtocolFixedFee);

    // Logs updates to the protocolFeeCollector address.
    event ProtocolFeeCollectorAddress(address oldProtocolFeeCollector, address updatedProtocolFeeCollector);

    /// @dev Allows the owner to update the protocol fee multiplier.
    /// @param updatedProtocolFeeMultiplier The updated protocol fee multiplier.
    function setProtocolFeeMultiplier(uint256 updatedProtocolFeeMultiplier) external;

    /// @dev Allows the owner to update the protocol fixed fee.
    /// @param fixedProtocolFee The updated protocol fixed fee.
    function setProtocolFixedFee(uint256 fixedProtocolFee) external;

    /// @dev Allows the owner to update the protocolFeeCollector address.
    /// @param updatedProtocolFeeCollector The updated protocolFeeCollector contract address.
    function setProtocolFeeCollectorAddress(address updatedProtocolFeeCollector) external;
}

File 7 of 21 : IExchangeCore.sol
pragma solidity ^0.8.4;

import "../libs/LibOrder.sol";


abstract contract IExchangeCore {

    // Fill event is emitted whenever an order is filled.
    event Fill(
        address indexed makerAddress,         // Address that created the order.
        address indexed royaltiesAddress,     // Address that received fees.
        bytes makerAssetData,                 // Encoded data specific to makerAsset.
        bytes takerAssetData,                 // Encoded data specific to takerAsset.
        bytes32 indexed orderHash,            // EIP712 hash of order (see LibOrder.getTypedDataHash).
        address takerAddress,                 // Address that filled the order.
        address senderAddress,                // Address that called the Exchange contract (msg.sender).
        uint256 makerAssetAmount,             // Amount of makerAsset sold by maker and bought by taker.
        uint256 takerAssetAmount,             // Amount of takerAsset sold by taker and bought by maker.
        uint256 royaltiesAmount,              // Amount of royalties paid to royaltiesAddress.
        uint256 protocolFeePaid,              // Amount paid to the protocol.
        bytes32 marketplaceIdentifier,        // marketplace identifier.
        uint256 marketplaceFeePaid            // Amount paid to the marketplace brought the taker.
    );

    // Cancel event is emitted whenever an individual order is cancelled.
    event Cancel(
        address indexed makerAddress,         // Address that created the order.
        bytes makerAssetData,                 // Encoded data specific to makerAsset.
        bytes takerAssetData,                 // Encoded data specific to takerAsset.
        address senderAddress,                // Address that called the Exchange contract (msg.sender).
        bytes32 indexed orderHash             // EIP712 hash of order (see LibOrder.getTypedDataHash).
    );

    // CancelUpTo event is emitted whenever `cancelOrdersUpTo` is executed succesfully.
    event CancelUpTo(
        address indexed makerAddress,         // Orders cancelled must have been created by this address.
        uint256 orderEpoch                    // Orders with a salt less than this value are considered cancelled.
    );

    /// @dev Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch
    /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled.
    function cancelOrdersUpTo(uint256 targetOrderEpoch)
        virtual
        external;

    /// @dev Fills the input order.
    /// @param order Order struct containing order specifications.
    /// @param signature Proof that order has been created by maker.
    /// @return fulfilled boolean
    function fillOrder(
        LibOrder.Order memory order,
        bytes memory signature,
        bytes32 marketIdentifier
    )
        virtual
        external
        payable
        returns (bool fulfilled);

    /// @dev Fills the input order.
    /// @param order Order struct containing order specifications.
    /// @param signature Proof that order has been created by maker.
    /// @param takerAddress address to fulfill the order for / gift.
    /// @return fulfilled boolean
    function fillOrderFor(
        LibOrder.Order memory order,
        bytes memory signature,
        bytes32 marketIdentifier,
        address takerAddress
    )
        virtual
        external
        payable
        returns (bool fulfilled);

    /// @dev After calling, the order can not be filled anymore.
    /// @param order Order struct containing order specifications.
    function cancelOrder(LibOrder.Order memory order)
        virtual
        external;

    /// @dev Gets information about an order: status, hash, and amount filled.
    /// @param order Order to gather information on.
    /// @return orderInfo Information about the order and its state.
    ///                   See LibOrder.OrderInfo for a complete description.
    function getOrderInfo(LibOrder.Order memory order)
        virtual
        external
        view
        returns (LibOrder.OrderInfo memory orderInfo);
}

File 8 of 21 : IAssetProxyRegistry.sol
pragma solidity ^0.8.4;


abstract contract IAssetProxyRegistry {

    // Logs registration of new asset proxy
    event AssetProxyRegistered(
        bytes4 id,              // Id of new registered AssetProxy.
        address assetProxy      // Address of new registered AssetProxy.
    );

    /// @dev Registers an asset proxy to its asset proxy id.
    ///      Once an asset proxy is registered, it cannot be unregistered.
    /// @param assetProxy Address of new asset proxy to register.
    function registerAssetProxy(address assetProxy)
        virtual external;

    /// @dev Gets an asset proxy.
    /// @param assetProxyId Id of the asset proxy.
    /// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.
    function getAssetProxy(bytes4 assetProxyId)
        virtual
        external
        view
        returns (address);
}

File 9 of 21 : IAssetProxy.sol
pragma solidity ^0.8.4;


interface IAssetProxy {

    /// @dev Transfers assets. Either succeeds or throws.
    /// @param assetData Byte array encoded for the respective asset proxy.
    /// @param from Address to transfer asset from.
    /// @param to Address to transfer asset to.
    /// @param amount Amount of asset to transfer.
    function transferFrom(
        bytes calldata assetData,
        address from,
        address to,
        uint256 amount
    )
        external;
    
    /// @dev Gets the proxy id associated with the proxy address.
    /// @return Proxy id.
    function getProxyId()
        external
        pure
        returns (bytes4);
}

File 10 of 21 : IAssetData.sol
pragma solidity ^0.8.4;


/// @dev Interface of the asset proxy's assetData.
// The asset proxies take an ABI encoded `bytes assetData` as argument.
// This argument is ABI encoded as one of the methods of this interface.
interface IAssetData {

    /// @dev Function signature for encoding ERC20 assetData.
    /// @param tokenAddress Address of ERC20Token contract.
    function ERC20Token(address tokenAddress)
        external;

    /// @dev Function signature for encoding ERC721 assetData.
    /// @param tokenAddress Address of ERC721 token contract.
    /// @param tokenId Id of ERC721 token to be transferred.
    function ERC721Token(
        address tokenAddress,
        uint256 tokenId
    )
        external;

    /// @dev Function signature for encoding ERC1155 assetData.
    /// @param tokenAddress Address of ERC1155 token contract.
    /// @param tokenIds Array of ids of tokens to be transferred.
    /// @param values Array of values that correspond to each token id to be transferred.
    ///        Note that each value will be multiplied by the amount being filled in the order before transferring.
    /// @param callbackData Extra data to be passed to receiver's `onERC1155Received` callback function.
    function ERC1155Assets(
        address tokenAddress,
        uint256[] calldata tokenIds,
        uint256[] calldata values,
        bytes calldata callbackData
    )
        external;

    /// @dev Function signature for encoding MultiAsset assetData.
    /// @param values Array of amounts that correspond to each asset to be transferred.
    ///        Note that each value will be multiplied by the amount being filled in the order before transferring.
    /// @param nestedAssetData Array of assetData fields that will be be dispatched to their correspnding AssetProxy contract.
    function MultiAsset(
        uint256[] calldata values,
        bytes[] calldata nestedAssetData
    )
        external;
}

File 11 of 21 : SignatureValidator.sol
pragma solidity ^0.8.4;

import "./libs/LibBytes.sol";
import "./libs/LibOrder.sol";
import "./EIP712Domain.sol";
import "./interfaces/ISignatureValidator.sol";


abstract contract SignatureValidator is
    LibEIP712ExchangeDomain,
    ISignatureValidator
{
    using LibBytes for bytes;
    using LibOrder for LibOrder.Order;

    /// @dev Verifies that a hash has been signed by the given signer.
    /// @param hash Any 32-byte hash.
    /// @param signerAddress Address that should have signed the given hash.
    /// @param signature Proof that the hash has been signed by signer.
    /// @return isValid `true` if the signature is valid for the given hash and signer.
    function isValidHashSignature(
        bytes32 hash,
        address signerAddress,
        bytes memory signature
    )
        override
        public
        pure
        returns (bool isValid)
    {
        SignatureType signatureType = _readValidSignatureType(
            signerAddress,
            signature
        );

        return _validateHashSignatureTypes(
            signatureType,
            hash,
            signerAddress,
            signature
        );
    }

    /// @dev Verifies that a signature for an order is valid.
    /// @param order The order.
    /// @param signature Proof that the order has been signed by signer.
    /// @return isValid `true` if the signature is valid for the given order and signer.
    function isValidOrderSignature(
        LibOrder.Order memory order,
        bytes memory signature
    )
        override
        public
        view
        returns (bool isValid)
    {
        bytes32 orderHash = order.getTypedDataHash(DOMAIN_HASH);
        isValid = _isValidOrderWithHashSignature(
            order,
            orderHash,
            signature
        );
        return isValid;
    }

    /// @dev Verifies that an order, with provided order hash, has been signed
    ///      by the given signer.
    /// @param order The order.
    /// @param orderHash The hash of the order.
    /// @param signature Proof that the hash has been signed by signer.
    /// @return isValid True if the signature is valid for the given order and signer.
    function _isValidOrderWithHashSignature(
        LibOrder.Order memory order,
        bytes32 orderHash,
        bytes memory signature
    )
        internal
        pure
        returns (bool isValid)
    {
        address signerAddress = order.makerAddress;
        SignatureType signatureType = _readValidSignatureType(
            signerAddress,
            signature
        );
        
        return _validateHashSignatureTypes(
            signatureType,
            orderHash,
            signerAddress,
            signature
        );
    }

    /// Validates a hash-only signature type
    /// (anything but `EIP1271Wallet`).
    function _validateHashSignatureTypes(
        SignatureType signatureType,
        bytes32 hash,
        address signerAddress,
        bytes memory signature
    )
        private
        pure
        returns (bool isValid)
    {
        // invalid signature.
        if (signatureType == SignatureType.Invalid) {
            if (signature.length != 1) {
                revert('SIGNATURE: invalid length');
            }
            isValid = false;

        // Signature using EIP712
        } else if (signatureType == SignatureType.EIP712) {
            if (signature.length != 66) {
                revert('SIGNATURE: invalid length');
            }
            uint8 v = uint8(signature[0]);
            bytes32 r = signature.readBytes32(1);
            bytes32 s = signature.readBytes32(33);
            address recovered = ecrecover(
                hash,
                v,
                r,
                s
            );
            isValid = signerAddress == recovered;

        // Signed using web3.eth_sign
        } else if (signatureType == SignatureType.EthSign) {
            if (signature.length != 66) {
                revert('SIGNATURE: invalid length');
            }
            uint8 v = uint8(signature[0]);
            bytes32 r = signature.readBytes32(1);
            bytes32 s = signature.readBytes32(33);
            address recovered = ecrecover(
                keccak256(abi.encodePacked(
                    "\x19Ethereum Signed Message:\n32",
                    hash
                )),
                v,
                r,
                s
            );
            isValid = signerAddress == recovered;
        }

        return isValid;
    }

    /// @dev Reads the `SignatureType` from the end of a signature and validates it.
    function _readValidSignatureType(
        address signerAddress,
        bytes memory signature
    )
        private
        pure
        returns (SignatureType signatureType)
    {
        if (signature.length == 0) {
            revert('SIGNATURE: invalid length');
        }
        signatureType = SignatureType(uint8(signature[signature.length - 1]));

        // Disallow address zero because ecrecover() returns zero on failure.
        if (signerAddress == address(0)) {
            revert('SIGNATURE: signerAddress cannot be null');
        }

        // Ensure signature is supported
        if (uint8(signatureType) >= uint8(SignatureType.NSignatureTypes)) {
            revert('SIGNATURE: signature not supported');
        }

        // illegal signature.
        if (signatureType == SignatureType.Illegal) {
            revert('SIGNATURE: illegal signature');
        }

        return signatureType;
    }
}

File 12 of 21 : Refundable.sol
pragma solidity ^0.8.4;

contract Refundable
{

    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    modifier refundFinalBalanceNoReentry {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        _refundNonZeroBalance();

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    function _refundNonZeroBalance()
        internal
    {
        uint256 balance = address(this).balance;
        if (balance > 0) {
            payable(msg.sender).transfer(balance);
        }
    }
}

File 13 of 21 : ProtocolFees.sol
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IProtocolFees.sol";


contract ProtocolFees is
    IProtocolFees,
    Ownable
{
    /// @dev The protocol fee multiplier -- the owner can update this field.
    /// @return 0 Gas multplier.
    uint256 public protocolFeeMultiplier;

    /// @dev The protocol fixed fee multiplier -- the owner can update this field.
    /// @return 0 fixed fee.
    uint256 public protocolFixedFee;

    /// @dev The address of the registered protocolFeeCollector contract -- the owner can update this field.
    /// @return 0 Contract to forward protocol fees to.
    address public protocolFeeCollector;

    /// @dev Allows the owner to update the protocol fee multiplier.
    /// @param updatedProtocolFeeMultiplier The updated protocol fee multiplier.
    function setProtocolFeeMultiplier(uint256 updatedProtocolFeeMultiplier)
        override
        external
        onlyOwner
    {
        emit ProtocolFeeMultiplier(protocolFeeMultiplier, updatedProtocolFeeMultiplier);
        protocolFeeMultiplier = updatedProtocolFeeMultiplier;
    }

    /// @dev Allows the owner to update the protocol fixed fee.
    /// @param updatedProtocolFixedFee The updated protocol fixed fee.
    function setProtocolFixedFee(uint256 updatedProtocolFixedFee)
        override
        external
        onlyOwner
    {
        emit ProtocolFixedFee(protocolFixedFee, updatedProtocolFixedFee);
        protocolFixedFee = updatedProtocolFixedFee;
    }

    /// @dev Allows the owner to update the protocolFeeCollector address.
    /// @param updatedProtocolFeeCollector The updated protocolFeeCollector contract address.
    function setProtocolFeeCollectorAddress(address updatedProtocolFeeCollector)
        override
        external
        onlyOwner
    {
        emit ProtocolFeeCollectorAddress(protocolFeeCollector, updatedProtocolFeeCollector);
        protocolFeeCollector = updatedProtocolFeeCollector;
    }
}

File 14 of 21 : MarketplaceRegistry.sol
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/access/Ownable.sol";

contract MarketplaceRegistry is Ownable {
    struct Marketplace {
        uint256 feeMultiplier;
        address feeCollector;
        bool isActive;
    }

    event MarketplaceRegister(bytes32 identifier, uint256 feeMultiplier, address feeCollector);
    event MarketplaceUpdateStatus(bytes32 identifier, bool status);
    event MarketplaceSetFees(bytes32 identifier, uint256 feeMultiplier, address feeCollector);

    bool public distributeMarketplaceFees = true;

    mapping(bytes32 => Marketplace) marketplaces;

    function marketplaceDistribution(bool _distributeMarketplaceFees)
        external
        onlyOwner
    {
        distributeMarketplaceFees = _distributeMarketplaceFees;
    }

    function registerMarketplace(bytes32 identifier, uint256 feeMultiplier, address feeCollector) external onlyOwner {
        require(feeMultiplier <= 100, "fee multiplier must be betwen 0 to 100");
        marketplaces[identifier] = Marketplace(feeMultiplier, feeCollector, true);
        emit MarketplaceRegister(identifier, feeMultiplier, feeCollector);
    }

    function setMarketplaceStatus(bytes32 identifier, bool isActive)
        external
        onlyOwner
    {
        marketplaces[identifier].isActive = isActive;
        emit MarketplaceUpdateStatus(identifier, isActive);
    }

    function setMarketplaceFees(
        bytes32 identifier,
        uint256 feeMultiplier,
        address feeCollector
    ) external onlyOwner {
        require(feeMultiplier <= 100, "fee multiplier must be betwen 0 to 100");
        marketplaces[identifier].feeMultiplier = feeMultiplier;
        marketplaces[identifier].feeCollector = feeCollector;
        emit MarketplaceSetFees(identifier, feeMultiplier, feeCollector);
    }
}

File 15 of 21 : ExchangeCore.sol
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "./libs/LibBytes.sol";
import "./libs/LibOrder.sol";
import "./interfaces/IExchangeCore.sol";
import "./interfaces/IAssetData.sol";
import "./AssetProxyRegistry.sol";
import "./EIP712Domain.sol";
import "./ProtocolFees.sol";
import "./SignatureValidator.sol";
import "./MarketplaceRegistry.sol";

abstract contract ExchangeCore is
    IExchangeCore,
    AssetProxyRegistry,
    ProtocolFees,
    SignatureValidator,
    MarketplaceRegistry
{
    using LibOrder for LibOrder.Order;
    using SafeMath for uint256;
    using LibBytes for bytes;

    /// @dev orderHash => filled
    /// @return boolean the order has been filled
    mapping (bytes32 => bool) public filled;

    /// @dev orderHash => cancelled
    /// @return boolean the order has been cancelled
    mapping (bytes32 => bool) public cancelled;

    /// @dev makerAddress => lowest salt an order can have in order to be fillable
    /// @return epoc Orders with a salt less than their epoch are considered cancelled
    mapping (address => uint256) public orderEpoch;

    /// @dev Fills the input order.
    /// @param order Order struct containing order specifications.
    /// @param signature Proof that order has been created by maker.
    /// @param takerAddress orider fill for the taker.
    /// @return fulfilled boolean
    function _fillOrder(
        LibOrder.Order memory order,
        bytes memory signature,
        address takerAddress,
        bytes32 marketplaceIdentifier
    )
        internal
        returns (bool fulfilled)
    {
        // Fetch order info
        LibOrder.OrderInfo memory orderInfo = _getOrderInfo(order);

        // Assert that the order is fillable by taker
        _assertFillable(
            order,
            orderInfo,
            takerAddress,
            signature
        );

        bytes32 orderHash = orderInfo.orderHash;

        // Update state
        filled[orderHash] = true;

        Marketplace memory marketplace = marketplaces[marketplaceIdentifier];

        // Settle order
        (uint256 protocolFee, uint256 marketplaceFee) = _settle(
            orderInfo,
            order,
            takerAddress,
            marketplace
        );

        _notifyFill(order, orderHash, takerAddress, protocolFee, marketplaceIdentifier, marketplaceFee);

        return filled[orderHash];
    }

    function _notifyFill(
        LibOrder.Order memory order,
        bytes32 orderHash,
        address takerAddress,
        uint256 protocolFee,
        bytes32 marketplaceIdentifier,
        uint256 marketplaceFee
    ) internal {
        emit Fill(
            order.makerAddress,
            order.royaltiesAddress,
            order.makerAssetData,
            order.takerAssetData,
            orderHash,
            takerAddress,
            msg.sender,
            order.makerAssetAmount,
            order.takerAssetAmount,
            order.royaltiesAmount,
            protocolFee,
            marketplaceIdentifier,
            marketplaceFee
        );
    }

    /// @dev After calling, the order can not be filled anymore.
    ///      Throws if order is invalid or sender does not have permission to cancel.
    /// @param order Order to cancel. Order must be OrderStatus.FILLABLE.
    function _cancelOrder(LibOrder.Order memory order)
        internal
    {
        // Fetch current order status
        LibOrder.OrderInfo memory orderInfo = _getOrderInfo(order);

        // Validate context
        _assertValidCancel(order);

        // Noop if order is already unfillable
        if (orderInfo.orderStatus != LibOrder.OrderStatus.FILLABLE) {
            return;
        }

        // Perform cancel
        _updateCancelledState(order, orderInfo.orderHash);
    }

    /// @dev Updates state with results of cancelling an order.
    ///      State is only updated if the order is currently fillable.
    ///      Otherwise, updating state would have no effect.
    /// @param order that was cancelled.
    /// @param orderHash Hash of order that was cancelled.
    function _updateCancelledState(
        LibOrder.Order memory order,
        bytes32 orderHash
    )
        internal
    {
        // Perform cancel
        cancelled[orderHash] = true;

        // Log cancel
        emit Cancel(
            order.makerAddress,
            order.makerAssetData,
            order.takerAssetData,
            msg.sender,
            orderHash
        );
    }

    /// @dev Validates context for fillOrder. Succeeds or throws.
    /// @param order to be filled.
    /// @param orderInfo OrderStatus, orderHash, and amount already filled of order.
    /// @param takerAddress Address of order taker.
    /// @param signature Proof that the orders was created by its maker.
    function _assertFillable(
        LibOrder.Order memory order,
        LibOrder.OrderInfo memory orderInfo,
        address takerAddress,
        bytes memory signature
    )
        internal
    {
        if (orderInfo.orderType == LibOrder.OrderType.INVALID) {
            revert('EXCHANGE: type illegal');
        }

        if (orderInfo.orderType == LibOrder.OrderType.LIST) {
            address erc20TokenAddress = order.takerAssetData.readAddress(4);
            if (erc20TokenAddress == address(0) && msg.value < order.takerAssetAmount) {
                revert('EXCHANGE: wrong value sent');
            }
        }

        if (orderInfo.orderType != LibOrder.OrderType.LIST && takerAddress != msg.sender) {
            revert('EXCHANGE: fill order for is only valid for buy now');
        }

        if (orderInfo.orderType == LibOrder.OrderType.SWAP) {
            if (msg.value < protocolFixedFee) {
                revert('EXCHANGE: wrong value sent');
            }
        }

        // An order can only be filled if its status is FILLABLE.
        if (orderInfo.orderStatus != LibOrder.OrderStatus.FILLABLE) {
            revert('EXCHANGE: status not fillable');
        }

        // Validate sender is allowed to fill this order
        if (order.senderAddress != address(0)) {
            if (order.senderAddress != msg.sender) {
                revert('EXCHANGE: invalid sender');
            }
        }

        // Validate taker is allowed to fill this order
        if (order.takerAddress != address(0)) {
            if (order.takerAddress != takerAddress) {
                revert('EXCHANGE: invalid taker');
            }
        }

        // Validate signature
        if (!_isValidOrderWithHashSignature(
                order,
                orderInfo.orderHash,
                signature
            )
        ) {
            revert('EXCHANGE: invalid signature');
        }
    }

    /// @dev Validates context for cancelOrder. Succeeds or throws.
    /// @param order to be cancelled.
    function _assertValidCancel(
        LibOrder.Order memory order
    )
        internal
        view
    {
        // Validate sender is allowed to cancel this order
        if (order.senderAddress != address(0)) {
            if (order.senderAddress != msg.sender) {
                revert('EXCHANGE: invalid sender');
            }
        }

        // Validate transaction signed by maker
        address makerAddress = msg.sender;
        if (order.makerAddress != makerAddress) {
            revert('EXCHANGE: invalid maker');
        }
    }

    /// @dev Gets information about an order: status, hash, and amount filled.
    /// @param order Order to gather information on.
    /// @return orderInfo Information about the order and its state.
    ///         See LibOrder.OrderInfo for a complete description.
    function _getOrderInfo(LibOrder.Order memory order)
        internal
        view
        returns (LibOrder.OrderInfo memory orderInfo)
    {
        // Compute the order hash
        orderInfo.orderHash = order.getTypedDataHash(DOMAIN_HASH);

        bool isTakerAssetDataERC20 = _isERC20Proxy(order.takerAssetData);
        bool isMakerAssetDataERC20 = _isERC20Proxy(order.makerAssetData);

        if (isTakerAssetDataERC20 && !isMakerAssetDataERC20) {
            orderInfo.orderType = LibOrder.OrderType.LIST;
        } else if (!isTakerAssetDataERC20 && isMakerAssetDataERC20) {
            orderInfo.orderType = LibOrder.OrderType.OFFER;
        } else if (!isTakerAssetDataERC20 && !isMakerAssetDataERC20) {
            orderInfo.orderType = LibOrder.OrderType.SWAP;
        } else {
            orderInfo.orderType = LibOrder.OrderType.INVALID;
        }

        // If order.makerAssetAmount is zero the order is invalid
        if (order.makerAssetAmount == 0) {
            orderInfo.orderStatus = LibOrder.OrderStatus.INVALID_MAKER_ASSET_AMOUNT;
            return orderInfo;
        }

        // If order.takerAssetAmount is zero the order is invalid
        if (order.takerAssetAmount == 0) {
            orderInfo.orderStatus = LibOrder.OrderStatus.INVALID_TAKER_ASSET_AMOUNT;
            return orderInfo;
        }

        if (orderInfo.orderType == LibOrder.OrderType.LIST && order.royaltiesAmount > order.takerAssetAmount) {
            orderInfo.orderStatus = LibOrder.OrderStatus.INVALID_ROYALTIES;
            return orderInfo;
        }

        if (orderInfo.orderType == LibOrder.OrderType.OFFER && order.royaltiesAmount > order.makerAssetAmount) {
            orderInfo.orderStatus = LibOrder.OrderStatus.INVALID_ROYALTIES;
            return orderInfo;
        }

        // Check if order has been filled
        if (filled[orderInfo.orderHash]) {
            orderInfo.orderStatus = LibOrder.OrderStatus.FILLED;
            return orderInfo;
        }

        // Check if order has been cancelled
        if (cancelled[orderInfo.orderHash]) {
            orderInfo.orderStatus = LibOrder.OrderStatus.CANCELLED;
            return orderInfo;
        }

        if (orderEpoch[order.makerAddress] > order.salt) {
            orderInfo.orderStatus = LibOrder.OrderStatus.CANCELLED;
            return orderInfo;
        }

        // Validate order expiration
        if (block.timestamp >= order.expirationTimeSeconds) {
            orderInfo.orderStatus = LibOrder.OrderStatus.EXPIRED;
            return orderInfo;
        }

        // All other statuses are ruled out: order is Fillable
        orderInfo.orderStatus = LibOrder.OrderStatus.FILLABLE;
        return orderInfo;
    }


    /// @dev Settles an order by transferring assets between counterparties.
    /// @param orderInfo The order info struct.
    /// @param order Order struct containing order specifications.
    /// @param takerAddress Address selling takerAsset and buying makerAsset.
    function _settle(
        LibOrder.OrderInfo memory orderInfo,
        LibOrder.Order memory order,
        address takerAddress,
        Marketplace memory marketplace
    )
        internal
        returns (uint256 protocolFee, uint256 marketplaceFee)
    {
        bytes memory payerAssetData;
        bytes memory sellerAssetData;
        address payerAddress;
        address sellerAddress;
        uint256 buyerPayment;
        uint256 sellerAmount;

        if (orderInfo.orderType == LibOrder.OrderType.LIST) {
            payerAssetData = order.takerAssetData;
            sellerAssetData = order.makerAssetData;
            payerAddress = msg.sender;
            sellerAddress = order.makerAddress;
            buyerPayment = order.takerAssetAmount;
            sellerAmount = order.makerAssetAmount;
        }

        if (orderInfo.orderType == LibOrder.OrderType.OFFER || orderInfo.orderType == LibOrder.OrderType.SWAP) {
            payerAssetData = order.makerAssetData;
            sellerAssetData = order.takerAssetData;
            payerAddress = order.makerAddress;
            sellerAddress = msg.sender;
            takerAddress = payerAddress;
            buyerPayment = order.makerAssetAmount;
            sellerAmount = order.takerAssetAmount;
        }


        // pay protocol fees
        if (protocolFeeCollector != address(0)) {
            bytes memory protocolAssetData = payerAssetData;
            if (orderInfo.orderType == LibOrder.OrderType.SWAP && protocolFixedFee > 0) {
                protocolFee = protocolFixedFee;
                protocolAssetData = abi.encodeWithSelector(IAssetData(address(0)).ERC20Token.selector, address(0));
            } else if (protocolFeeMultiplier > 0) {
                protocolFee = buyerPayment.mul(protocolFeeMultiplier).div(1000); // 10 times the fee to support decimals - 20 -> 2%
                buyerPayment = buyerPayment.sub(protocolFee);
            }

            if (marketplace.isActive && marketplace.feeCollector != address(0) && marketplace.feeMultiplier > 0 && distributeMarketplaceFees) {
                marketplaceFee = protocolFee.mul(marketplace.feeMultiplier).div(100);
                protocolFee = protocolFee.sub(marketplaceFee);
                _dispatchTransfer(
                    protocolAssetData,
                    payerAddress,
                    marketplace.feeCollector,
                    marketplaceFee
                );
            }

            _dispatchTransfer(
                protocolAssetData,
                payerAddress,
                protocolFeeCollector,
                protocolFee
            );
        }

        // pay royalties
        if (order.royaltiesAddress != address(0) && order.royaltiesAmount > 0 ) {
            buyerPayment = buyerPayment.sub(order.royaltiesAmount);
            _dispatchTransfer(
                payerAssetData,
                payerAddress,
                order.royaltiesAddress,
                order.royaltiesAmount
            );
        }

        // pay seller // erc20
        _dispatchTransfer(
            payerAssetData,
            payerAddress,
            sellerAddress,
            buyerPayment
        );

        // Transfer seller -> buyer (nft / bundle)
        _dispatchTransfer(
            sellerAssetData,
            sellerAddress,
            takerAddress,
            sellerAmount
        );

        return (protocolFee, marketplaceFee);
      
    }
}

File 16 of 21 : EIP712Domain.sol
pragma solidity ^0.8.4;

import "./libs/LibEIP712.sol";


contract LibEIP712ExchangeDomain {

    // EIP712 Exchange Domain Name value
    string constant internal DOMAIN_NAME = "Nifty Exchange";

    // EIP712 Exchange Domain Version value
    string constant internal DOMAIN_VERSION = "2.0";

    // solhint-disable var-name-mixedcase
    /// @dev Hash of the EIP712 Domain Separator data
    /// @return 0 Domain hash.
    bytes32 public DOMAIN_HASH;
    // solhint-enable var-name-mixedcase

    /// @param chainId Chain ID of the network this contract is deployed on.
    constructor (
        uint256 chainId
    )
    {
        DOMAIN_HASH = LibEIP712.hashDomain(
            DOMAIN_NAME,
            DOMAIN_VERSION,
            chainId,
            address(this)
        );
    }
}

File 17 of 21 : AssetProxyRegistry.sol
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/access/Ownable.sol";
import "./libs/LibBytes.sol";
import "./interfaces/IAssetData.sol";
import "./interfaces/IAssetProxy.sol";
import "./interfaces/IAssetProxyRegistry.sol";


contract AssetProxyRegistry is
    Ownable,
    IAssetProxyRegistry
{
    using LibBytes for bytes;

    // Mapping from Asset Proxy Id's to their respective Asset Proxy
    mapping (bytes4 => address) internal _assetProxies;

    /// @dev Registers an asset proxy to its asset proxy id.
    /// @param assetProxy Address of new asset proxy to register.
    function registerAssetProxy(address assetProxy)
        override
        external
        onlyOwner
    {
        // Ensure that no asset proxy exists with current id.
        bytes4 assetProxyId = IAssetProxy(assetProxy).getProxyId();
        // Add asset proxy and log registration.
        _assetProxies[assetProxyId] = assetProxy;
        emit AssetProxyRegistered(
            assetProxyId,
            assetProxy
        );
    }

    /// @dev Gets an asset proxy.
    /// @param assetProxyId Id of the asset proxy.
    /// @return assetProxy The asset proxy address registered to assetProxyId. Returns 0x0 if no proxy is registered.
    function getAssetProxy(bytes4 assetProxyId)
        override
        external
        view
        returns (address assetProxy)
    {
        return _assetProxies[assetProxyId];
    }

    function _isERC20Proxy(bytes memory assetData)
        internal
        pure
        returns (bool)
    {
        bytes4 assetProxyId = assetData.readBytes4(0);
        bytes4 erc20ProxyId = IAssetData(address(0)).ERC20Token.selector;

        return assetProxyId == erc20ProxyId;
    }

    /// @dev Forwards arguments to assetProxy and calls `transferFrom`. Either succeeds or throws.
    /// @param assetData Byte array encoded for the asset.
    /// @param from Address to transfer token from.
    /// @param to Address to transfer token to.
    /// @param amount Amount of token to transfer.
    function _dispatchTransfer(
        bytes memory assetData,
        address from,
        address to,
        uint256 amount
    )
        internal
    {
        // Do nothing if no amount should be transferred.
        if (amount > 0) {

            // Ensure assetData is padded to 32 bytes (excluding the id) and is at least 4 bytes long
            if (assetData.length % 32 != 4) {
                revert('ASSET PROXY: invalid length');
            }

            // Lookup assetProxy.
            bytes4 assetProxyId = assetData.readBytes4(0);
            address assetProxy = _assetProxies[assetProxyId];

            // Ensure that assetProxy exists
            if (assetProxy == address(0)) {
                revert('ASSET PROXY: unknown');
            }

            bool ethPayment = false;

            if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
                address erc20TokenAddress = assetData.readAddress(4);
                ethPayment = erc20TokenAddress == address(0);
            }

            if (ethPayment) {
                if (address(this).balance < amount) {
                    revert("ASSET PROXY: insufficient balance");
                }
                (bool success, ) = to.call{value: amount}("");
                require(success, "ASSET PROXY: eth transfer failed");
            } else {
                // Construct the calldata for the transferFrom call.
                bytes memory proxyCalldata = abi.encodeWithSelector(
                    IAssetProxy(address(0)).transferFrom.selector,
                    assetData,
                    from,
                    to,
                    amount
                );

                // Call the asset proxy's transferFrom function with the constructed calldata.
                (bool didSucceed, ) = assetProxy.call(proxyCalldata);

                // If the transaction did not succeed, revert with the returned data.
                if (!didSucceed) {
                    revert("ASSET PROXY: transfer failed");
                }
            }
        }
    }
}

File 18 of 21 : SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 19 of 21 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 20 of 21 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 21 of 21 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

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

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"id","type":"bytes4"},{"indexed":false,"internalType":"address","name":"assetProxy","type":"address"}],"name":"AssetProxyRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"makerAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"takerAssetData","type":"bytes"},{"indexed":false,"internalType":"address","name":"senderAddress","type":"address"},{"indexed":true,"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"Cancel","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"makerAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"orderEpoch","type":"uint256"}],"name":"CancelUpTo","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"makerAddress","type":"address"},{"indexed":true,"internalType":"address","name":"royaltiesAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"takerAssetData","type":"bytes"},{"indexed":true,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"takerAddress","type":"address"},{"indexed":false,"internalType":"address","name":"senderAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"makerAssetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"takerAssetAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"royaltiesAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"protocolFeePaid","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"marketplaceIdentifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"marketplaceFeePaid","type":"uint256"}],"name":"Fill","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"feeMultiplier","type":"uint256"},{"indexed":false,"internalType":"address","name":"feeCollector","type":"address"}],"name":"MarketplaceRegister","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"feeMultiplier","type":"uint256"},{"indexed":false,"internalType":"address","name":"feeCollector","type":"address"}],"name":"MarketplaceSetFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"identifier","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"MarketplaceUpdateStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldProtocolFeeCollector","type":"address"},{"indexed":false,"internalType":"address","name":"updatedProtocolFeeCollector","type":"address"}],"name":"ProtocolFeeCollectorAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldProtocolFeeMultiplier","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"updatedProtocolFeeMultiplier","type":"uint256"}],"name":"ProtocolFeeMultiplier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldProtocolFixedFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"updatedProtocolFixedFee","type":"uint256"}],"name":"ProtocolFixedFee","type":"event"},{"inputs":[],"name":"DOMAIN_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"address","name":"takerAddress","type":"address"},{"internalType":"address","name":"royaltiesAddress","type":"address"},{"internalType":"address","name":"senderAddress","type":"address"},{"internalType":"uint256","name":"makerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"takerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"royaltiesAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"}],"name":"cancelOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"targetOrderEpoch","type":"uint256"}],"name":"cancelOrdersUpTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"cancelled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributeMarketplaceFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"address","name":"takerAddress","type":"address"},{"internalType":"address","name":"royaltiesAddress","type":"address"},{"internalType":"address","name":"senderAddress","type":"address"},{"internalType":"uint256","name":"makerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"takerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"royaltiesAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"marketplaceIdentifier","type":"bytes32"}],"name":"fillOrder","outputs":[{"internalType":"bool","name":"fulfilled","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"address","name":"takerAddress","type":"address"},{"internalType":"address","name":"royaltiesAddress","type":"address"},{"internalType":"address","name":"senderAddress","type":"address"},{"internalType":"uint256","name":"makerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"takerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"royaltiesAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"marketplaceIdentifier","type":"bytes32"},{"internalType":"address","name":"takerAddress","type":"address"}],"name":"fillOrderFor","outputs":[{"internalType":"bool","name":"fulfilled","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"filled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"assetProxyId","type":"bytes4"}],"name":"getAssetProxy","outputs":[{"internalType":"address","name":"assetProxy","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"address","name":"takerAddress","type":"address"},{"internalType":"address","name":"royaltiesAddress","type":"address"},{"internalType":"address","name":"senderAddress","type":"address"},{"internalType":"uint256","name":"makerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"takerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"royaltiesAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"}],"name":"getOrderInfo","outputs":[{"components":[{"internalType":"enum LibOrder.OrderStatus","name":"orderStatus","type":"uint8"},{"internalType":"enum LibOrder.OrderType","name":"orderType","type":"uint8"},{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"bool","name":"filled","type":"bool"}],"internalType":"struct LibOrder.OrderInfo","name":"orderInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"address","name":"signerAddress","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidHashSignature","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"makerAddress","type":"address"},{"internalType":"address","name":"takerAddress","type":"address"},{"internalType":"address","name":"royaltiesAddress","type":"address"},{"internalType":"address","name":"senderAddress","type":"address"},{"internalType":"uint256","name":"makerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"takerAssetAmount","type":"uint256"},{"internalType":"uint256","name":"royaltiesAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes","name":"makerAssetData","type":"bytes"},{"internalType":"bytes","name":"takerAssetData","type":"bytes"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidOrderSignature","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_distributeMarketplaceFees","type":"bool"}],"name":"marketplaceDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"orderEpoch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFixedFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"assetProxy","type":"address"}],"name":"registerAssetProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"feeMultiplier","type":"uint256"},{"internalType":"address","name":"feeCollector","type":"address"}],"name":"registerMarketplace","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"returnAllETHToOwner","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"ERC20Token","type":"address"}],"name":"returnERC20ToOwner","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint256","name":"feeMultiplier","type":"uint256"},{"internalType":"address","name":"feeCollector","type":"address"}],"name":"setMarketplaceFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"bool","name":"isActive","type":"bool"}],"name":"setMarketplaceStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"updatedProtocolFeeCollector","type":"address"}],"name":"setProtocolFeeCollectorAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"updatedProtocolFeeMultiplier","type":"uint256"}],"name":"setProtocolFeeMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"updatedProtocolFixedFee","type":"uint256"}],"name":"setProtocolFixedFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6007805460ff1916600117905560c0604052600e60808190526d139a599d1e48141c9bdd1bd8dbdb60921b60a09081526200003e91600c91906200018f565b503480156200004c57600080fd5b506040516200324f3803806200324f8339810160408190526200006f9162000235565b806200007b33620000e8565b60018081905550620000dc6040518060400160405280600e81526020016d4e696674792045786368616e676560901b815250604051806040016040528060038152602001620322e360ec1b81525083306200013860201b620010131760201c565b600655506200028b9050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b8280546200019d906200024e565b90600052602060002090601f016020900481019282620001c157600085556200020c565b82601f10620001dc57805160ff19168380011785556200020c565b828001600101855582156200020c579182015b828111156200020c578251825591602001919060010190620001ef565b506200021a9291506200021e565b5090565b5b808211156200021a57600081556001016200021f565b60006020828403121562000247578081fd5b5051919050565b600181811c908216806200026357607f821691505b602082108114156200028557634e487b7160e01b600052602260045260246000fd5b50919050565b612fb4806200029b6000396000f3fe6080604052600436106101d15760003560e01c80638171c407116100f7578063b062930911610095578063d0da53e811610064578063d0da53e81461057c578063e98b3b7e1461058f578063e9e8f255146105a2578063f2fde38b146105aa57600080fd5b8063b0629309146104fc578063c0fa16cc1461051c578063c585bb931461053c578063c82512a31461055c57600080fd5b80638da5cb5b116100d15780638da5cb5b1461048b5780639331c742146104a95780639331ff07146104c9578063a57aad95146104e957600080fd5b80638171c40714610435578063850a1501146104555780638b114f7a1461047557600080fd5b8063416bae2b1161016f57806353e1a6e41161013e57806353e1a6e4146103885780635804df9f146103a857806360704108146103c8578063715018a61461042057600080fd5b8063416bae2b146102f857806343795d2b1461032557806344c11275146103525780634f9559b11461036857600080fd5b80630be6904e116101ab5780630be6904e146102545780631ce4c78b14610274578063288cdc91146102985780632ac12622146102c857600080fd5b806306fdde03146101dd57806308566069146102085780630a555e681461023257600080fd5b366101d857005b600080fd5b3480156101e957600080fd5b506101f26105ca565b6040516101ff9190612ce5565b60405180910390f35b34801561021457600080fd5b506007546102229060ff1681565b60405190151581526020016101ff565b34801561023e57600080fd5b5061025261024d36600461298a565b610658565b005b34801561026057600080fd5b5061025261026f3660046128e5565b6106f4565b34801561028057600080fd5b5061028a60035481565b6040519081526020016101ff565b3480156102a457600080fd5b506102226102b336600461291d565b60096020526000908152604090205460ff1681565b3480156102d457600080fd5b506102226102e336600461291d565b600a6020526000908152604090205460ff1681565b34801561030457600080fd5b50610318610313366004612a25565b610731565b6040516101ff9190612daa565b34801561033157600080fd5b5061028a6103403660046128cb565b600b6020526000908152604090205481565b34801561035e57600080fd5b5061028a60045481565b34801561037457600080fd5b5061025261038336600461291d565b61076c565b34801561039457600080fd5b506102526103a33660046129b9565b610840565b3480156103b457600080fd5b506102226103c3366004612a58565b610932565b3480156103d457600080fd5b506104086103e33660046129ed565b6001600160e01b0319166000908152600260205260409020546001600160a01b031690565b6040516001600160a01b0390911681526020016101ff565b34801561042c57600080fd5b5061025261095f565b34801561044157600080fd5b50610222610450366004612935565b610995565b34801561046157600080fd5b50600554610408906001600160a01b031681565b34801561048157600080fd5b5061028a60065481565b34801561049757600080fd5b506000546001600160a01b0316610408565b3480156104b557600080fd5b506102526104c436600461291d565b6109b9565b3480156104d557600080fd5b506102526104e4366004612a25565b610a24565b6102526104f73660046128cb565b610a30565b34801561050857600080fd5b506102526105173660046129b9565b610b6b565b34801561052857600080fd5b506102526105373660046128cb565b610c26565b34801561054857600080fd5b506102526105573660046128cb565b610cb9565b34801561056857600080fd5b5061025261057736600461291d565b610dc3565b61022261058a366004612b23565b610e2e565b61022261059d366004612ab9565b610eaa565b610252610f25565b3480156105b657600080fd5b506102526105c53660046128cb565b610f7b565b600c80546105d790612eb3565b80601f016020809104026020016040519081016040528092919081815260200182805461060390612eb3565b80156106505780601f1061062557610100808354040283529160200191610650565b820191906000526020600020905b81548152906001019060200180831161063357829003601f168201915b505050505081565b6000546001600160a01b0316331461068b5760405162461bcd60e51b815260040161068290612d2f565b60405180910390fd5b600082815260086020908152604091829020600101805460ff60a01b1916600160a01b851515908102919091179091558251858152918201527fcdb43529d2b43068dbbd48f63dc15aa366c63f54681ef121ae27cc49201efa1391015b60405180910390a15050565b6000546001600160a01b0316331461071e5760405162461bcd60e51b815260040161068290612d2f565b6007805460ff1916911515919091179055565b61075d604080516080810190915280600081526020016000815260006020820181905260409091015290565b6107668261106a565b92915050565b33600061077a836001612e25565b6001600160a01b0383166000908152600b60205260409020549091508082116107e55760405162461bcd60e51b815260206004820152601b60248201527f45584348414e47453a206f726465722065706f6368206572726f7200000000006044820152606401610682565b6001600160a01b0383166000818152600b602052604090819020849055517f666a5047451d0c744e58819166260f8048fe2786e33b3c1115af94887a451ca7906108329085815260200190565b60405180910390a250505050565b6000546001600160a01b0316331461086a5760405162461bcd60e51b815260040161068290612d2f565b606482111561088b5760405162461bcd60e51b815260040161068290612d64565b60408051606080820183528482526001600160a01b038481166020808501828152600186880181815260008c8152600885528990209751885591519601805491511515600160a01b026001600160a81b03199092169690941695909517949094179091558351878152928301869052928201929092527f1eef4f4100283c5fe019e5d6c46da4a09e2c75bd5ea6a0295cb9dd7952f4aae391015b60405180910390a1505050565b60008061094a600654856112b390919063ffffffff16565b90506109578482856112e8565b949350505050565b6000546001600160a01b031633146109895760405162461bcd60e51b815260040161068290612d2f565b6109936000611310565b565b6000806109a28484611360565b90506109b08186868661152c565b95945050505050565b6000546001600160a01b031633146109e35760405162461bcd60e51b815260040161068290612d2f565b60035460408051918252602082018390527f3a3e76d7a75e198aef1f53137e4f2a8a2ec74e2e9526db8404d08ccc9f1e621d910160405180910390a1600355565b610a2d816117e1565b50565b6000546001600160a01b03163314610a5a5760405162461bcd60e51b815260040161068290612d2f565b6040516370a0823160e01b8152306004820181905282916001600160a01b038316916323b872dd91339084906370a082319060240160206040518083038186803b158015610aa757600080fd5b505afa158015610abb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610adf9190612b9e565b6040516001600160e01b031960e086901b1681526001600160a01b0393841660048201529290911660248301526044820152606401602060405180830381600087803b158015610b2e57600080fd5b505af1158015610b42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b669190612901565b505050565b6000546001600160a01b03163314610b955760405162461bcd60e51b815260040161068290612d2f565b6064821115610bb65760405162461bcd60e51b815260040161068290612d64565b60008381526008602090815260409182902084815560010180546001600160a01b0319166001600160a01b0385169081179091558251868152918201859052918101919091527f5d5c9f9b29dc8b774ec7ab6c8cc1ca18081609a2a1ce835a31e18a8cfe1f5bce90606001610925565b6000546001600160a01b03163314610c505760405162461bcd60e51b815260040161068290612d2f565b600554604080516001600160a01b03928316815291831660208301527fe1a5430ebec577336427f40f15822f1f36c5e3509ff209d6db9e6c9e6941cb0b910160405180910390a1600580546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610ce35760405162461bcd60e51b815260040161068290612d2f565b6000816001600160a01b031663ae25532e6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1e57600080fd5b505afa158015610d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d569190612a09565b6001600160e01b0319811660008181526002602090815260409182902080546001600160a01b0319166001600160a01b0388169081179091558251938452908301529192507fd2c6b762299c609bdb96520b58a49bfb80186934d4f71a86a367571a15c0319491016106e8565b6000546001600160a01b03163314610ded5760405162461bcd60e51b815260040161068290612d2f565b60045460408051918252602082018390527fd6af4e0ae346a7e53efebd270fb369edb05c20aab0b87232b5ba50d9d238fc62910160405180910390a1600455565b600060026001541415610e835760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610682565b6002600155610e9485858486611835565b9050610e9e6118f1565b60018055949350505050565b600060026001541415610eff5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610682565b6002600155610f1084843385611835565b9050610f1a6118f1565b600180559392505050565b6000546001600160a01b03163314610f4f5760405162461bcd60e51b815260040161068290612d2f565b60405133904780156108fc02916000818181858888f19350505050158015610a2d573d6000803e3d6000fd5b6000546001600160a01b03163314610fa55760405162461bcd60e51b815260040161068290612d2f565b6001600160a01b03811661100a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610682565b610a2d81611310565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b611096604080516080810190915280600081526020016000815260006020820181905260409091015290565b6006546110a49083906112b3565b60408201526101408201516000906110bb90611925565b905060006110cd846101200151611925565b90508180156110da575080155b1561110f576020830160015b9081600381111561110757634e487b7160e01b600052602160045260246000fd5b90525061114e565b8115801561111a5750805b1561112a576020830160026110e6565b81158015611136575080155b15611146576020830160036110e6565b600060208401525b6080840151611187578260015b9081600781111561117c57634e487b7160e01b600052602160045260246000fd5b815250505050919050565b60a08401516111985782600261115b565b6001836020015160038111156111be57634e487b7160e01b600052602160045260246000fd5b1480156111d257508360a001518460c00151115b156111df5782600361115b565b60028360200151600381111561120557634e487b7160e01b600052602160045260246000fd5b148015611219575083608001518460c00151115b156112265782600361115b565b60408084015160009081526009602052205460ff16156112485782600661115b565b6040808401516000908152600a602052205460ff161561126a5782600761115b565b61010084015184516001600160a01b03166000908152600b602052604090205411156112985782600761115b565b8360e0015142106112ab5782600561115b565b82600461115b565b60006112e1826112c28561194c565b60405161190160f01b8152600281019290925260228201526042902090565b9392505050565b8251600090816112f88285611360565b90506113068186848761152c565b9695505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60008151600014156113845760405162461bcd60e51b815260040161068290612cf8565b81600183516113939190612e70565b815181106113b157634e487b7160e01b600052603260045260246000fd5b016020015160f81c60048111156113d857634e487b7160e01b600052602160045260246000fd5b90506001600160a01b0383166114405760405162461bcd60e51b815260206004820152602760248201527f5349474e41545552453a207369676e6572416464726573732063616e6e6f74206044820152661899481b9d5b1b60ca1b6064820152608401610682565b6004818181111561146157634e487b7160e01b600052602160045260246000fd5b60ff16106114bc5760405162461bcd60e51b815260206004820152602260248201527f5349474e41545552453a207369676e6174757265206e6f7420737570706f7274604482015261195960f21b6064820152608401610682565b60008160048111156114de57634e487b7160e01b600052602160045260246000fd5b14156107665760405162461bcd60e51b815260206004820152601c60248201527f5349474e41545552453a20696c6c6567616c207369676e6174757265000000006044820152606401610682565b6000600185600481111561155057634e487b7160e01b600052602160045260246000fd5b141561157f5781516001146115775760405162461bcd60e51b815260040161068290612cf8565b506000610957565b60028560048111156115a157634e487b7160e01b600052602160045260246000fd5b141561168e5781516042146115c85760405162461bcd60e51b815260040161068290612cf8565b6000826000815181106115eb57634e487b7160e01b600052603260045260246000fd5b016020015160f81c905060006116028460016119c6565b905060006116118560216119c6565b604080516000808252602082018084528b905260ff87169282019290925260608101859052608081018390529192509060019060a0016020604051602081039080840390855afa158015611669573d6000803e3d6000fd5b5050604051601f1901516001600160a01b038981169116149550610957945050505050565b60038560048111156116b057634e487b7160e01b600052602160045260246000fd5b14156109575781516042146116d75760405162461bcd60e51b815260040161068290612cf8565b6000826000815181106116fa57634e487b7160e01b600052603260045260246000fd5b016020015160f81c905060006117118460016119c6565b905060006117208560216119c6565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101899052909150600090600190605c0160408051601f198184030181528282528051602091820120600084529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156117ba573d6000803e3d6000fd5b5050604051601f1901516001600160a01b0389811691161495505050505050949350505050565b60006117ec8261106a565b90506117f782611a5f565b60048151600781111561181a57634e487b7160e01b600052602160045260246000fd5b14611823575050565b611831828260400151611b24565b5050565b6000806118418661106a565b905061184f86828688611b99565b604080820151600081815260096020908152838220805460ff19166001908117909155878352600882528483208551606081018752815481529101546001600160a01b03811692820192909252600160a01b90910460ff16151593810193909352909190806118c0858b8a86611f87565b915091506118d28a858a858b86612230565b50505060009081526009602052604090205460ff169695505050505050565b478015610a2d57604051339082156108fc029083906000818181858888f19350505050158015611831573d6000803e3d6000fd5b60008061193283826122b4565b6001600160e01b031916630f47261b60e41b149392505050565b6101208101516101408201516000917f85eeee70c9e228559a0ea5492e9915b70dab1efedd40807802f996020d88dc2e91602085101561198857fe5b601f19850180516101208701805161014090980180519684528551602096870120825284519490950193909320845261018082209152949052525090565b60006119d3826020612e25565b83511015611a495760405162461bcd60e51b815260206004820152603c60248201527f4c49422042595445533a206c656e6774682067726561746572207468616e206f60448201527f7220657175616c73207468697274792074776f207265717569726564000000006064820152608401610682565b611a54602083612e25565b929092015192915050565b60608101516001600160a01b031615611ac95760608101516001600160a01b03163314611ac95760405162461bcd60e51b815260206004820152601860248201527722ac21a420a723a29d1034b73b30b634b21039b2b73232b960411b6044820152606401610682565b805133906001600160a01b031681146118315760405162461bcd60e51b815260206004820152601760248201527f45584348414e47453a20696e76616c6964206d616b65720000000000000000006044820152606401610682565b6000818152600a602052604090819020805460ff191660011790558251610120840151610140850151925184936001600160a01b03909316927fe35250280688e0425977df1ac938278234930716fe16d305fb38c7ea55a1aee292611b8d929091903390612c34565b60405180910390a35050565b600083602001516003811115611bbf57634e487b7160e01b600052602160045260246000fd5b1415611c065760405162461bcd60e51b8152602060048201526016602482015275115610d2105391d14e881d1e5c19481a5b1b1959d85b60521b6044820152606401610682565b600183602001516003811115611c2c57634e487b7160e01b600052602160045260246000fd5b1415611cb157610140840151600090611c4690600461234f565b90506001600160a01b038116158015611c6257508460a0015134105b15611caf5760405162461bcd60e51b815260206004820152601a60248201527f45584348414e47453a2077726f6e672076616c75652073656e740000000000006044820152606401610682565b505b600183602001516003811115611cd757634e487b7160e01b600052602160045260246000fd5b14158015611cee57506001600160a01b0382163314155b15611d565760405162461bcd60e51b815260206004820152603260248201527f45584348414e47453a2066696c6c206f7264657220666f72206973206f6e6c796044820152712076616c696420666f7220627579206e6f7760701b6064820152608401610682565b600383602001516003811115611d7c57634e487b7160e01b600052602160045260246000fd5b1415611dd457600454341015611dd45760405162461bcd60e51b815260206004820152601a60248201527f45584348414e47453a2077726f6e672076616c75652073656e740000000000006044820152606401610682565b600483516007811115611df757634e487b7160e01b600052602160045260246000fd5b14611e445760405162461bcd60e51b815260206004820152601d60248201527f45584348414e47453a20737461747573206e6f742066696c6c61626c650000006044820152606401610682565b60608401516001600160a01b031615611eae5760608401516001600160a01b03163314611eae5760405162461bcd60e51b815260206004820152601860248201527722ac21a420a723a29d1034b73b30b634b21039b2b73232b960411b6044820152606401610682565b60208401516001600160a01b031615611f2657816001600160a01b031684602001516001600160a01b031614611f265760405162461bcd60e51b815260206004820152601760248201527f45584348414e47453a20696e76616c69642074616b65720000000000000000006044820152606401610682565b611f35848460400151836112e8565b611f815760405162461bcd60e51b815260206004820152601b60248201527f45584348414e47453a20696e76616c6964207369676e617475726500000000006044820152606401610682565b50505050565b6000806060808280808060018c602001516003811115611fb757634e487b7160e01b600052602160045260246000fd5b1415611fe357505050610140880151610120890151895160a08b015160808c0151939650919450339350915b60028c60200151600381111561200957634e487b7160e01b600052602160045260246000fd5b1480612038575060038c60200151600381111561203657634e487b7160e01b600052602160045260246000fd5b145b15612069578a610120015195508a610140015194508a6000015193503392508399508a6080015191508a60a0015190505b6005546001600160a01b0316156121be578560038d6020015160038111156120a157634e487b7160e01b600052602160045260246000fd5b1480156120b057506000600454115b156120fc57506004546040805160006024808301919091528251808303909101815260449091019091526020810180516001600160e01b0316630f47261b60e41b179052909850612134565b60035415612134576121256103e861211f600354866123f190919063ffffffff16565b906123fd565b9850612131838a612409565b92505b89604001518015612151575060208a01516001600160a01b031615155b801561215d5750895115155b801561216b575060075460ff165b156121a25789516121849060649061211f908c906123f1565b97506121908989612409565b98506121a281868c602001518b612415565b6005546121bc90829087906001600160a01b03168c612415565b505b60408b01516001600160a01b0316158015906121de575060008b60c00151115b156122095760c08b01516121f3908390612409565b915061220986858d604001518e60c00151612415565b61221586858585612415565b61222185848c84612415565b50505050505094509492505050565b8486604001516001600160a01b031687600001516001600160a01b03167f35d3c32d322e234e99b7f37b3ff4cb69c8a4027a04bee33d3a716da66ee1e6a18961012001518a610140015189338d608001518e60a001518f60c001518d8d8d6040516122a49a99989796959493929190612c72565b60405180910390a4505050505050565b60006122c1826004612e25565b835110156123305760405162461bcd60e51b815260206004820152603660248201527f4c49422042595445533a206c656e6774682067726561746572207468616e206f6044820152751c88195c5d585b1cc8199bdd5c881c995c5d5a5c995960521b6064820152608401610682565b61233b602083612e25565b909201516001600160e01b03191692915050565b600061235c826014612e25565b835110156123d25760405162461bcd60e51b815260206004820152603860248201527f4c49422042595445533a206c656e6774682067726561746572207468616e206f60448201527f7220657175616c73207477656e747920726571756972656400000000000000006064820152608401610682565b6123dd601483612e25565b92909201516001600160a01b031692915050565b60006112e18284612e51565b60006112e18284612e3d565b60006112e18284612e70565b8015611f8157602084516124299190612eee565b6004146124785760405162461bcd60e51b815260206004820152601b60248201527f41535345542050524f58593a20696e76616c6964206c656e67746800000000006044820152606401610682565b600061248485826122b4565b6001600160e01b031981166000908152600260205260409020549091506001600160a01b0316806124ee5760405162461bcd60e51b815260206004820152601460248201527320a9a9a2aa10282927ac2c9d103ab735b737bbb760611b6044820152606401610682565b60006001600160e01b03198316630f47261b60e41b141561252457600061251688600461234f565b6001600160a01b0316159150505b801561262d57834710156125845760405162461bcd60e51b815260206004820152602160248201527f41535345542050524f58593a20696e73756666696369656e742062616c616e636044820152606560f81b6064820152608401610682565b6000856001600160a01b03168560405160006040518083038185875af1925050503d80600081146125d1576040519150601f19603f3d011682016040523d82523d6000602084013e6125d6565b606091505b50509050806126275760405162461bcd60e51b815260206004820181905260248201527f41535345542050524f58593a20657468207472616e73666572206661696c65646044820152606401610682565b50612733565b600063a85e59e460e01b8888888860405160240161264e9493929190612bfe565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b03838183161783525050505090506000836001600160a01b03168260405161269d9190612be2565b6000604051808303816000865af19150503d80600081146126da576040519150601f19603f3d011682016040523d82523d6000602084013e6126df565b606091505b50509050806127305760405162461bcd60e51b815260206004820152601c60248201527f41535345542050524f58593a207472616e73666572206661696c6564000000006044820152606401610682565b50505b50505050505050565b80356001600160a01b038116811461275357600080fd5b919050565b600082601f830112612768578081fd5b813567ffffffffffffffff8082111561278357612783612f44565b604051601f8301601f19908116603f011681019082821181831017156127ab576127ab612f44565b816040528381528660208588010111156127c3578485fd5b8360208701602083013792830160200193909352509392505050565b600061016082840312156127f1578081fd5b6127f9612dfb565b90506128048261273c565b81526128126020830161273c565b60208201526128236040830161273c565b60408201526128346060830161273c565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013567ffffffffffffffff8082111561288a57600080fd5b61289686838701612758565b838501526101409250828501359150808211156128b257600080fd5b506128bf85828601612758565b82840152505092915050565b6000602082840312156128dc578081fd5b6112e18261273c565b6000602082840312156128f6578081fd5b81356112e181612f5a565b600060208284031215612912578081fd5b81516112e181612f5a565b60006020828403121561292e578081fd5b5035919050565b600080600060608486031215612949578182fd5b833592506129596020850161273c565b9150604084013567ffffffffffffffff811115612974578182fd5b61298086828701612758565b9150509250925092565b6000806040838503121561299c578182fd5b8235915060208301356129ae81612f5a565b809150509250929050565b6000806000606084860312156129cd578283fd5b83359250602084013591506129e46040850161273c565b90509250925092565b6000602082840312156129fe578081fd5b81356112e181612f68565b600060208284031215612a1a578081fd5b81516112e181612f68565b600060208284031215612a36578081fd5b813567ffffffffffffffff811115612a4c578182fd5b610957848285016127df565b60008060408385031215612a6a578182fd5b823567ffffffffffffffff80821115612a81578384fd5b612a8d868387016127df565b93506020850135915080821115612aa2578283fd5b50612aaf85828601612758565b9150509250929050565b600080600060608486031215612acd578283fd5b833567ffffffffffffffff80821115612ae4578485fd5b612af0878388016127df565b94506020860135915080821115612b05578384fd5b50612b1286828701612758565b925050604084013590509250925092565b60008060008060808587031215612b38578182fd5b843567ffffffffffffffff80821115612b4f578384fd5b612b5b888389016127df565b95506020870135915080821115612b70578384fd5b50612b7d87828801612758565b93505060408501359150612b936060860161273c565b905092959194509250565b600060208284031215612baf578081fd5b5051919050565b60008151808452612bce816020860160208601612e87565b601f01601f19169290920160200192915050565b60008251612bf4818460208701612e87565b9190910192915050565b608081526000612c116080830187612bb6565b6001600160a01b0395861660208401529390941660408201526060015292915050565b606081526000612c476060830186612bb6565b8281036020840152612c598186612bb6565b91505060018060a01b0383166040830152949350505050565b6000610140808352612c868184018e612bb6565b90508281036020840152612c9a818d612bb6565b6001600160a01b039b8c16604085015299909a16606083015250608081019690965260a086019490945260c085019290925260e0840152610100830152610120909101529392505050565b6020815260006112e16020830184612bb6565b60208082526019908201527f5349474e41545552453a20696e76616c6964206c656e67746800000000000000604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526026908201527f666565206d756c7469706c696572206d7573742062652062657477656e2030206040820152650746f203130360d41b606082015260800190565b8151608082019060088110612dc157612dc1612f2e565b8252602083015160048110612dd857612dd8612f2e565b806020840152506040830151604083015260608301511515606083015292915050565b604051610160810167ffffffffffffffff81118282101715612e1f57612e1f612f44565b60405290565b60008219821115612e3857612e38612f02565b500190565b600082612e4c57612e4c612f18565b500490565b6000816000190483118215151615612e6b57612e6b612f02565b500290565b600082821015612e8257612e82612f02565b500390565b60005b83811015612ea2578181015183820152602001612e8a565b83811115611f815750506000910152565b600181811c90821680612ec757607f821691505b60208210811415612ee857634e487b7160e01b600052602260045260246000fd5b50919050565b600082612efd57612efd612f18565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b8015158114610a2d57600080fd5b6001600160e01b031981168114610a2d57600080fdfea2646970667358221220536b4b58dcda1e30932d5d1b747e7d1fa4a8589b1ea07d2c591b17c318f79c3064736f6c63430008040033000000000000000000000000000000000000000000000000000000000000a86a

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

000000000000000000000000000000000000000000000000000000000000a86a

-----Decoded View---------------
Arg [0] : chainId (uint256): 43114

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000000000000000000000000000000000000000a86a


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.