Contract 0xBBE52b3Df581B9e3127A23a514f96De2D9a78a26

Txn Hash Method
Block
From
To
Value [Txn Fee]
0xdae518ce896bddc49054686910910ec2ad710a56c418bfbdeda37f7f01ab63fcTransfer Ownersh...13435602022-06-30 15:12:36456 days 17 hrs ago0x1476e2069503fc7a1c8969f920d786fccdfa5b78 IN  0xbbe52b3df581b9e3127a23a514f96de2d9a78a260 GLMR0.00264721
0x7adec955b94b520dade04be229b8cdd879647fed7fd3c50f46b8008080f1fd65Enable Supported...10390582022-05-16 16:40:12501 days 16 hrs ago0x1476e2069503fc7a1c8969f920d786fccdfa5b78 IN  0xbbe52b3df581b9e3127a23a514f96de2d9a78a260 GLMR0.0047387
0xedbba7db50288afc35e8ac3b1b63f084ae57802d6bbd9001705c81926ee71cbbAdd Supported Bo...10390562022-05-16 16:39:48501 days 16 hrs ago0x1476e2069503fc7a1c8969f920d786fccdfa5b78 IN  0xbbe52b3df581b9e3127a23a514f96de2d9a78a260 GLMR0.0046661
0x9e8c966926735bae69e46ef0d754bdaadf3d320f8913d1579f8650488d4c2f96Add Supported Bo...10390542022-05-16 16:39:24501 days 16 hrs ago0x1476e2069503fc7a1c8969f920d786fccdfa5b78 IN  0xbbe52b3df581b9e3127a23a514f96de2d9a78a260 GLMR0.0046661
0x11fb2803af765d9ddde967d7c8a3127526c3a05f057749912e6a37b85ff565bf0x6080604010389102022-05-16 16:09:54501 days 16 hrs ago0x1476e2069503fc7a1c8969f920d786fccdfa5b78 IN  Create: NftSwap0 GLMR0.536023545
[ Download CSV Export 
Parent Txn Hash Block From To Value
Index Block
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
NftSwap

Compiler Version
v0.6.7+commit.b8d736ae

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 15 : NftSwap.sol
pragma solidity 0.6.7;
pragma experimental ABIEncoderV2;

import "./../openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./../openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "./../openzeppelin/contracts/token/ERC721/IERC721.sol";
import "./../openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "./../openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./../openzeppelin/contracts/access/Ownable.sol";
import "./NftParamsInterface.sol";
import "./SwapSigner.sol";
import "./Crowns.sol";

/// @title Nft Swap is a part of Seascape marketplace platform.
/// It allows users to obtain desired nfts in exchange for their offered nfts,
/// a fee and an optional bounty
/// @author Nejc Schneider
contract NftSwap is Crowns, Ownable, ReentrancyGuard, IERC721Receiver {
    using SafeERC20 for IERC20;

    SwapSigner private swapSigner;

    uint256 public lastOfferId;             /// @dev keep count of offers (aka offerIds)
    bool public tradeEnabled = true;        /// @dev enable/disable create and accept offer
    uint256 public fee;                     /// @dev fee for creating an offer

    struct OfferObject{
        uint256 offerId;                   // offer ID
        uint8 offeredTokensAmount;         // total offered tokens
        uint8 requestedTokensAmount;       // total requested tokens
        uint256 bounty;                    // reward for the buyer
        address bountyAddress;             // currency address for paying bounties
        address payable seller;            // seller's address
        uint256 fee;                       // fee amount at the time offer was created
        mapping(uint256 => OfferedToken) offeredTokens;       // offered tokens data
        mapping(uint256 => RequestedToken) requestedTokens;   // requested tokensdata
    }

    struct OfferedToken{
        uint256 tokenId;                    // offered token id
        address tokenAddress;               // offered token address
    }

    struct RequestedToken{
        address tokenAddress;              // requested token address
        bytes tokenParams;                 // requested token Params
        uint8 v;
        bytes32 r;
        bytes32 s;
    }

    /// @dev store offer objects.
    /// @param offerId => OfferObject
    mapping(uint256 => OfferObject) offerObjects;
    /// @dev supported ERC721 and ERC20 contracts
    mapping(address => bool) public supportedBountyAddresses;
    /// @dev parse params contract addresses (1 per individual nftSeries)
    /// @param nftAddress => nftParams contract address
    mapping(address => address) public supportedNftAddresses;

    event CreateOffer(
        uint256 indexed offerId,
        address indexed seller,
        uint256 bounty,
        address indexed bountyAddress,
        uint256 fee,
        uint256 offeredTokensAmount,
        uint256 requestedTokensAmount,
        OfferedToken [5] offeredTokens,
        RequestedToken [5] requestedTokens
    );

    event AcceptOffer(
        uint256 indexed offerId,
        address indexed buyer,
        uint256 bounty,
        address indexed bountyAddress,
        uint256 fee,
        uint256 requestedTokensAmount,
        uint256 [5] requestedTokenIds,
        uint256 offeredTokensAmount,
        uint256 [5] offeredTokenIds
    );

    event CancelOffer(
        uint256 indexed offerId,
        address indexed seller
    );

    event NftReceived(address operator, address from, uint256 tokenId, bytes data);
    event Received(address, uint);

    /// @param _feeRate - fee amount
    /// @param _crownsAddress staking currency address
    constructor(uint256 _feeRate, address _crownsAddress, address _signerAddress) public {
        /// @dev set crowns is defined in Crowns.sol
        require(_crownsAddress != address(0x0), "invalid cws address");
        setCrowns(_crownsAddress);
        fee = _feeRate;
        swapSigner = SwapSigner(_signerAddress);
    }

    //--------------------------------------------------
    // External methods
    //--------------------------------------------------

    fallback() external payable {
        emit Received(msg.sender, msg.value);
    }

    /// @notice enable/disable createOffer() and acceptOffer() functionality
    /// @param _tradeEnabled set tradeEnabled to true/false
    function enableTrade(bool _tradeEnabled) external onlyOwner { tradeEnabled = _tradeEnabled; }

    /// @notice enable additional nft series
    /// @param _nftAddress ERC721 contract address
    // @param _nftParamsAddress SwapParams contract address
    function enableSupportedNftAddress(
        address _nftAddress,
        address _nftParamsAddress
    )
        external
        onlyOwner
    {
        require(_nftAddress != address(0x0), "invalid nft address");
        require(_nftParamsAddress != address(0x0), "invalid NftParams address");
        require(supportedNftAddresses[_nftAddress] == address(0x0),
            "nft address already enabled");
        supportedNftAddresses[_nftAddress] = _nftParamsAddress;
    }

    /// @notice disable nft series
    /// @param _nftAddress ERC721 contract address
    function disableSupportedNftAddress(address _nftAddress) external onlyOwner {
        require(_nftAddress != address(0x0), "invalid address");
        require(supportedNftAddresses[_nftAddress] != address(0),
            "nft address already disabled");
        supportedNftAddresses[_nftAddress] = address(0x0);
    }

    /// @notice enable additional bounty currency
    /// @param _bountyAddress ERC20 contract address
    function addSupportedBountyAddress(address _bountyAddress) external onlyOwner {
        require(!supportedBountyAddresses[_bountyAddress], "bounty already supported");
        supportedBountyAddresses[_bountyAddress] = true;
    }

    /// @notice disable supported bounty currency
    /// @param _bountyAddress ERC20 contract address
    function removeSupportedBountyAddress(address _bountyAddress) external onlyOwner {
        require(supportedBountyAddresses[_bountyAddress], "bounty already removed");
        supportedBountyAddresses[_bountyAddress] = false;
    }

    /// @notice update fee value. Change will only apply to new offers.
    /// @param _feeRate set fee to this value.
    function setFee(uint256 _feeRate) external onlyOwner { fee = _feeRate; }

    /// @notice returns amount of offers
    /// @return total amount of offer objects
    function getLastOfferId() external view returns(uint) { return lastOfferId; }

    /// @dev returns all properties of offer object at _offerId element
    /// @return elements of OfferObject at given index
    function getOffer(uint _offerId)
        external
        view
        returns(uint256, uint8, uint8, uint256, address, address, uint256)
    {
        return (
        offerObjects[_offerId].offerId,
        offerObjects[_offerId].offeredTokensAmount,
        offerObjects[_offerId].requestedTokensAmount,
        offerObjects[_offerId].bounty,
        offerObjects[_offerId].bountyAddress,
        offerObjects[_offerId].seller,
        offerObjects[_offerId].fee
        );
    }

    //--------------------------------------------------
    // Public methods
    //--------------------------------------------------

    /// @notice by creating a new offer, msg.sender will transfer offered tokens,
    /// fee and an optional bounty to the contract
    /// @param _offeredTokens array of five OfferedToken structs
    /// @param _requestedTokens array of five RequestedToken structs
    /// @param _bounty additional coins to offer to buyer
    /// @return lastOfferId total amount of offers
    function createOffer(
        uint8 _offeredTokensAmount,
        OfferedToken [5] memory _offeredTokens,
        uint8 _requestedTokensAmount,
        RequestedToken [5] memory _requestedTokens,
        uint256 _bounty,
        address _bountyAddress
    )
        public
        payable
        returns(uint256)
    {
        /// require statements
        require(tradeEnabled, "trade is disabled");
        require(_offeredTokensAmount > 0, "should offer at least one nft");
        require(_offeredTokensAmount <= 5, "cant offer more than 5 tokens");
        require(_requestedTokensAmount > 0, "should require at least one nft");
        require(_requestedTokensAmount <= 5, "cant request more than 5 tokens");
        // bounty & fee related requirements
        if (_bounty > 0) {
            if (address(crowns) == _bountyAddress) {
                require(crowns.balanceOf(msg.sender) >= fee + _bounty,
                    "not enough CWS for fee & bounty");
            } else {
                require(supportedBountyAddresses[_bountyAddress],
                    "bounty address not supported");

                if (_bountyAddress == address(0x0)) {
                    require (msg.value >= _bounty, "insufficient transfer amount");
                    uint256 returnBack = msg.value - _bounty;
                    if (returnBack > 0)
                        msg.sender.transfer(returnBack);
                } else {
                    IERC20 currency = IERC20(_bountyAddress);
                    require(currency.balanceOf(msg.sender) >= _bounty,
                        "not enough money to pay bounty");
                }
            }
        } else {
            require(crowns.balanceOf(msg.sender) >= fee, "not enough CWS for fee");
        }
        /// input token verification
        // verify offered nft oddresses and ids
        for (uint index = 0; index < _offeredTokensAmount; ++index) {
            // the following checks should only apply if slot at index is filled.
            require(supportedNftAddresses[_offeredTokens[index].tokenAddress] != address(0),
                "offered nft address unsupported");
            IERC721 nft = IERC721(_offeredTokens[index].tokenAddress);
            require(nft.ownerOf(_offeredTokens[index].tokenId) == msg.sender,
                "sender not owner of nft");
        }
        // verify requested nft oddresses
        for (uint _index = 0; _index < _requestedTokensAmount; ++_index) {
            address nftParamsAddress = supportedNftAddresses[_requestedTokens[_index].tokenAddress];
            require(nftParamsAddress != address(0),
                "requested nft address unsupported");
            // verify nft parameters
            // external but trusted contract maintained by Seascape
            NftParamsInterface requestedToken = NftParamsInterface (nftParamsAddress);
            require(requestedToken.paramsAreValid(lastOfferId, _requestedTokens[_index].tokenParams,
              _requestedTokens[_index].v, _requestedTokens[_index].r, _requestedTokens[_index].s),
                "invalid nft Params");
        }

        /// make transactions
        // send offered nfts to smart contract
        for (uint index = 0; index < _offeredTokensAmount; ++index) {
            // send nfts to contract
            IERC721(_offeredTokens[index].tokenAddress)
                .safeTransferFrom(msg.sender, address(this), _offeredTokens[index].tokenId);
        }
        // send fee and _bounty to contract
        if (_bounty > 0) {
            if (_bountyAddress == address(crowns)) {
                IERC20(crowns).safeTransferFrom(msg.sender, address(this), fee + _bounty);
            } else {
                if (_bountyAddress == address(0)) {
                    address(this).transfer(_bounty);
                } else {
                    IERC20(_bountyAddress).safeTransferFrom(msg.sender, address(this), _bounty);
                }
                IERC20(crowns).safeTransferFrom(msg.sender, address(this), fee);
            }
        } else {
            IERC20(crowns).safeTransferFrom(msg.sender, address(this), fee);
        }

        /// update states
        lastOfferId++;

        offerObjects[lastOfferId].offerId = lastOfferId;
        offerObjects[lastOfferId].offeredTokensAmount = _offeredTokensAmount;
        offerObjects[lastOfferId].requestedTokensAmount = _requestedTokensAmount;
        for(uint256 i = 0; i < _offeredTokensAmount; ++i){
            offerObjects[lastOfferId].offeredTokens[i] = _offeredTokens[i];
        }
        for(uint256 i = 0; i < _requestedTokensAmount; ++i){
            offerObjects[lastOfferId].requestedTokens[i] = _requestedTokens[i];
        }
        offerObjects[lastOfferId].bounty = _bounty;
        offerObjects[lastOfferId].bountyAddress = _bountyAddress;
        offerObjects[lastOfferId].seller = msg.sender;
        offerObjects[lastOfferId].fee = fee;

        /// emit events
        emit CreateOffer(
            lastOfferId,
            msg.sender,
            _bounty,
            _bountyAddress,
            fee,
            _offeredTokensAmount,
            _requestedTokensAmount,
            _offeredTokens,
            _requestedTokens
          );

        return lastOfferId;
    }

    /// @notice by accepting offer, buyer will transfer requested tokens to the seller,
    /// in exchange for offered tokens and an optional bounty. Fee is spend.
    function acceptOffer(
        uint256 _offerId,
        uint256 [5] memory _requestedTokenIds,
        address [5] memory _requestedTokenAddresses,
        uint8 [5] memory _v,
        bytes32 [5] memory _r,
        bytes32 [5] memory _s
    )
        public
        nonReentrant
        payable
    {
        OfferObject storage obj = offerObjects[_offerId];
        require(tradeEnabled, "trade is disabled");
        require(msg.sender != obj.seller, "cant buy self-made offer");

        /// @dev verify requested tokens
        for(uint256 i = 0; i < obj.requestedTokensAmount; ++i){
            require(_requestedTokenAddresses[i] == obj.requestedTokens[i].tokenAddress,
                "wrong requested token address");
            IERC721 nft = IERC721(obj.requestedTokens[i].tokenAddress);
            require(nft.ownerOf(_requestedTokenIds[i]) == msg.sender,
                "sender not owner of nft");
            /// digital signature part
            bytes32 _messageNoPrefix = keccak256(abi.encodePacked(
                _offerId,
                _requestedTokenIds[i],
                _requestedTokenAddresses[i],
                msg.sender
            ));
            bytes32 _message = keccak256(abi.encodePacked(
                "\x19Ethereum Signed Message:\n32", _messageNoPrefix));
            address _recover = ecrecover(_message, _v[i], _r[i], _s[i]);
            require(_recover == swapSigner.getSigner(),  "Verification failed");
        }

        /// make transactions
        // send requestedTokens from buyer to seller
        for (uint index = 0; index < obj.requestedTokensAmount; ++index) {
            IERC721(_requestedTokenAddresses[index])
                .safeTransferFrom(msg.sender, obj.seller, _requestedTokenIds[index]);
        }
        // send offeredTokens from SC to buyer
        for (uint index = 0; index < obj.offeredTokensAmount; ++index) {
            IERC721(obj.offeredTokens[index].tokenAddress)
                .safeTransferFrom(address(this), msg.sender, obj.offeredTokens[index].tokenId);
        }
        // spend obj.fee and send obj.bounty from SC to buyer
        crowns.spend(obj.fee);
        if(obj.bounty > 0) {
            if(obj.bountyAddress == address(0))
                msg.sender.transfer(obj.bounty);
            else
                IERC20(obj.bountyAddress).safeTransfer(msg.sender, obj.bounty);
        }

        /// emit events
        emit AcceptOffer(
            obj.offerId,
            msg.sender,
            obj.bounty,
            obj.bountyAddress,
            obj.fee,
            obj.requestedTokensAmount,
            _requestedTokenIds,
            obj.offeredTokensAmount,
            [obj.offeredTokens[0].tokenId,
            obj.offeredTokens[1].tokenId,
            obj.offeredTokens[2].tokenId,
            obj.offeredTokens[3].tokenId,
            obj.offeredTokens[4].tokenId]
        );

        /// update states
        delete offerObjects[_offerId];
    }

    /// @notice offered tokens, fee, and an optional bounty is returned to seller
    /// @param _offerId offer unique ID
    function cancelOffer(uint _offerId) public nonReentrant {
        OfferObject storage obj = offerObjects[_offerId];
        require(obj.seller == msg.sender, "sender is not creator of offer");

        /// make transactions
        // send the offeredTokens from SC to seller
        for (uint index=0; index < obj.offeredTokensAmount; ++index) {
            IERC721(obj.offeredTokens[index].tokenAddress)
                .safeTransferFrom(address(this), obj.seller, obj.offeredTokens[index].tokenId);
        }

        // send crowns and bounty from SC to seller
        if (obj.bounty > 0) {
            if (obj.bountyAddress == address(crowns)) {
                crowns.transfer(msg.sender, obj.fee + obj.bounty);
            } else {
                if (obj.bountyAddress == address(0)) {
                    msg.sender.transfer(obj.bounty);
                } else {
                    IERC20(obj.bountyAddress).safeTransfer(msg.sender, obj.bounty);
                }
                crowns.transfer(msg.sender, obj.fee);
            }
        } else {
            crowns.transfer(msg.sender, obj.fee);
        }

        /// emit events
        emit CancelOffer(
            obj.offerId,
            obj.seller
        );

        /// update states
        delete offerObjects[_offerId];
    }

    /// @dev encrypt token data
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes memory data
    )
        public
        override
        returns (bytes4)
    {
        //only receive the _nft staff
        if (address(this) != operator) {
            //invalid from nft
            return 0;
        }

        //success
        emit NftReceived(operator, from, tokenId, data);
        return bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
    }

}

File 2 of 15 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.2;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 3 of 15 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data)
    external returns (bytes4);
}

File 4 of 15 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.2;

import "../../introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transfered from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
      * @dev Safely transfers `tokenId` token from `from` to `to`.
      *
      * Requirements:
      *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
      * - `tokenId` token must exist and be owned by `from`.
      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
      *
      * Emits a {Transfer} event.
      */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}

File 5 of 15 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 6 of 15 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    function decimals() external view returns (uint8);

    /**
     * @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 7 of 15 : ReentrancyGuard.sol
// File: contracts/library/ReentrancyGuard.sol

pragma solidity ^0.6.7;

contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() internal {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // 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;

        _;

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

    function initReentrancyStatus() internal {
        _status = _NOT_ENTERED;
    }
}

File 8 of 15 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

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

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

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

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

        return c;
    }

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

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

File 9 of 15 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 10 of 15 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

import "../GSN/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.
 */
contract Ownable is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(_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 {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

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

File 11 of 15 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

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

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 12 of 15 : SwapSigner.sol
pragma solidity 0.6.7;

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

/// @title SwapSigner holds address for signature verification.
/// It is used by NftSwap and SwapParams contracts.
/// @author Nejc Schneider
contract SwapSigner is Ownable {

    address public signer;         // @dev verify v, r, s signature

    constructor() public { signer = msg.sender; }

    /// @notice change address to verify signature against
    /// @param _signer new signer address
    function setSigner(address _signer) external onlyOwner {
        require(_signer != address(0), "invalid signer address");
        signer = _signer;
    }

    /// @notice returns verifier of signatures
    /// @return signer address
    function getSigner() external view returns(address) { return signer; }
}

File 13 of 15 : NftParamsInterface.sol
pragma solidity 0.6.7;


/// @dev Interface of the nftSwapParams

interface NftParamsInterface {

    /// @dev Returns true if signature is valid
    function paramsAreValid(uint256 _offerId, bytes calldata _encodedParams,
        uint8 v, bytes32 r, bytes32 s) external view returns (bool);

}

File 14 of 15 : Crowns.sol
pragma solidity 0.6.7;

import "./../crowns/erc-20/contracts/CrownsToken/CrownsToken.sol";

/// @dev Nft Rush and Leaderboard contracts both are with Crowns.
/// So, making Crowns available for both Contracts by moving it to another contract.
///
/// @author Medet Ahmetson
contract Crowns {
    CrownsToken public crowns;

   function setCrowns(address _crowns) internal {
        require(_crowns != address(0), "Crowns can't be zero address");
       	crowns = CrownsToken(_crowns);
   }
}

File 15 of 15 : CrownsToken.sol
// contracts/Crowns.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.6.7;

import "./../../../../openzeppelin/contracts/access/Ownable.sol";
import "./../../../../openzeppelin/contracts/GSN/Context.sol";
import "./../../../../openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./../../../../openzeppelin/contracts/math/SafeMath.sol";
import "./../../../../openzeppelin/contracts/utils/Address.sol";

/// @title Official token of the Seascape ecosystem.
/// @author Medet Ahmetson
/// @notice Crowns (CWS) is an ERC-20 token with a PayWave feature.
/// PayWave is a distribution of spent tokens among all current token holders.
/// In order to appear in balance, the paywaved tokens need
/// to be claimed by users by triggering any transaction in the ERC-20 contract.
/// @dev Implementation of the {IERC20} interface.
contract CrownsToken is Context, IERC20, Ownable {
    using SafeMath for uint256;
    using Address for address;

    struct Account {
        uint256 balance;
        uint256 lastPayWave;
    }

    mapping (address => Account) private _accounts;
    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private constant _name = "Crowns";
    string private constant _symbol = "CWS";
    uint8 private immutable _decimals = 18;

    uint256 private constant MIN_SPEND = 10 ** 6;
    uint256 private constant SCALER = 10 ** 18;
    uint256 private constant TEN_MILLION = SCALER * 1e7;


    /// @notice Total amount of tokens that have yet to be transferred to token holders as part of the PayWave.
    /// @dev Used Variable tracking unclaimed PayWave token amounts.
    uint256 public unclaimedPayWave = 0;
    /// @notice Amount of tokens spent by users that have not been paywaved yet.
    /// @dev Calling the payWave function will move the amount to {totalPayWave}
    uint256 public unconfirmedPayWave = 0;
    /// @notice Total amount of tokens that were paywaved overall.
    /// @dev Total paywaved tokens amount that is always increasing.
    uint256 public totalPayWave = 0;

    /// @notice Maximum possible supply of this token.
    uint256 public limitSupply = 0;

    /// @notice Set to false to stop mint/burn of token. Set to true to allow minting.
    bool public bridgeAllowed = false;

    /// @notice the list of bridge addresses allowed to mint tokens.
    mapping(address => bool) public bridges;

    // Mint and Burn
    modifier onlyBridge {
        require(bridgeAllowed && bridges[msg.sender]);
        _;
    }

    /**
     * @dev Emitted when `spent` tokens are moved
     * from `unconfirmedPayWave` to `totalPayWave`.
     */
    event PayWave(
        uint256 spent,
        uint256 totalPayWave
    );

    event AddBridge(address indexed bridge);
    event RemoveBridge(address indexed bridge);

    /**
     * @dev Sets the {name} and {symbol} of token.
     * Initializes {decimals} with a default value of 18.
     * Mints all tokens.
     * Transfers ownership to another account. So, the token creator will not be counted as an owner.
     * @param _type o minting:
     *      0 - ETH primary version of Token. Mints each pool to its dedicated multi-sig wallet account.
     *      1 - Test version to develop on local network. Mints all supply to one address.
     *      2 - Sidechain version of Token. Allows minting/burning of token to be done by third parties.
     */
    constructor (uint8 _type) public {
        if (_type == 1) {
            _mint(msg.sender,             10e6 * SCALER);
            return;
        } else if (_type == 0) {
            // Multi-sig wallet accounts to hold the pools and ownership.
            address gameIncentivesHolder = 0x94E169Be9037561aC37D8bb3471c7e35B81708A7;
            address liquidityHolder      = 0xf409fDF4069c825656ba3e1f931FCde8525F1bEE;
            address teamHolder           = 0x2Ff42929f444e496D7e856591764E00ee13b7077;
            address investHolder         = 0x2cfca4ccd9ef6d9420ae1ff26306d179DABAEdC2;
            address communityHolder      = 0x2C25ba4DB75D43e655647F24fB0cB2e896116dbD;
    	    address newOwner             = 0xbfdadB9a06C90B6625aF3C6DAc0Bb7f56a852886;

	        // 5 million tokens
            uint256 gameIncentives       = 5e6 * SCALER;
            // 1,5 million tokens
            uint256 reserve              = 15e5 * SCALER; // reserve for the next 5 years.
	        // 1 million tokens
	        uint256 community            = 1e6 * SCALER;
            uint256 team                 = 1e6 * SCALER;
            uint256 investment           = 1e6 * SCALER;
            // 500,000 tokens
            uint256 liquidity            = 5e5 * SCALER;

            _mint(gameIncentivesHolder,  gameIncentives);
            _mint(liquidityHolder,       liquidity);
            _mint(teamHolder,            team);
            _mint(investHolder,          investment);
            _mint(communityHolder,       community);
            _mint(newOwner,              reserve);

            transferOwnership(newOwner);
        } else {
            bridgeAllowed = true;
            limitSupply = 5e5 * SCALER;     // Initially it allows 500k tokens to mint
        }
   }

   function addBridge(address _bridge) external onlyOwner returns(bool) {
       require(_bridge != address(0), "Crowns: zero address");
       require(bridges[_bridge] == false, "Crowns: already added bridge");

       bridges[_bridge] = true;

       emit AddBridge(_bridge);
   }

    function removeBridge(address _bridge) external onlyOwner returns(bool) {
       require(_bridge != address(0), "Crowns: zero address");
       require(bridges[_bridge], "Crowns: not added bridge");

       bridges[_bridge] = false;

       emit RemoveBridge(_bridge);
   }

   function setLimitSupply(uint256 _newLimit) external onlyOwner returns(bool) {
       require(_newLimit > 0 && _newLimit <= TEN_MILLION, "Crowns: invalid supply limit");

       limitSupply = _newLimit;
   }

   /**
     * @dev Creates `amount` new tokens for `to`.
     *
     * See {ERC20-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(address to, uint256 amount) external onlyBridge {
        require(_totalSupply.add(amount) <= limitSupply, "Crowns: exceeds mint limit");
        _mint(to, amount);
    }

    /**
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     *
     * Included just to follow the standard of OpenZeppelin.
     */
    function burn(uint256 amount) public onlyBridge {
        require(false, "Only burnFrom is allowed");
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for ``accounts``'s tokens of at least
     * `amount`.
     */
    function burnFrom(address account, uint256 amount) public onlyBridge {
        uint256 currentAllowance = allowance(account, _msgSender());
        require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");

        _approve(account, _msgSender(), currentAllowance.sub(amount, "ERC20: transfer amount exceeds allowance"));
        _burn(account, amount);
    }

    function toggleBridgeAllowance() external onlyOwner {
        bridgeAllowed = !bridgeAllowed;
    }

    /**
     * @notice Return amount of tokens that {account} gets during the PayWave
     * @dev Used both internally and externally to calculate the PayWave amount
     * @param account is an address of token holder to calculate for
     * @return amount of tokens that player could get
     */
    function payWaveOwing (address account) public view returns(uint256) {
        Account memory _account = _accounts[account];

        uint256 newPayWave = totalPayWave.sub(_account.lastPayWave);
        uint256 proportion = _account.balance.mul(newPayWave);

        // The PayWave is not a part of total supply, since it was moved out of balances
        uint256 supply = _totalSupply.sub(newPayWave);

        // PayWave owed proportional to current balance of the account.
        // The decimal factor is used to avoid floating issue.
        uint256 payWave = proportion.mul(SCALER).div(supply).div(SCALER);

        return payWave;
    }

    /**
     * @dev Called before any edit of {account} balance.
     * Modifier moves the belonging PayWave amount to its balance.
     * @param account is an address of Token holder.
     */
    modifier updateAccount(address account) {
        uint256 owing = payWaveOwing(account);
        _accounts[account].lastPayWave = totalPayWave;

        if (owing > 0) {
            _accounts[account].balance    = _accounts[account].balance.add(owing);
            unclaimedPayWave     = unclaimedPayWave.sub(owing);

            emit Transfer(
                address(0),
                account,
                owing
            );
        }

        _;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public pure returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public pure returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view override returns (uint8) {
        return _decimals;
    }

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _getBalance(account);
    }

    /**
     * @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) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @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) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @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) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @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) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal updateAccount(sender) updateAccount(recipient) virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");
        require(amount > 0, "Can not send 0 token");
        require(_getBalance(sender) >= amount, "ERC20: Not enough token to send");

        _beforeTokenTransfer(sender, recipient, amount);

        _accounts[sender].balance =  _accounts[sender].balance.sub(amount);
        _accounts[recipient].balance = _accounts[recipient].balance.add(amount);

        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _accounts[account].balance = _accounts[account].balance.add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal updateAccount(account) virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _accounts[account].balance;
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        _accounts[account].balance = accountBalance.sub(amount);
        _totalSupply = _totalSupply.sub(amount);

        emit Transfer(account, address(0), amount);
    }

    function _spend(address account, uint256 amount) internal updateAccount(account) {
        require(account != address(0), "ERC20: burn from the zero address");
        require(_getBalance(account) >= amount, "ERC20: Not enough token to burn");

        _beforeTokenTransfer(account, address(0), amount);

        _accounts[account].balance = _accounts[account].balance.sub(amount);

        unconfirmedPayWave = unconfirmedPayWave.add(amount);

        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }

    /**
     * @notice Spend some token from caller's balance in the game.
     * @dev Moves `amount` of token from caller to `unconfirmedPayWave`.
     * @param amount Amount of token used to spend
     */
    function spend(uint256 amount) public returns(bool) {
        require(amount > MIN_SPEND, "Crowns: trying to spend less than expected");
        require(_getBalance(msg.sender) >= amount, "Crowns: Not enough balance");

        _spend(msg.sender, amount);

	return true;
    }

    function spendFrom(address sender, uint256 amount) public returns(bool) {
        require(amount > MIN_SPEND, "Crowns: trying to spend less than expected");
        require(_getBalance(sender) >= amount, "Crowns: not enough balance");

        _spend(sender, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));

        return true;
    }

    /**
     * @notice Return the PayWave amount, when `account` balance was updated.
     */
    function getLastPayWave(address account) public view returns (uint256) {
        return _accounts[account].lastPayWave;
    }

    /**
     * @dev Returns actual balance of account as a sum of owned divends and current balance.
     * @param account Address of Token holder.
     * @return Token amount
     */
    function _getBalance(address account) private view returns (uint256) {
        uint256 balance = _accounts[account].balance;
    	if (balance == 0) {
    		return 0;
    	}
    	uint256 owing = payWaveOwing(account);

    	return balance.add(owing);
    }

    /**
     * @notice Pay Wave is a unique feature of Crowns (CWS) token. It redistributes tokens spenth within game among all token holders.
     * @dev Moves tokens from {unconfirmedPayWave} to {totalPayWave}.
     * Any account balance related functions will use {totalPayWave} to calculate the dividend shares for each account.
     *
     * Emits a {PayWave} event.
     */
    function payWave() public onlyOwner() returns (bool) {
    	totalPayWave = totalPayWave.add(unconfirmedPayWave);
    	unclaimedPayWave = unclaimedPayWave.add(unconfirmedPayWave);
        uint256 payWaved = unconfirmedPayWave;
        unconfirmedPayWave = 0;

        emit PayWave (
            payWaved,
            totalPayWave
        );

        return true;
    }
}

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

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_feeRate","type":"uint256"},{"internalType":"address","name":"_crownsAddress","type":"address"},{"internalType":"address","name":"_signerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"offerId","type":"uint256"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"bounty","type":"uint256"},{"indexed":true,"internalType":"address","name":"bountyAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestedTokensAmount","type":"uint256"},{"indexed":false,"internalType":"uint256[5]","name":"requestedTokenIds","type":"uint256[5]"},{"indexed":false,"internalType":"uint256","name":"offeredTokensAmount","type":"uint256"},{"indexed":false,"internalType":"uint256[5]","name":"offeredTokenIds","type":"uint256[5]"}],"name":"AcceptOffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"offerId","type":"uint256"},{"indexed":true,"internalType":"address","name":"seller","type":"address"}],"name":"CancelOffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"offerId","type":"uint256"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"uint256","name":"bounty","type":"uint256"},{"indexed":true,"internalType":"address","name":"bountyAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"offeredTokensAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"requestedTokensAmount","type":"uint256"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"}],"indexed":false,"internalType":"struct NftSwap.OfferedToken[5]","name":"offeredTokens","type":"tuple[5]"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"bytes","name":"tokenParams","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"indexed":false,"internalType":"struct NftSwap.RequestedToken[5]","name":"requestedTokens","type":"tuple[5]"}],"name":"CreateOffer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"NftReceived","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":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"Received","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"uint256","name":"_offerId","type":"uint256"},{"internalType":"uint256[5]","name":"_requestedTokenIds","type":"uint256[5]"},{"internalType":"address[5]","name":"_requestedTokenAddresses","type":"address[5]"},{"internalType":"uint8[5]","name":"_v","type":"uint8[5]"},{"internalType":"bytes32[5]","name":"_r","type":"bytes32[5]"},{"internalType":"bytes32[5]","name":"_s","type":"bytes32[5]"}],"name":"acceptOffer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_bountyAddress","type":"address"}],"name":"addSupportedBountyAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_offerId","type":"uint256"}],"name":"cancelOffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"_offeredTokensAmount","type":"uint8"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"}],"internalType":"struct NftSwap.OfferedToken[5]","name":"_offeredTokens","type":"tuple[5]"},{"internalType":"uint8","name":"_requestedTokensAmount","type":"uint8"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"bytes","name":"tokenParams","type":"bytes"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct NftSwap.RequestedToken[5]","name":"_requestedTokens","type":"tuple[5]"},{"internalType":"uint256","name":"_bounty","type":"uint256"},{"internalType":"address","name":"_bountyAddress","type":"address"}],"name":"createOffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"crowns","outputs":[{"internalType":"contract CrownsToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"}],"name":"disableSupportedNftAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nftAddress","type":"address"},{"internalType":"address","name":"_nftParamsAddress","type":"address"}],"name":"enableSupportedNftAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_tradeEnabled","type":"bool"}],"name":"enableTrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastOfferId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_offerId","type":"uint256"}],"name":"getOffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastOfferId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bountyAddress","type":"address"}],"name":"removeSupportedBountyAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feeRate","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedBountyAddresses","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"supportedNftAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradeEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526001600560006101000a81548160ff0219169083151502179055503480156200002c57600080fd5b5060405162005fb938038062005fb98339818101604052810190620000529190620002cc565b600062000064620001e060201b60201c565b905080600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3506001600281905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200017e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200017590620003a6565b60405180910390fd5b6200018f82620001e860201b60201c565b8260068190555080600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050506200046d565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156200025b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200025290620003c8565b60405180910390fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600081519050620002af8162000439565b92915050565b600081519050620002c68162000453565b92915050565b600080600060608486031215620002e257600080fd5b6000620002f286828701620002b5565b935050602062000305868287016200029e565b925050604062000318868287016200029e565b9150509250925092565b600062000331601383620003ea565b91507f696e76616c6964206377732061646472657373000000000000000000000000006000830152602082019050919050565b600062000373601c83620003ea565b91507f43726f776e732063616e2774206265207a65726f2061646472657373000000006000830152602082019050919050565b60006020820190508181036000830152620003c18162000322565b9050919050565b60006020820190508181036000830152620003e38162000364565b9050919050565b600082825260208201905092915050565b600062000408826200040f565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6200044481620003fb565b81146200045057600080fd5b50565b6200045e816200042f565b81146200046a57600080fd5b50565b615b3c806200047d6000396000f3fe60806040526004361061012e5760003560e01c80638da5cb5b116100ab578063d621e8131161006f578063d621e81314610415578063ddca3f4314610440578063e388bf211461046b578063ea5ed05d14610494578063ef706adf146104bf578063f2fde38b146104e85761012f565b80638da5cb5b1461032b578063a760d79a14610356578063af13b97114610386578063c00f04d1146103af578063cdd21397146103d85761012f565b8063643268c9116100f2578063643268c91461027b57806369fe0e2d146102a6578063715018a6146102cf5780637e6c2378146102e6578063834a37b9146103025761012f565b806306edf3461461016a578063150b7a02146101935780634579268a146101d057806347eda88f1461021357806359e148fc146102505761012f565b5b7f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f885258743334604051610160929190614fd6565b60405180910390a1005b34801561017657600080fd5b50610191600480360381019061018c9190613f4a565b610511565b005b34801561019f57600080fd5b506101ba60048036038101906101b59190613fd8565b61068f565b6040516101c7919061510b565b60405180910390f35b3480156101dc57600080fd5b506101f760048036038101906101f291906140a5565b61072c565b60405161020a9796959493929190615666565b60405180910390f35b34801561021f57600080fd5b5061023a60048036038101906102359190613f4a565b61084e565b60405161024791906150ab565b60405180910390f35b34801561025c57600080fd5b5061026561086e565b6040516102729190615523565b60405180910390f35b34801561028757600080fd5b50610290610878565b60405161029d9190615523565b60405180910390f35b3480156102b257600080fd5b506102cd60048036038101906102c891906140a5565b61087e565b005b3480156102db57600080fd5b506102e461091f565b005b61030060048036038101906102fb91906140f7565b610a77565b005b34801561030e57600080fd5b5061032960048036038101906103249190613f9c565b611596565b005b34801561033757600080fd5b5061034061185d565b60405161034d9190614f69565b60405180910390f35b610370600480360381019061036b9190614184565b611887565b60405161037d9190615523565b60405180910390f35b34801561039257600080fd5b506103ad60048036038101906103a89190613f4a565b61291d565b005b3480156103bb57600080fd5b506103d660048036038101906103d19190614053565b612b75565b005b3480156103e457600080fd5b506103ff60048036038101906103fa9190613f4a565b612c29565b60405161040c9190614f69565b60405180910390f35b34801561042157600080fd5b5061042a612c5c565b60405161043791906150ab565b60405180910390f35b34801561044c57600080fd5b50610455612c6f565b6040516104629190615523565b60405180910390f35b34801561047757600080fd5b50610492600480360381019061048d9190613f4a565b612c75565b005b3480156104a057600080fd5b506104a9612df4565b6040516104b69190615126565b60405180910390f35b3480156104cb57600080fd5b506104e660048036038101906104e191906140a5565b612e19565b005b3480156104f457600080fd5b5061050f600480360381019061050a9190613f4a565b6134e9565b005b6105196136b0565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146105a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059f90615363565b60405180910390fd5b600860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062b906154a3565b60405180910390fd5b6000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008473ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16146106d057600060e01b9050610724565b7f0895c277367ff99b8c0dec875f3149fc2c82df592f63ca6f0747ac2095169087858585856040516107059493929190615036565b60405180910390a160405161071990614ee0565b604051809103902090505b949350505050565b60008060008060008060006007600089815260200190815260200160002060000154600760008a815260200190815260200160002060010160009054906101000a900460ff16600760008b815260200190815260200160002060010160019054906101000a900460ff16600760008c815260200190815260200160002060020154600760008d815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600760008e815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600760008f8152602001908152602001600020600501548191509650965096509650965096509650919395979092949650565b60086020528060005260406000206000915054906101000a900460ff1681565b6000600454905090565b60045481565b6108866136b0565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610915576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090c90615363565b60405180910390fd5b8060068190555050565b6109276136b0565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146109b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ad90615363565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b600280541415610abc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ab3906154c3565b60405180910390fd5b600280819055506000600760008881526020019081526020016000209050600560009054906101000a900460ff16610b29576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2090615463565b60405180910390fd5b8060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610bbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb3906152a3565b60405180910390fd5b60008090505b8160010160019054906101000a900460ff1660ff16811015610ff25781600701600082815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16868260058110610c3957fe5b602002015173ffffffffffffffffffffffffffffffffffffffff1614610c94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8b90615423565b60405180910390fd5b600082600701600083815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16636352211e8a8560058110610d1057fe5b60200201516040518263ffffffff1660e01b8152600401610d319190615523565b60206040518083038186803b158015610d4957600080fd5b505afa158015610d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d819190613f73565b73ffffffffffffffffffffffffffffffffffffffff1614610dd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dce90615443565b60405180910390fd5b600089898460058110610de657fe5b6020020151898560058110610df757fe5b602002015133604051602001610e109493929190614f1b565b604051602081830303815290604052805190602001209050600081604051602001610e3b9190614ef5565b60405160208183030381529060405280519060200120905060006001828a8760058110610e6457fe5b60200201518a8860058110610e7557fe5b60200201518a8960058110610e8657fe5b602002015160405160008152602001604052604051610ea894939291906150c6565b6020604051602081039080840390855afa158015610eca573d6000803e3d6000fd5b505050602060405103519050600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637ac3c02f6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f3e57600080fd5b505afa158015610f52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f769190613f73565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610fe3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fda90615283565b60405180910390fd5b50505050806001019050610bc2565b5060008090505b8160010160019054906101000a900460ff1660ff168110156110d35785816005811061102157fe5b602002015173ffffffffffffffffffffffffffffffffffffffff166342842e0e338460040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a856005811061107357fe5b60200201516040518463ffffffff1660e01b815260040161109693929190614f9f565b600060405180830381600087803b1580156110b057600080fd5b505af11580156110c4573d6000803e3d6000fd5b50505050806001019050610ff9565b5060008090505b8160010160009054906101000a900460ff1660ff168110156111c05781600601600082815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e3033856006016000868152602001908152602001600020600001546040518463ffffffff1660e01b815260040161118393929190614f9f565b600060405180830381600087803b15801561119d57600080fd5b505af11580156111b1573d6000803e3d6000fd5b505050508060010190506110da565b506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16631dbf3bc782600501546040518263ffffffff1660e01b815260040161121f9190615523565b602060405180830381600087803b15801561123957600080fd5b505af115801561124d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611271919061407c565b5060008160020154111561137d57600073ffffffffffffffffffffffffffffffffffffffff168160030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611328573373ffffffffffffffffffffffffffffffffffffffff166108fc82600201549081150290604051600060405180830381858888f19350505050158015611322573d6000803e3d6000fd5b5061137c565b61137b3382600201548360030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166136b89092919063ffffffff16565b5b5b8060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1682600001547f02fcdef9298c6a533466daaf962b24b1953ac9fa98b50e68493263c3b593df4f846002015485600501548660010160019054906101000a900460ff168c8860010160009054906101000a900460ff166040518060a001604052808b60060160008081526020019081526020016000206000015481526020018b6006016000600181526020019081526020016000206000015481526020018b6006016000600281526020019081526020016000206000015481526020018b6006016000600381526020019081526020016000206000015481526020018b600601600060048152602001908152602001600020600001548152506040516114d996959493929190615598565b60405180910390a4600760008881526020019081526020016000206000808201600090556001820160006101000a81549060ff02191690556001820160016101000a81549060ff021916905560028201600090556003820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556004820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905560058201600090555050506001600281905550505050505050565b61159e6136b0565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461162d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161162490615363565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561169d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611694906151a3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561170d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170490615263565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117d2906154e3565b60405180910390fd5b80600960008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600560009054906101000a900460ff166118d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118cf90615463565b60405180910390fd5b60008760ff161161191e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161191590615383565b60405180910390fd5b60058760ff161115611965576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195c90615323565b60405180910390fd5b60008560ff16116119ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a290615203565b60405180910390fd5b60058560ff1611156119f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119e990615183565b60405180910390fd5b6000831115611d7f578173ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611b455782600654016000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b8152600401611aaf9190614f84565b60206040518083038186803b158015611ac757600080fd5b505afa158015611adb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aff91906140ce565b1015611b40576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b3790615163565b60405180910390fd5b611d7a565b600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16611bd1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc890615223565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611ca75782341015611c49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4090615243565b60405180910390fd5b600083340390506000811115611ca1573373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611c9f573d6000803e3d6000fd5b505b50611d79565b6000829050838173ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b8152600401611ce69190614f84565b60206040518083038186803b158015611cfe57600080fd5b505afa158015611d12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d3691906140ce565b1015611d77576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d6e906152e3565b60405180910390fd5b505b5b611e6e565b6006546000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b8152600401611ddc9190614f84565b60206040518083038186803b158015611df457600080fd5b505afa158015611e08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2c91906140ce565b1015611e6d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6490615343565b60405180910390fd5b5b60008090505b8760ff1681101561209157600073ffffffffffffffffffffffffffffffffffffffff1660096000898460058110611ea757fe5b60200201516020015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415611f62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f5990615403565b60405180910390fd5b6000878260058110611f7057fe5b60200201516020015190503373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16636352211e8a8560058110611fba57fe5b6020020151600001516040518263ffffffff1660e01b8152600401611fdf9190615523565b60206040518083038186803b158015611ff757600080fd5b505afa15801561200b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061202f9190613f73565b73ffffffffffffffffffffffffffffffffffffffff1614612085576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207c90615443565b60405180910390fd5b50806001019050611e74565b5060008090505b8560ff168110156122bf576000600960008784600581106120b557fe5b60200201516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561218b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612182906151e3565b60405180910390fd5b60008190508073ffffffffffffffffffffffffffffffffffffffff1663640e13086004548986600581106121bb57fe5b6020020151602001518a87600581106121d057fe5b6020020151604001518b88600581106121e557fe5b6020020151606001518c89600581106121fa57fe5b6020020151608001516040518663ffffffff1660e01b815260040161222395949392919061553e565b60206040518083038186803b15801561223b57600080fd5b505afa15801561224f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612273919061407c565b6122b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122a990615303565b60405180910390fd5b5050806001019050612098565b5060008090505b8760ff16811015612373578681600581106122dd57fe5b60200201516020015173ffffffffffffffffffffffffffffffffffffffff166342842e0e33308a856005811061230f57fe5b6020020151600001516040518463ffffffff1660e01b815260040161233693929190614f9f565b600060405180830381600087803b15801561235057600080fd5b505af1158015612364573d6000803e3d6000fd5b505050508060010190506122c6565b50600083111561252e576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561242957612424333085600654016000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661373e909392919063ffffffff16565b612529565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156124aa573073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f193505050501580156124a4573d6000803e3d6000fd5b506124d8565b6124d73330858573ffffffffffffffffffffffffffffffffffffffff1661373e909392919063ffffffff16565b5b61252833306006546000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661373e909392919063ffffffff16565b5b61257f565b61257e33306006546000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661373e909392919063ffffffff16565b5b600460008154809291906001019190505550600454600760006004548152602001908152602001600020600001819055508660076000600454815260200190815260200160002060010160006101000a81548160ff021916908360ff1602179055508460076000600454815260200190815260200160002060010160016101000a81548160ff021916908360ff16021790555060008090505b8760ff168110156126bc5786816005811061262f57fe5b602002015160076000600454815260200190815260200160002060060160008381526020019081526020016000206000820151816000015560208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050806001019050612618565b5060008090505b8560ff168110156127af578481600581106126da57fe5b6020020151600760006004548152602001908152602001600020600701600083815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101908051906020019061276b929190613a14565b5060408201518160020160006101000a81548160ff021916908360ff16021790555060608201518160030155608082015181600401559050508060010190506126c3565b5082600760006004548152602001908152602001600020600201819055508160076000600454815260200190815260200160002060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503360076000600454815260200190815260200160002060040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600654600760006004548152602001908152602001600020600501819055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff166004547ff7cb1dace9489604343b4263c9b235428dc3f912546aadc59f5b2afac2bb7f6d866006548c8b8d8c604051612906969594939291906155fc565b60405180910390a460045490509695505050505050565b6129256136b0565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146129b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129ab90615363565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612a24576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a1b906152c3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415612af3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aea906153c3565b60405180910390fd5b6000600960008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b612b7d6136b0565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612c0c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c0390615363565b60405180910390fd5b80600560006101000a81548160ff02191690831515021790555050565b60096020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600560009054906101000a900460ff1681565b60065481565b612c7d6136b0565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612d0c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d0390615363565b60405180910390fd5b600860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612d99576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d9090615503565b60405180910390fd5b6001600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600280541415612e5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e55906154c3565b60405180910390fd5b6002808190555060006007600083815260200190815260200160002090503373ffffffffffffffffffffffffffffffffffffffff168160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612f0e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f05906153a3565b60405180910390fd5b60008090505b8160010160009054906101000a900460ff1660ff1681101561301e5781600601600082815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166342842e0e308460040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856006016000868152602001908152602001600020600001546040518463ffffffff1660e01b8152600401612fe193929190614f9f565b600060405180830381600087803b158015612ffb57600080fd5b505af115801561300f573d6000803e3d6000fd5b50505050806001019050612f14565b50600081600201541115613319576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168160030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415613163576000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb3383600201548460050154016040518363ffffffff1660e01b815260040161310b929190614fd6565b602060405180830381600087803b15801561312557600080fd5b505af1158015613139573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061315d919061407c565b50613314565b600073ffffffffffffffffffffffffffffffffffffffff168160030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141561320c573373ffffffffffffffffffffffffffffffffffffffff166108fc82600201549081150290604051600060405180830381858888f19350505050158015613206573d6000803e3d6000fd5b50613260565b61325f3382600201548360030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166136b89092919063ffffffff16565b5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb3383600501546040518363ffffffff1660e01b81526004016132c0929190614fd6565b602060405180830381600087803b1580156132da57600080fd5b505af11580156132ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613312919061407c565b505b6133cd565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb3383600501546040518363ffffffff1660e01b8152600401613379929190614fd6565b602060405180830381600087803b15801561339357600080fd5b505af11580156133a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133cb919061407c565b505b8060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681600001547fc4caef7e3533865382e608c341581a5e2a1b0d1ac37b0aaf58023ccd4eedfd8e60405160405180910390a3600760008381526020019081526020016000206000808201600090556001820160006101000a81549060ff02191690556001820160016101000a81549060ff021916905560028201600090556003820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556004820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556005820160009055505050600160028190555050565b6134f16136b0565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614613580576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161357790615363565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156135f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016135e7906151c3565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b6137398363a9059cbb60e01b84846040516024016136d7929190615082565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506137c7565b505050565b6137c1846323b872dd60e01b85858560405160240161375f93929190614fff565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506137c7565b50505050565b6060613829826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661388e9092919063ffffffff16565b90506000815111156138895780806020019051810190613849919061407c565b613888576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161387f90615483565b60405180910390fd5b5b505050565b606061389d84846000856138a6565b90509392505050565b60606138b1856139c9565b6138f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138e7906153e3565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161391a9190614ec9565b60006040518083038185875af1925050503d8060008114613957576040519150601f19603f3d011682016040523d82523d6000602084013e61395c565b606091505b509150915081156139715780925050506139c1565b6000815111156139845780518082602001fd5b836040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139b89190615141565b60405180910390fd5b949350505050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f9150808214158015613a0b57506000801b8214155b92505050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613a5557805160ff1916838001178555613a83565b82800160010185558215613a83579182015b82811115613a82578251825591602001919060010190613a67565b5b509050613a909190613a94565b5090565b613ab691905b80821115613ab2576000816000905550600101613a9a565b5090565b90565b600081359050613ac881615a93565b92915050565b600081519050613add81615a93565b92915050565b600082601f830112613af457600080fd5b6005613b07613b0282615702565b6156d5565b91508183856020840282011115613b1d57600080fd5b60005b83811015613b4d5781613b338882613ab9565b845260208401935060208301925050600181019050613b20565b5050505092915050565b600082601f830112613b6857600080fd5b6005613b7b613b7682615724565b6156d5565b91508183856020840282011115613b9157600080fd5b60005b83811015613bc15781613ba78882613db6565b845260208401935060208301925050600181019050613b94565b5050505092915050565b600082601f830112613bdc57600080fd5b6005613bef613bea82615746565b6156d5565b91508183856040840282011115613c0557600080fd5b60005b83811015613c355781613c1b8882613e1f565b845260208401935060408301925050600181019050613c08565b5050505092915050565b600082601f830112613c5057600080fd5b6005613c63613c5e82615768565b6156d5565b9150818360005b83811015613c9a5781358601613c808882613e6b565b845260208401935060208301925050600181019050613c6a565b5050505092915050565b600082601f830112613cb557600080fd5b6005613cc8613cc38261578a565b6156d5565b91508183856020840282011115613cde57600080fd5b60005b83811015613d0e5781613cf48882613f0b565b845260208401935060208301925050600181019050613ce1565b5050505092915050565b600082601f830112613d2957600080fd5b6005613d3c613d37826157ac565b6156d5565b91508183856020840282011115613d5257600080fd5b60005b83811015613d825781613d688882613f35565b845260208401935060208301925050600181019050613d55565b5050505092915050565b600081359050613d9b81615aaa565b92915050565b600081519050613db081615aaa565b92915050565b600081359050613dc581615ac1565b92915050565b600082601f830112613ddc57600080fd5b8135613def613dea826157ce565b6156d5565b91508082526020830160208301858383011115613e0b57600080fd5b613e168382846159e9565b50505092915050565b600060408284031215613e3157600080fd5b613e3b60406156d5565b90506000613e4b84828501613f0b565b6000830152506020613e5f84828501613ab9565b60208301525092915050565b600060a08284031215613e7d57600080fd5b613e8760a06156d5565b90506000613e9784828501613ab9565b600083015250602082013567ffffffffffffffff811115613eb757600080fd5b613ec384828501613dcb565b6020830152506040613ed784828501613f35565b6040830152506060613eeb84828501613db6565b6060830152506080613eff84828501613db6565b60808301525092915050565b600081359050613f1a81615ad8565b92915050565b600081519050613f2f81615ad8565b92915050565b600081359050613f4481615aef565b92915050565b600060208284031215613f5c57600080fd5b6000613f6a84828501613ab9565b91505092915050565b600060208284031215613f8557600080fd5b6000613f9384828501613ace565b91505092915050565b60008060408385031215613faf57600080fd5b6000613fbd85828601613ab9565b9250506020613fce85828601613ab9565b9150509250929050565b60008060008060808587031215613fee57600080fd5b6000613ffc87828801613ab9565b945050602061400d87828801613ab9565b935050604061401e87828801613f0b565b925050606085013567ffffffffffffffff81111561403b57600080fd5b61404787828801613dcb565b91505092959194509250565b60006020828403121561406557600080fd5b600061407384828501613d8c565b91505092915050565b60006020828403121561408e57600080fd5b600061409c84828501613da1565b91505092915050565b6000602082840312156140b757600080fd5b60006140c584828501613f0b565b91505092915050565b6000602082840312156140e057600080fd5b60006140ee84828501613f20565b91505092915050565b600080600080600080610340878903121561411157600080fd5b600061411f89828a01613f0b565b965050602061413089828a01613ca4565b95505060c061414189828a01613ae3565b94505061016061415389828a01613d18565b93505061020061416589828a01613b57565b9250506102a061417789828a01613b57565b9150509295509295509295565b6000806000806000806101e0878903121561419e57600080fd5b60006141ac89828a01613f35565b96505060206141bd89828a01613bcb565b9550506101606141cf89828a01613f35565b94505061018087013567ffffffffffffffff8111156141ed57600080fd5b6141f989828a01613c3f565b9350506101a061420b89828a01613f0b565b9250506101c061421d89828a01613ab9565b9150509295509295509295565b60006142368383614dc2565b60408301905092915050565b600061424e8383614df1565b905092915050565b60006142628383614e67565b60208301905092915050565b6142778161597d565b82525050565b61428e614289826158f2565b615a3d565b82525050565b61429d816158e0565b82525050565b6142ac816158e0565b82525050565b6142c36142be826158e0565b615a2b565b82525050565b6142d281615818565b6142dc8184615876565b92506142e7826157fa565b8060005b838110156143185781516142ff878261422a565b965061430a8361584f565b9250506001810190506142eb565b505050505050565b600061432b82615823565b6143358185615881565b93508360208202850161434785615804565b8060005b8581101561438357848403895281516143648582614242565b945061436f8361585c565b925060208a0199505060018101905061434b565b50829750879550505050505092915050565b61439e8161582e565b6143a8818461588c565b92506143b38261580e565b8060005b838110156143e45781516143cb8782614256565b96506143d683615869565b9250506001810190506143b7565b505050505050565b6143f581615904565b82525050565b61440481615910565b82525050565b61441381615910565b82525050565b61442a61442582615910565b615a4f565b82525050565b6144398161591a565b82525050565b600061444a82615839565b6144548185615897565b93506144648185602086016159f8565b61446d81615a75565b840191505092915050565b600061448382615839565b61448d81856158a8565b935061449d8185602086016159f8565b6144a681615a75565b840191505092915050565b60006144bc82615839565b6144c681856158b9565b93506144d68185602086016159f8565b80840191505092915050565b6144eb8161598f565b82525050565b60006144fc82615844565b61450681856158c4565b93506145168185602086016159f8565b61451f81615a75565b840191505092915050565b6000614537601f836158c4565b91507f6e6f7420656e6f7567682043575320666f7220666565202620626f756e7479006000830152602082019050919050565b6000614577602f836158d5565b91507f6f6e455243373231526563656976656428616464726573732c6164647265737360008301527f2c75696e743235362c62797465732900000000000000000000000000000000006020830152602f82019050919050565b60006145dd601c836158d5565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b600061461d601f836158c4565b91507f63616e742072657175657374206d6f7265207468616e203520746f6b656e73006000830152602082019050919050565b600061465d6013836158c4565b91507f696e76616c6964206e66742061646472657373000000000000000000000000006000830152602082019050919050565b600061469d6026836158c4565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006147036021836158c4565b91507f726571756573746564206e6674206164647265737320756e737570706f72746560008301527f64000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614769601f836158c4565b91507f73686f756c642072657175697265206174206c65617374206f6e65206e6674006000830152602082019050919050565b60006147a9601c836158c4565b91507f626f756e74792061646472657373206e6f7420737570706f72746564000000006000830152602082019050919050565b60006147e9601c836158c4565b91507f696e73756666696369656e74207472616e7366657220616d6f756e74000000006000830152602082019050919050565b60006148296019836158c4565b91507f696e76616c6964204e6674506172616d732061646472657373000000000000006000830152602082019050919050565b60006148696013836158c4565b91507f566572696669636174696f6e206661696c6564000000000000000000000000006000830152602082019050919050565b60006148a96018836158c4565b91507f63616e74206275792073656c662d6d616465206f6666657200000000000000006000830152602082019050919050565b60006148e9600f836158c4565b91507f696e76616c6964206164647265737300000000000000000000000000000000006000830152602082019050919050565b6000614929601e836158c4565b91507f6e6f7420656e6f756768206d6f6e657920746f2070617920626f756e747900006000830152602082019050919050565b60006149696012836158c4565b91507f696e76616c6964206e667420506172616d7300000000000000000000000000006000830152602082019050919050565b60006149a9601d836158c4565b91507f63616e74206f66666572206d6f7265207468616e203520746f6b656e730000006000830152602082019050919050565b60006149e96016836158c4565b91507f6e6f7420656e6f7567682043575320666f7220666565000000000000000000006000830152602082019050919050565b6000614a296020836158c4565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000614a69601d836158c4565b91507f73686f756c64206f66666572206174206c65617374206f6e65206e66740000006000830152602082019050919050565b6000614aa9601e836158c4565b91507f73656e646572206973206e6f742063726561746f72206f66206f6666657200006000830152602082019050919050565b6000614ae9601c836158c4565b91507f6e6674206164647265737320616c72656164792064697361626c6564000000006000830152602082019050919050565b6000614b29601d836158c4565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000614b69601f836158c4565b91507f6f666665726564206e6674206164647265737320756e737570706f72746564006000830152602082019050919050565b6000614ba9601d836158c4565b91507f77726f6e672072657175657374656420746f6b656e20616464726573730000006000830152602082019050919050565b6000614be96017836158c4565b91507f73656e646572206e6f74206f776e6572206f66206e66740000000000000000006000830152602082019050919050565b6000614c296011836158c4565b91507f74726164652069732064697361626c65640000000000000000000000000000006000830152602082019050919050565b6000614c69602a836158c4565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000614ccf6016836158c4565b91507f626f756e747920616c72656164792072656d6f766564000000000000000000006000830152602082019050919050565b6000614d0f601f836158c4565b91507f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006000830152602082019050919050565b6000614d4f601b836158c4565b91507f6e6674206164647265737320616c726561647920656e61626c656400000000006000830152602082019050919050565b6000614d8f6018836158c4565b91507f626f756e747920616c726561647920737570706f7274656400000000000000006000830152602082019050919050565b604082016000820151614dd86000850182614e67565b506020820151614deb6020850182614294565b50505050565b600060a083016000830151614e096000860182614294565b5060208301518482036020860152614e21828261443f565b9150506040830151614e366040860182614eab565b506060830151614e4960608601826143fb565b506080830151614e5c60808601826143fb565b508091505092915050565b614e7081615966565b82525050565b614e7f81615966565b82525050565b614e96614e9182615966565b615a6b565b82525050565b614ea5816159d7565b82525050565b614eb481615970565b82525050565b614ec381615970565b82525050565b6000614ed582846144b1565b915081905092915050565b6000614eeb8261456a565b9150819050919050565b6000614f00826145d0565b9150614f0c8284614419565b60208201915081905092915050565b6000614f278287614e85565b602082019150614f378286614e85565b602082019150614f4782856142b2565b601482019150614f57828461427d565b60148201915081905095945050505050565b6000602082019050614f7e60008301846142a3565b92915050565b6000602082019050614f99600083018461426e565b92915050565b6000606082019050614fb4600083018661426e565b614fc1602083018561426e565b614fce6040830184614e76565b949350505050565b6000604082019050614feb600083018561426e565b614ff86020830184614e76565b9392505050565b600060608201905061501460008301866142a3565b61502160208301856142a3565b61502e6040830184614e76565b949350505050565b600060808201905061504b60008301876142a3565b61505860208301866142a3565b6150656040830185614e76565b81810360608301526150778184614478565b905095945050505050565b600060408201905061509760008301856142a3565b6150a46020830184614e76565b9392505050565b60006020820190506150c060008301846143ec565b92915050565b60006080820190506150db600083018761440a565b6150e86020830186614eba565b6150f5604083018561440a565b615102606083018461440a565b95945050505050565b60006020820190506151206000830184614430565b92915050565b600060208201905061513b60008301846144e2565b92915050565b6000602082019050818103600083015261515b81846144f1565b905092915050565b6000602082019050818103600083015261517c8161452a565b9050919050565b6000602082019050818103600083015261519c81614610565b9050919050565b600060208201905081810360008301526151bc81614650565b9050919050565b600060208201905081810360008301526151dc81614690565b9050919050565b600060208201905081810360008301526151fc816146f6565b9050919050565b6000602082019050818103600083015261521c8161475c565b9050919050565b6000602082019050818103600083015261523c8161479c565b9050919050565b6000602082019050818103600083015261525c816147dc565b9050919050565b6000602082019050818103600083015261527c8161481c565b9050919050565b6000602082019050818103600083015261529c8161485c565b9050919050565b600060208201905081810360008301526152bc8161489c565b9050919050565b600060208201905081810360008301526152dc816148dc565b9050919050565b600060208201905081810360008301526152fc8161491c565b9050919050565b6000602082019050818103600083015261531c8161495c565b9050919050565b6000602082019050818103600083015261533c8161499c565b9050919050565b6000602082019050818103600083015261535c816149dc565b9050919050565b6000602082019050818103600083015261537c81614a1c565b9050919050565b6000602082019050818103600083015261539c81614a5c565b9050919050565b600060208201905081810360008301526153bc81614a9c565b9050919050565b600060208201905081810360008301526153dc81614adc565b9050919050565b600060208201905081810360008301526153fc81614b1c565b9050919050565b6000602082019050818103600083015261541c81614b5c565b9050919050565b6000602082019050818103600083015261543c81614b9c565b9050919050565b6000602082019050818103600083015261545c81614bdc565b9050919050565b6000602082019050818103600083015261547c81614c1c565b9050919050565b6000602082019050818103600083015261549c81614c5c565b9050919050565b600060208201905081810360008301526154bc81614cc2565b9050919050565b600060208201905081810360008301526154dc81614d02565b9050919050565b600060208201905081810360008301526154fc81614d42565b9050919050565b6000602082019050818103600083015261551c81614d82565b9050919050565b60006020820190506155386000830184614e76565b92915050565b600060a0820190506155536000830188614e76565b81810360208301526155658187614478565b90506155746040830186614eba565b615581606083018561440a565b61558e608083018461440a565b9695505050505050565b60006101c0820190506155ae6000830189614e76565b6155bb6020830188614e76565b6155c86040830187614e9c565b6155d56060830186614395565b6155e3610100830185614e9c565b6155f1610120830184614395565b979650505050505050565b60006101e0820190506156126000830189614e76565b61561f6020830188614e76565b61562c6040830187614e9c565b6156396060830186614e9c565b61564660808301856142c9565b8181036101c08301526156598184614320565b9050979650505050505050565b600060e08201905061567b600083018a614e76565b6156886020830189614eba565b6156956040830188614eba565b6156a26060830187614e76565b6156af60808301866142a3565b6156bc60a08301856142a3565b6156c960c0830184614e76565b98975050505050505050565b6000604051905081810181811067ffffffffffffffff821117156156f857600080fd5b8060405250919050565b600067ffffffffffffffff82111561571957600080fd5b602082029050919050565b600067ffffffffffffffff82111561573b57600080fd5b602082029050919050565b600067ffffffffffffffff82111561575d57600080fd5b602082029050919050565b600067ffffffffffffffff82111561577f57600080fd5b602082029050919050565b600067ffffffffffffffff8211156157a157600080fd5b602082029050919050565b600067ffffffffffffffff8211156157c357600080fd5b602082029050919050565b600067ffffffffffffffff8211156157e557600080fd5b601f19601f8301169050602081019050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600060059050919050565b600060059050919050565b600060059050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600081905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006158eb82615946565b9050919050565b60006158fd82615946565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000615988826159b3565b9050919050565b600061599a826159a1565b9050919050565b60006159ac82615946565b9050919050565b60006159be826159c5565b9050919050565b60006159d082615946565b9050919050565b60006159e282615970565b9050919050565b82818337600083830152505050565b60005b83811015615a165780820151818401526020810190506159fb565b83811115615a25576000848401525b50505050565b6000615a3682615a59565b9050919050565b6000615a4882615a59565b9050919050565b6000819050919050565b6000615a6482615a86565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b615a9c816158e0565b8114615aa757600080fd5b50565b615ab381615904565b8114615abe57600080fd5b50565b615aca81615910565b8114615ad557600080fd5b50565b615ae181615966565b8114615aec57600080fd5b50565b615af881615970565b8114615b0357600080fd5b5056fea264697066735822122043fd9c6a1517f928599669fe1062199e380e69e9620de830428dff6f0ffe523c64736f6c634300060700330000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000001abb8fde5e64be3419fcef80df335c68dd2956c7000000000000000000000000bfb0b85fdbf132bb23db11f9c9aa72a153edcc69

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

0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000001abb8fde5e64be3419fcef80df335c68dd2956c7000000000000000000000000bfb0b85fdbf132bb23db11f9c9aa72a153edcc69

-----Decoded View---------------
Arg [0] : _feeRate (uint256): 1000000000000000000
Arg [1] : _crownsAddress (address): 0x1abb8fde5e64be3419fcef80df335c68dd2956c7
Arg [2] : _signerAddress (address): 0xbfb0b85fdbf132bb23db11f9c9aa72a153edcc69

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [1] : 0000000000000000000000001abb8fde5e64be3419fcef80df335c68dd2956c7
Arg [2] : 000000000000000000000000bfb0b85fdbf132bb23db11f9c9aa72a153edcc69


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