ETH Price: $3,664.53 (+0.67%)

Token

ERC-20: ()
 

Overview

Max Total Supply

10

Holders

6

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
0x20D6CF7075CcbE840f2AcFa07A7B98536684A1ED
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
DIADataNFT

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 20000 runs

Other Settings:
default evmVersion
File 1 of 16 : DIADataNFT.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "./DIASourceNFT.sol";
import "./Strings.sol";

contract DIADataNFT is Ownable, ERC1155 {

	using Math for uint256;
	using Strings for string;

	address public DIASourceNFTAddr;
	DIASourceNFT public diaSourceNFTImpl = DIASourceNFT(DIASourceNFTAddr);

	address public DIAGenesisMinterAddr;

	uint256 public constant NUM_PRIVILEGED_RANKS = 10;

	uint256 public numMintedNFTs;
	mapping (uint256 => address) rankMinter;
	mapping (uint256 => uint256) rankClaims;
	mapping (uint256 => uint) lastClaimPayout;
	bool public exists;
	bool public started;
	bool public genesisPhase;
	uint256 public sourceNFTId;
	mapping (address => uint256) public mintsPerWallet;
	uint256 public maxMintsPerWallet = 3;

	address public paymentToken;
	address public constant burnAddress = address(0x000000000000000000000000000000000000dEaD);
	uint256 public burnAmount;
	uint256 public mintingPoolAmount;

	constructor(address _paymentToken, uint256 _burnAmount, uint256 _mintingPoolAmount, address _DIAGenesisMinterAddr, bytes memory metadataURI) ERC1155(string(metadataURI)) {
		require(_paymentToken != address(0), "Payment token address is 0.");
		paymentToken = _paymentToken;
		burnAmount = _burnAmount;
		mintingPoolAmount = _mintingPoolAmount;
		DIAGenesisMinterAddr = _DIAGenesisMinterAddr;
	}

	event NewDataNFTCategory(uint256 sourceNFTId);
	event MintedDataNFT(address owner, uint256 numMinted, uint256 newRank);
	event ClaimedMintingPoolReward(uint256 rank, address claimer);

	function uri(uint256 _id) public view override returns (string memory) {
		if (_id > NUM_PRIVILEGED_RANKS) {
			_id = NUM_PRIVILEGED_RANKS;
		}
		return string(abi.encodePacked(
			super.uri(_id),
			Strings.uint2str(_id),
			".json"
		));
	}

	function finishGenesisPhase() external onlyOwner {
		genesisPhase = false;
	}

	function startMinting() external onlyOwner {
		started = true;
	}

	function updateMaxMintsPerWallet(uint256 newValue) external onlyOwner {
		maxMintsPerWallet = newValue;
	}

	function updateDIAGenesisMinterAddr(address newAddress) external onlyOwner {
		DIAGenesisMinterAddr = newAddress;
	}

	function setSrcNFT(address _newAddress) external onlyOwner {
		DIASourceNFTAddr = _newAddress;
		diaSourceNFTImpl = DIASourceNFT(DIASourceNFTAddr);
	}

	function generateDataNFTCategory(uint256 _sourceNFTId) external {
		require(diaSourceNFTImpl.balanceOf(msg.sender, _sourceNFTId) > 0);
		exists = true;
		genesisPhase = true;
		started = false;
		sourceNFTId = _sourceNFTId;
		emit NewDataNFTCategory(_sourceNFTId);
	}

	function getRankClaim(uint256 newRank, uint256 max) public view returns (uint256) {
		// 1. Get tetrahedron sum of token units to distribute
		uint256 totalClaimsForMint = getTetrahedronSum(max);
		// 2. Get raw claim from the rank of an NFT
		uint256 rawRankClaim = (getInverseTetrahedronNumber(newRank, max) * mintingPoolAmount) / totalClaimsForMint;
		// 3. Special cases: privileged ranks
		if (newRank == 1 || newRank == 2) {
			return ((getInverseTetrahedronNumber(1, max) * mintingPoolAmount) / totalClaimsForMint + (getInverseTetrahedronNumber(2, max) * mintingPoolAmount) / totalClaimsForMint) / 2;
		} else if (newRank == 3 || newRank == 4 || newRank == 5) {
			return ((getInverseTetrahedronNumber(3, max) * mintingPoolAmount) / totalClaimsForMint + (getInverseTetrahedronNumber(4, max) * mintingPoolAmount) / totalClaimsForMint + (getInverseTetrahedronNumber(5, max) * mintingPoolAmount) / totalClaimsForMint) / 3;
		} else if (newRank == 6 || newRank == 7 || newRank == 8 || newRank == 9) {
			return ((getInverseTetrahedronNumber(6, max) * mintingPoolAmount) / totalClaimsForMint + (getInverseTetrahedronNumber(7, max) * mintingPoolAmount) / totalClaimsForMint + (getInverseTetrahedronNumber(8, max) * mintingPoolAmount) / totalClaimsForMint + (getInverseTetrahedronNumber(9, max) * mintingPoolAmount) / totalClaimsForMint) / 4;
		}
		return rawRankClaim;
	}

	function _mintDataNFT(address _origin, uint256 _newRank) public returns (uint256) {
		require(msg.sender == DIAGenesisMinterAddr, "Only callable from the genesis minter contract");
		// Check that category exists
		require(exists, "_mintDataNFT.Category must exist");
		// Get current number minted of the NFT
		uint256 numMinted = numMintedNFTs;

		if (numMinted < NUM_PRIVILEGED_RANKS) {
			while (rankMinter[_newRank] != address(0)) {
				_newRank = (_newRank + 1) % NUM_PRIVILEGED_RANKS;
			}
		} else {
			_newRank = numMinted;
		}

		for (uint256 i = 0; i < Math.max(NUM_PRIVILEGED_RANKS, numMinted); i++) {
			rankClaims[i] += getRankClaim(i, Math.max(NUM_PRIVILEGED_RANKS, numMinted));
		}

		// Check that the wallet is still allowed to mint
		require(mintsPerWallet[_origin] < maxMintsPerWallet, "Sender has used all its mints");

		// Mint data NFT
		_mint(_origin, _newRank, 1, "");

		// Update data struct
		rankMinter[_newRank] = _origin;
		numMintedNFTs = numMinted + 1;

		// Update Source NFT data
		uint256 currSourceNFTId = sourceNFTId;

		diaSourceNFTImpl.notifyDataNFTMint(currSourceNFTId);

		mintsPerWallet[_origin] += 1;
		emit MintedDataNFT(_origin, numMinted, _newRank);
		return _newRank;
	}

	function getRankMinter(uint256 rank) external view returns (address) {
	    return rankMinter[rank];
	}

	function getLastClaimPayout(uint256 rank) external view returns (uint) {
	    return lastClaimPayout[rank];
	}

	function claimMintingPoolReward(uint256 rank) public {
		require(!genesisPhase);
		address claimer = msg.sender;
		require(balanceOf(claimer, rank) > 0);

		uint256 reward = rankClaims[rank];

		// transfer reward to claimer
		require(ERC20(paymentToken).transfer(claimer, reward));
		// Set claim to 0 for rank
		rankClaims[rank] = 0;
		emit ClaimedMintingPoolReward(rank, claimer);
	}

	function getRewardAmount(uint256 rank) public view returns (uint) {
		return rankClaims[rank];
	}

	// Returns the n-th tetrahedron number
	function getTetrahedronNumber(uint256 n) internal pure returns (uint256) {
		return (n * (n + 1) * (n + 2))/ 6;
	}

	// Returns the n-th tetrahedron number from above
	function getInverseTetrahedronNumber(uint256 n, uint256 max) internal pure returns (uint256) {
		return getTetrahedronNumber(max - n);
	}

	function getTetrahedronSum(uint256 n) internal pure returns (uint256) {
		uint256 acc = 0;
		// Start at 1 so that the last minter doesn't get 0
		for (uint256 i = 1; i <= n; i++) {
			acc += getTetrahedronNumber(i);
		}
		return acc;
	}

	function getMintedNFTs() external view returns (uint) {
		return numMintedNFTs;
	}

	/*function getErcRank(uint256 internalRank) public pure returns (uint256) {
		// Translate rank to ERC1155 ID "rank" info
		uint256 ercRank = 0;
		if (internalRank == 0) { ercRank = 0; }
		else if (internalRank == 1 || internalRank == 2) { ercRank = 1; }
		else if (internalRank == 3 || internalRank == 4 || internalRank == 5) { ercRank = 2; }
		else if (internalRank == 6 || internalRank == 7 || internalRank == 8 || internalRank == 9) { ercRank = 3; }
		else { ercRank = 4; }
		return ercRank;
	}*/
}

File 2 of 16 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        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 3 of 16 : ERC1155.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC1155.sol";
import "./IERC1155Receiver.sol";
import "./extensions/IERC1155MetadataURI.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of the basic standard multi-token.
 * See https://eips.ethereum.org/EIPS/eip-1155
 * Originally based on code by Enjin: https://github.com/enjin/erc-1155
 *
 * _Available since v3.1._
 */
contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
    using Address for address;

    // Mapping from token ID to account balances
    mapping (uint256 => mapping(address => uint256)) private _balances;

    // Mapping from account to operator approvals
    mapping (address => mapping(address => bool)) private _operatorApprovals;

    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json
    string private _uri;

    /**
     * @dev See {_setURI}.
     */
    constructor (string memory uri_) {
        _setURI(uri_);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return interfaceId == type(IERC1155).interfaceId
            || interfaceId == type(IERC1155MetadataURI).interfaceId
            || super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IERC1155MetadataURI-uri}.
     *
     * This implementation returns the same URI for *all* token types. It relies
     * on the token type ID substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
     *
     * Clients calling this function must replace the `\{id\}` substring with the
     * actual token type ID.
     */
    function uri(uint256) public view virtual override returns (string memory) {
        return _uri;
    }

    /**
     * @dev See {IERC1155-balanceOf}.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {
        require(account != address(0), "ERC1155: balance query for the zero address");
        return _balances[id][account];
    }

    /**
     * @dev See {IERC1155-balanceOfBatch}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(
        address[] memory accounts,
        uint256[] memory ids
    )
        public
        view
        virtual
        override
        returns (uint256[] memory)
    {
        require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch");

        uint256[] memory batchBalances = new uint256[](accounts.length);

        for (uint256 i = 0; i < accounts.length; ++i) {
            batchBalances[i] = balanceOf(accounts[i], ids[i]);
        }

        return batchBalances;
    }

    /**
     * @dev See {IERC1155-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(_msgSender() != operator, "ERC1155: setting approval status for self");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    /**
     * @dev See {IERC1155-isApprovedForAll}.
     */
    function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[account][operator];
    }

    /**
     * @dev See {IERC1155-safeTransferFrom}.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    )
        public
        virtual
        override
    {
        require(to != address(0), "ERC1155: transfer to the zero address");
        require(
            from == _msgSender() || isApprovedForAll(from, _msgSender()),
            "ERC1155: caller is not owner nor approved"
        );

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);

        uint256 fromBalance = _balances[id][from];
        require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
        _balances[id][from] = fromBalance - amount;
        _balances[id][to] += amount;

        emit TransferSingle(operator, from, to, id, amount);

        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);
    }

    /**
     * @dev See {IERC1155-safeBatchTransferFrom}.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    )
        public
        virtual
        override
    {
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");
        require(to != address(0), "ERC1155: transfer to the zero address");
        require(
            from == _msgSender() || isApprovedForAll(from, _msgSender()),
            "ERC1155: transfer caller is not owner nor approved"
        );

        address operator = _msgSender();

        _beforeTokenTransfer(operator, from, to, ids, amounts, data);

        for (uint256 i = 0; i < ids.length; ++i) {
            uint256 id = ids[i];
            uint256 amount = amounts[i];

            uint256 fromBalance = _balances[id][from];
            require(fromBalance >= amount, "ERC1155: insufficient balance for transfer");
            _balances[id][from] = fromBalance - amount;
            _balances[id][to] += amount;
        }

        emit TransferBatch(operator, from, to, ids, amounts);

        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);
    }

    /**
     * @dev Sets a new URI for all token types, by relying on the token type ID
     * substitution mechanism
     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].
     *
     * By this mechanism, any occurrence of the `\{id\}` substring in either the
     * URI or any of the amounts in the JSON file at said URI will be replaced by
     * clients with the token type ID.
     *
     * For example, the `https://token-cdn-domain/\{id\}.json` URI would be
     * interpreted by clients as
     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`
     * for token type ID 0x4cce0.
     *
     * See {uri}.
     *
     * Because these URIs cannot be meaningfully represented by the {URI} event,
     * this function emits no events.
     */
    function _setURI(string memory newuri) internal virtual {
        _uri = newuri;
    }

    /**
     * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual {
        require(account != address(0), "ERC1155: mint to the zero address");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);

        _balances[id][account] += amount;
        emit TransferSingle(operator, address(0), account, id, amount);

        _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual {
        require(to != address(0), "ERC1155: mint to the zero address");
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);

        for (uint i = 0; i < ids.length; i++) {
            _balances[ids[i]][to] += amounts[i];
        }

        emit TransferBatch(operator, address(0), to, ids, amounts);

        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);
    }

    /**
     * @dev Destroys `amount` tokens of token type `id` from `account`
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens of token type `id`.
     */
    function _burn(address account, uint256 id, uint256 amount) internal virtual {
        require(account != address(0), "ERC1155: burn from the zero address");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), "");

        uint256 accountBalance = _balances[id][account];
        require(accountBalance >= amount, "ERC1155: burn amount exceeds balance");
        _balances[id][account] = accountBalance - amount;

        emit TransferSingle(operator, account, address(0), id, amount);
    }

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     */
    function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual {
        require(account != address(0), "ERC1155: burn from the zero address");
        require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch");

        address operator = _msgSender();

        _beforeTokenTransfer(operator, account, address(0), ids, amounts, "");

        for (uint i = 0; i < ids.length; i++) {
            uint256 id = ids[i];
            uint256 amount = amounts[i];

            uint256 accountBalance = _balances[id][account];
            require(accountBalance >= amount, "ERC1155: burn amount exceeds balance");
            _balances[id][account] = accountBalance - amount;
        }

        emit TransferBatch(operator, account, address(0), ids, amounts);
    }

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning, as well as batched variants.
     *
     * The same hook is called on both single and batched variants. For single
     * transfers, the length of the `id` and `amount` arrays will be 1.
     *
     * Calling conditions (for each `id` and `amount` pair):
     *
     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * of token type `id` will be  transferred to `to`.
     * - When `from` is zero, `amount` tokens of token type `id` will be minted
     * for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`
     * will be burned.
     * - `from` and `to` are never both zero.
     * - `ids` and `amounts` have the same, non-zero length.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    )
        internal
        virtual
    { }

    function _doSafeTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    )
        private
    {
        if (to.isContract()) {
            try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
                if (response != IERC1155Receiver(to).onERC1155Received.selector) {
                    revert("ERC1155: ERC1155Receiver rejected tokens");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("ERC1155: transfer to non ERC1155Receiver implementer");
            }
        }
    }

    function _doSafeBatchTransferAcceptanceCheck(
        address operator,
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    )
        private
    {
        if (to.isContract()) {
            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {
                if (response != IERC1155Receiver(to).onERC1155BatchReceived.selector) {
                    revert("ERC1155: ERC1155Receiver rejected tokens");
                }
            } catch Error(string memory reason) {
                revert(reason);
            } catch {
                revert("ERC1155: transfer to non ERC1155Receiver implementer");
            }
        }
    }

    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {
        uint256[] memory array = new uint256[](1);
        array[0] = element;

        return array;
    }
}

File 4 of 16 : ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The defaut value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override 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`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * 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 virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        _approve(sender, _msgSender(), currentAllowance - amount);

        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] + 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) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        _approve(_msgSender(), spender, currentAllowance - subtractedValue);

        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 virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        _balances[sender] = senderBalance - amount;
        _balances[recipient] += 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 += amount;
        _balances[account] += 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 virtual {
        require(account != address(0), "ERC20: burn from the zero address");

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

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

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

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This 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 { }
}

File 5 of 16 : Math.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

File 6 of 16 : DIASourceNFT.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract DIASourceNFT is Ownable, ERC1155 {

	address public paymentToken;
	mapping (address => bool) public dataNFTContractAddresses;

	struct SourceNFTMetadata {
		uint256 claimablePayout;
		bool exists;
		address admin;
		uint256[] parentIds;
		uint256[] parentPayoutShares;
		uint256 payoutShare;
		uint256 sourcePoolAmount;
	}

	mapping (uint256 => SourceNFTMetadata) public sourceNfts;

	constructor(address newOwner) ERC1155("https://api.diadata.org/v1/nft/source_{id}.json") {
		transferOwnership(newOwner);
	}

	function setMetadataUri(string memory metadataURI) onlyOwner external {
		_setURI(metadataURI);
	}

	function getSourcePoolAmount(uint256 sourceNftId) external view returns (uint256) {
		return sourceNfts[sourceNftId].sourcePoolAmount;
	}
	
	function setSourcePoolAmount(uint256 sourceNftId, uint256 newAmount) external {
	    require(sourceNfts[sourceNftId].admin == msg.sender, "Source Pool Amount can only be set by the sART admin");
	    sourceNfts[sourceNftId].sourcePoolAmount = newAmount;
	}

	function addDataNFTContractAddress(address newAddress) onlyOwner external {
		require(newAddress != address(0), "New address is 0.");
		dataNFTContractAddresses[newAddress] = true;
	}

	function removeDataNFTContractAddress(address oldAddress) onlyOwner external {
		require(oldAddress != address(0), "Removed address is 0.");
		dataNFTContractAddresses[oldAddress] = false;
	}

	function updateAdmin(uint256 sourceNftId, address newAdmin) external {
		require(sourceNfts[sourceNftId].admin == msg.sender);
		sourceNfts[sourceNftId].admin = newAdmin;
	}

	function addParent(uint256 sourceNftId, uint256 parentId, uint256 payoutShare) external {
		require(sourceNfts[sourceNftId].admin == msg.sender);
		require(sourceNfts[sourceNftId].payoutShare >= payoutShare);
		require(sourceNfts[parentId].exists, "Parent NFT does not exist!");

		sourceNfts[sourceNftId].payoutShare -= payoutShare;
		sourceNfts[sourceNftId].parentPayoutShares.push(payoutShare);
		sourceNfts[sourceNftId].parentIds.push(parentId);
	}

	function updateParentPayoutShare(uint256 sourceNftId, uint256 parentId, uint256 newPayoutShare) external {
		require(sourceNfts[sourceNftId].admin == msg.sender);
		
		uint256 arrayIndex = (2**256) - 1;
		// find parent ID in payout shares
		for (uint256 i = 0; i < sourceNfts[sourceNftId].parentPayoutShares.length; i++) {
			if (sourceNfts[sourceNftId].parentIds[i] == parentId) {
				arrayIndex = i;
				break;
			}
		}

		uint256 payoutDelta;
		// Check if we can distribute enough payout shares
		if (newPayoutShare >= sourceNfts[sourceNftId].parentPayoutShares[arrayIndex]) {
			payoutDelta = newPayoutShare - sourceNfts[sourceNftId].parentPayoutShares[arrayIndex];
			require(sourceNfts[sourceNftId].payoutShare >= payoutDelta, "Error: Not enough shares left to increase payout!");
			sourceNfts[sourceNftId].payoutShare -= payoutDelta;
			sourceNfts[sourceNftId].parentPayoutShares[arrayIndex] += payoutDelta;
		} else {
			payoutDelta = sourceNfts[sourceNftId].parentPayoutShares[arrayIndex] - newPayoutShare;
			require(sourceNfts[sourceNftId].parentPayoutShares[arrayIndex] >= payoutDelta, "Error: Not enough shares left to decrease payout!");
			sourceNfts[sourceNftId].payoutShare += payoutDelta;
			sourceNfts[sourceNftId].parentPayoutShares[arrayIndex] -= payoutDelta;
		}
	}

	function generateSourceToken(uint256 sourceNftId, address receiver) external onlyOwner {
		sourceNfts[sourceNftId].exists = true;
		sourceNfts[sourceNftId].admin = msg.sender;
		sourceNfts[sourceNftId].payoutShare = 10000;

		_mint(receiver, sourceNftId, 1, ""); 
	}

	function notifyDataNFTMint(uint256 sourceNftId) external {
		require(dataNFTContractAddresses[msg.sender], "notifyDataNFTMint: Only data NFT contracts can be used to mint data NFTs");
		require(sourceNfts[sourceNftId].exists, "notifyDataNFTMint: Source NFT does not exist!");
		for (uint256 i = 0; i < sourceNfts[sourceNftId].parentIds.length; i++) {
			uint256 currentParentId = sourceNfts[sourceNftId].parentIds[i];
			sourceNfts[currentParentId].claimablePayout += (sourceNfts[sourceNftId].parentPayoutShares[i] * sourceNfts[sourceNftId].sourcePoolAmount) / 10000;
		}
		sourceNfts[sourceNftId].claimablePayout += (sourceNfts[sourceNftId].payoutShare * sourceNfts[sourceNftId].sourcePoolAmount) / 10000;
	}

	function claimRewards(uint256 sourceNftId) external {
		address claimer = msg.sender;
		require(sourceNfts[sourceNftId].admin == claimer);
		uint256 payoutDataTokens = sourceNfts[sourceNftId].claimablePayout;

		require(ERC20(paymentToken).transfer(claimer, payoutDataTokens), "Token transfer failed.");
		sourceNfts[sourceNftId].claimablePayout = 0;
	}
}

File 7 of 16 : Strings.sol
// SPDX-License-Identifier: MIT


pragma solidity 0.8.0;

library Strings {
    function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
			if (_i == 0) {
				return "0";
			}
			uint j = _i;
			uint len;
			while (j != 0) {
				len++;
				j /= 10;
			}
			bytes memory bstr = new bytes(len);
			uint k = len;
			while (_i != 0) {
				k = k-1;
				uint8 temp = (48 + uint8(_i - _i / 10 * 10));
				bytes1 b1 = bytes1(temp);
				bstr[k] = b1;
				_i /= 10;
			}
			return string(bstr);
		}
}

File 8 of 16 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

File 9 of 16 : IERC1155.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}

File 10 of 16 : IERC1155Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {

    /**
        @dev Handles the receipt of a single ERC1155 token type. This function is
        called at the end of a `safeTransferFrom` after the balance has been updated.
        To accept the transfer, this must return
        `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
        (i.e. 0xf23a6e61, or its own function selector).
        @param operator The address which initiated the transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param id The ID of the token being transferred
        @param value The amount of tokens being transferred
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
    */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    )
        external
        returns(bytes4);

    /**
        @dev Handles the receipt of a multiple ERC1155 token types. This function
        is called at the end of a `safeBatchTransferFrom` after the balances have
        been updated. To accept the transfer(s), this must return
        `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
        (i.e. 0xbc197c81, or its own function selector).
        @param operator The address which initiated the batch transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param ids An array containing ids of each token being transferred (order and length must match values array)
        @param values An array containing amounts of each token being transferred (order and length must match ids array)
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
    */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    )
        external
        returns(bytes4);
}

File 11 of 16 : IERC1155MetadataURI.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC1155.sol";

/**
 * @dev Interface of the optional ERC1155MetadataExtension interface, as defined
 * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155MetadataURI is IERC1155 {
    /**
     * @dev Returns the URI for token type `id`.
     *
     * If the `\{id\}` substring is present in the URI, it must be replaced by
     * clients with the actual token type ID.
     */
    function uri(uint256 id) external view returns (string memory);
}

File 12 of 16 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @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) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @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");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        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 13 of 16 : ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 14 of 16 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.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 15 of 16 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 16 of 16 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_paymentToken","type":"address"},{"internalType":"uint256","name":"_burnAmount","type":"uint256"},{"internalType":"uint256","name":"_mintingPoolAmount","type":"uint256"},{"internalType":"address","name":"_DIAGenesisMinterAddr","type":"address"},{"internalType":"bytes","name":"metadataURI","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"rank","type":"uint256"},{"indexed":false,"internalType":"address","name":"claimer","type":"address"}],"name":"ClaimedMintingPoolReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"numMinted","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRank","type":"uint256"}],"name":"MintedDataNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"sourceNFTId","type":"uint256"}],"name":"NewDataNFTCategory","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":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"DIAGenesisMinterAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DIASourceNFTAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NUM_PRIVILEGED_RANKS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_origin","type":"address"},{"internalType":"uint256","name":"_newRank","type":"uint256"}],"name":"_mintDataNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rank","type":"uint256"}],"name":"claimMintingPoolReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"diaSourceNFTImpl","outputs":[{"internalType":"contract DIASourceNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finishGenesisPhase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sourceNFTId","type":"uint256"}],"name":"generateDataNFTCategory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"genesisPhase","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rank","type":"uint256"}],"name":"getLastClaimPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintedNFTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRank","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"getRankClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rank","type":"uint256"}],"name":"getRankMinter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"rank","type":"uint256"}],"name":"getRewardAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintsPerWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintingPoolAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"mintsPerWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numMintedNFTs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAddress","type":"address"}],"name":"setSrcNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sourceNFTId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"started","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddress","type":"address"}],"name":"updateDIAGenesisMinterAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"updateMaxMintsPerWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]

6080604052600454600580546001600160a01b0319166001600160a01b039092169190911790556003600e553480156200003857600080fd5b5060405162003734380380620037348339810160408190526200005b916200020f565b806000620000686200012f565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350620000bd8162000133565b506001600160a01b038516620000f05760405162461bcd60e51b8152600401620000e7906200031a565b60405180910390fd5b50600f80546001600160a01b039586166001600160a01b03199182161790915560109390935560119190915560068054919093169116179055620003a4565b3390565b8051620001489060039060208401906200014c565b5050565b8280546200015a9062000351565b90600052602060002090601f0160209004810192826200017e5760008555620001c9565b82601f106200019957805160ff1916838001178555620001c9565b82800160010185558215620001c9579182015b82811115620001c9578251825591602001919060010190620001ac565b50620001d7929150620001db565b5090565b5b80821115620001d75760008155600101620001dc565b80516001600160a01b03811681146200020a57600080fd5b919050565b600080600080600060a0868803121562000227578081fd5b6200023286620001f2565b94506020808701519450604087015193506200025160608801620001f2565b60808801519093506001600160401b03808211156200026e578384fd5b818901915089601f83011262000282578384fd5b8151818111156200029757620002976200038e565b604051601f8201601f1916810185018381118282101715620002bd57620002bd6200038e565b60405281815283820185018c1015620002d4578586fd5b8592505b81831015620002f75783830185015181840186015291840191620002d8565b818311156200030857858583830101525b80955050505050509295509295909350565b6020808252601b908201527f5061796d656e7420746f6b656e206164647265737320697320302e0000000000604082015260600190565b6002810460018216806200036657607f821691505b602082108114156200038857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b61338080620003b46000396000f3fe608060405234801561001057600080fd5b50600436106102ac5760003560e01c806385a18dc81161017b578063bfd2e577116100d8578063d9761c501161008c578063f242432a11610071578063f242432a146104e3578063f2fde38b146104f6578063f516a2e614610509576102ac565b8063d9761c50146104bd578063e985e9c5146104d0576102ac565b8063c84993af116100bd578063c84993af14610484578063cf2d1b9b14610497578063d5a6c7b7146104aa576102ac565b8063bfd2e57714610469578063c06356be14610471576102ac565b8063b363873d1161012f578063b9a252ed11610114578063b9a252ed14610446578063ba1afe5714610459578063bc011a3514610461576102ac565b8063b363873d14610436578063b95732071461043e576102ac565b80638e9dbd3f116101605780638e9dbd3f146104085780639a65ea261461041b578063a22cb46514610423576102ac565b806385a18dc8146103f85780638da5cb5b14610400576102ac565b806348a2789a11610229578063715018a6116101dd57806377bf44ea116101c257806377bf44ea146103ca5780638008573a146103d2578063851f845e146103e5576102ac565b8063715018a6146103ba578063771b432e146103c2576102ac565b80634e1273f41161020e5780634e1273f41461038a57806364d4be82146103aa57806370d5ae05146103b2576102ac565b806348a2789a146103645780634d0df5fc14610377576102ac565b80631f2698ab116102805780632eb2c2d6116102655780632eb2c2d61461033f5780633013ce2914610354578063486a7e6b1461035c576102ac565b80631f2698ab1461032f578063267c4ae414610337576102ac565b8062fdd58e146102b157806301ffc9a7146102da5780630e89341c146102fa5780631844523a1461031a575b600080fd5b6102c46102bf366004612648565b610511565b6040516102d19190612f98565b60405180910390f35b6102ed6102e836600461274b565b610587565b6040516102d19190612a20565b61030d610308366004612783565b610631565b6040516102d19190612a2b565b61032261067a565b6040516102d191906128af565b6102ed610696565b6102ed6106a4565b61035261034d366004612509565b6106ad565b005b6103226109d7565b6102c46109f3565b6103526103723660046124bd565b6109f9565b6102c46103853660046124bd565b610a99565b61039d610398366004612671565b610aab565b6040516102d191906129df565b610322610c2f565b610322610c4b565b610352610c51565b6102c4610d19565b6102c4610d1f565b6103526103e03660046124bd565b610d26565b6102c46103f33660046127b3565b610dd3565b6102c4610fde565b610322610fe3565b610322610416366004612783565b610fff565b610352611027565b610352610431366004612612565b6110ae565b6102ed6111ce565b6103226111dd565b6102c4610454366004612783565b6111f9565b6102c461120b565b610352611211565b6102c4611294565b61035261047f366004612783565b61129a565b6102c4610492366004612783565b611404565b6103526104a5366004612783565b611416565b6103526104b8366004612783565b611556565b6102c46104cb366004612648565b6115b4565b6102ed6104de3660046124d7565b611890565b6103526104f13660046125af565b6118cb565b6103526105043660046124bd565b611acd565b6102c4611be6565b600073ffffffffffffffffffffffffffffffffffffffff831661054f5760405162461bcd60e51b815260040161054690612af8565b60405180910390fd5b50600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020545b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fd9b67a2600000000000000000000000000000000000000000000000000000000148061061a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e89341c00000000000000000000000000000000000000000000000000000000145b80610629575061062982611bec565b90505b919050565b6060600a82111561064157600a91505b61064a82611c36565b61065383611cca565b604051602001610664929190612858565b6040516020818303038152906040529050919050565b60065473ffffffffffffffffffffffffffffffffffffffff1681565b600b54610100900460ff1681565b600b5460ff1681565b81518351146106ce5760405162461bcd60e51b815260040161054690612ede565b73ffffffffffffffffffffffffffffffffffffffff84166107015760405162461bcd60e51b815260040161054690612c0f565b610709611e76565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614806107495750610749856104de611e76565b6107655760405162461bcd60e51b815260040161054690612c6c565b600061076f611e76565b905061077f8187878787876109cf565b60005b84518110156109425760008582815181106107c6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101519050600085838151811061080b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602090810291909101810151600084815260018352604080822073ffffffffffffffffffffffffffffffffffffffff8e1683529093529190912054909150818110156108695760405162461bcd60e51b815260040161054690612cc9565b61087382826130af565b6001600085815260200190815260200160002060008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816001600085815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546109279190613021565b925050819055505050508061093b9061314a565b9050610782565b508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516109b99291906129f2565b60405180910390a46109cf818787878787611e7a565b505050505050565b600f5473ffffffffffffffffffffffffffffffffffffffff1681565b60105481565b610a01611e76565b73ffffffffffffffffffffffffffffffffffffffff16610a1f610fe3565b73ffffffffffffffffffffffffffffffffffffffff1614610a525760405162461bcd60e51b815260040161054690612d5b565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600d6020526000908152604090205481565b60608151835114610ace5760405162461bcd60e51b815260040161054690612e81565b6000835167ffffffffffffffff811115610b11577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051908082528060200260200182016040528015610b3a578160200160208202803683370190505b50905060005b8451811015610c2757610bd3858281518110610b85577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151858381518110610bc6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151610511565b828281518110610c0c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020908102919091010152610c208161314a565b9050610b40565b509392505050565b60055473ffffffffffffffffffffffffffffffffffffffff1681565b61dead81565b610c59611e76565b73ffffffffffffffffffffffffffffffffffffffff16610c77610fe3565b73ffffffffffffffffffffffffffffffffffffffff1614610caa5760405162461bcd60e51b815260040161054690612d5b565b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60075481565b6007545b90565b610d2e611e76565b73ffffffffffffffffffffffffffffffffffffffff16610d4c610fe3565b73ffffffffffffffffffffffffffffffffffffffff1614610d7f5760405162461bcd60e51b815260040161054690612d5b565b600480547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff938416179182905560058054929093169116179055565b600080610ddf8361200a565b9050600081601154610df18787612045565b610dfb9190613072565b610e05919061305e565b90508460011480610e165750846002145b15610e8057600282601154610e2c600288612045565b610e369190613072565b610e40919061305e565b83601154610e4f600189612045565b610e599190613072565b610e63919061305e565b610e6d9190613021565b610e77919061305e565b92505050610581565b8460031480610e8f5750846004145b80610e9a5750846005145b15610f1457600382601154610eb0600588612045565b610eba9190613072565b610ec4919061305e565b83601154610ed3600489612045565b610edd9190613072565b610ee7919061305e565b84601154610ef660038a612045565b610f009190613072565b610f0a919061305e565b610e639190613021565b8460061480610f235750846007145b80610f2e5750846008145b80610f395750846009145b15610fd657600482601154610f4f600988612045565b610f599190613072565b610f63919061305e565b83601154610f72600889612045565b610f7c9190613072565b610f86919061305e565b84601154610f9560078a612045565b610f9f9190613072565b610fa9919061305e565b85601154610fb860068b612045565b610fc29190613072565b610fcc919061305e565b610f0a9190613021565b949350505050565b600a81565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b60009081526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b61102f611e76565b73ffffffffffffffffffffffffffffffffffffffff1661104d610fe3565b73ffffffffffffffffffffffffffffffffffffffff16146110805760405162461bcd60e51b815260040161054690612d5b565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b8173ffffffffffffffffffffffffffffffffffffffff166110cd611e76565b73ffffffffffffffffffffffffffffffffffffffff1614156111015760405162461bcd60e51b815260040161054690612e24565b806002600061110e611e76565b73ffffffffffffffffffffffffffffffffffffffff90811682526020808301939093526040918201600090812091871680825291909352912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169215159290921790915561117d611e76565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516111c29190612a20565b60405180910390a35050565b600b5462010000900460ff1681565b60045473ffffffffffffffffffffffffffffffffffffffff1681565b6000908152600a602052604090205490565b600c5481565b611219611e76565b73ffffffffffffffffffffffffffffffffffffffff16611237610fe3565b73ffffffffffffffffffffffffffffffffffffffff161461126a5760405162461bcd60e51b815260040161054690612d5b565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff169055565b60115481565b6005546040517efdd58e00000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff169062fdd58e906112f1903390869060040161298b565b60206040518083038186803b15801561130957600080fd5b505afa15801561131d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611341919061279b565b1161134b57600080fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909216600117919091166201000017169055600c8190556040517f3ac60f4dd148ce151982c55ecc19e7741e5f302deab6a6b84b0fb5a3a409329e906113f9908390612f98565b60405180910390a150565b60009081526009602052604090205490565b600b5462010000900460ff161561142c57600080fd5b3360006114398284610511565b1161144357600080fd5b6000828152600960205260409081902054600f5491517fa9059cbb000000000000000000000000000000000000000000000000000000008152909173ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906114ab908590859060040161298b565b602060405180830381600087803b1580156114c557600080fd5b505af11580156114d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fd919061272f565b61150657600080fd5b60008381526009602052604080822091909155517f3c82435c4b206f0d843119ab50927469b13f586c6b82901b9814c2bb7ca84d0b906115499085908590612fa1565b60405180910390a1505050565b61155e611e76565b73ffffffffffffffffffffffffffffffffffffffff1661157c610fe3565b73ffffffffffffffffffffffffffffffffffffffff16146115af5760405162461bcd60e51b815260040161054690612d5b565b600e55565b60065460009073ffffffffffffffffffffffffffffffffffffffff1633146115ee5760405162461bcd60e51b815260040161054690612dc7565b600b5460ff166116105760405162461bcd60e51b815260040161054690612d26565b600754600a81101561166a575b60008381526008602052604090205473ffffffffffffffffffffffffffffffffffffffff161561166557600a611654846001613021565b61165e9190613183565b925061161d565b61166e565b8092505b60005b61167c600a83612060565b8110156116c857611692816103f3600a85612060565b600082815260096020526040812080549091906116b0908490613021565b909155508190506116c08161314a565b915050611671565b50600e5473ffffffffffffffffffffffffffffffffffffffff85166000908152600d60205260409020541061170f5760405162461bcd60e51b815260040161054690612d90565b61172b8484600160405180602001604052806000815250612077565b600083815260086020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616179055611782816001613021565b600755600c546005546040517f5173951400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906351739514906117de908490600401612f98565b600060405180830381600087803b1580156117f857600080fd5b505af115801561180c573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff85166000908152600d60205260408120805460019290611846908490613021565b90915550506040517fb2b74b520c5449911caca63eaea39abeb103f3ae116fbfc8d19bf8998215efaa9061187f908790859088906129b1565b60405180910390a150919392505050565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205460ff1690565b73ffffffffffffffffffffffffffffffffffffffff84166118fe5760405162461bcd60e51b815260040161054690612c0f565b611906611e76565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614806119465750611946856104de611e76565b6119625760405162461bcd60e51b815260040161054690612bb2565b600061196c611e76565b905061198c81878761197d886121a1565b611986886121a1565b876109cf565b600084815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a168452909152902054838110156119dc5760405162461bcd60e51b815260040161054690612cc9565b6119e684826130af565b600086815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8c81168552925280832093909355881681529081208054869290611a31908490613021565b925050819055508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628888604051611aae929190612fc5565b60405180910390a4611ac4828888888888612213565b50505050505050565b611ad5611e76565b73ffffffffffffffffffffffffffffffffffffffff16611af3610fe3565b73ffffffffffffffffffffffffffffffffffffffff1614611b265760405162461bcd60e51b815260040161054690612d5b565b73ffffffffffffffffffffffffffffffffffffffff8116611b595760405162461bcd60e51b815260040161054690612b55565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600e5481565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f01ffc9a70000000000000000000000000000000000000000000000000000000014919050565b606060038054611c45906130f6565b80601f0160208091040260200160405190810160405280929190818152602001828054611c71906130f6565b8015611cbe5780601f10611c9357610100808354040283529160200191611cbe565b820191906000526020600020905b815481529060010190602001808311611ca157829003601f168201915b50505050509050919050565b606081611d0b575060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015261062c565b8160005b8115611d355780611d1f8161314a565b9150611d2e9050600a8361305e565b9150611d0f565b60008167ffffffffffffffff811115611d77577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611da1576020820181803683370190505b509050815b8515611e6d57611db76001826130af565b90506000611dc6600a8861305e565b611dd190600a613072565b611ddb90886130af565b611de6906030613039565b905060008160f81b905080848481518110611e2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611e64600a8961305e565b97505050611da6565b50949350505050565b3390565b611e998473ffffffffffffffffffffffffffffffffffffffff16612366565b156109cf576040517fbc197c8100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063bc197c8190611ef890899089908890889088906004016128d0565b602060405180830381600087803b158015611f1257600080fd5b505af1925050508015611f60575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611f5d91810190612767565b60015b611fa957611f6c61322a565b80611f775750611f91565b8060405162461bcd60e51b81526004016105469190612a2b565b60405162461bcd60e51b815260040161054690612a3e565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c810000000000000000000000000000000000000000000000000000000014611ac45760405162461bcd60e51b815260040161054690612a9b565b60008060015b83811161203e576120208161236c565b61202a9083613021565b9150806120368161314a565b915050612010565b5092915050565b600061205961205484846130af565b61236c565b9392505050565b6000818310156120705781612059565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff84166120aa5760405162461bcd60e51b815260040161054690612f3b565b60006120b4611e76565b90506120c68160008761197d886121a1565b600084815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845290915281208054859290612105908490613021565b925050819055508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051612183929190612fc5565b60405180910390a461219a81600087878787612213565b5050505050565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110612202577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602090810291909101015292915050565b6122328473ffffffffffffffffffffffffffffffffffffffff16612366565b156109cf576040517ff23a6e6100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063f23a6e6190612291908990899088908890889060040161293b565b602060405180830381600087803b1580156122ab57600080fd5b505af19250505080156122f9575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526122f691810190612767565b60015b61230557611f6c61322a565b7fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e610000000000000000000000000000000000000000000000000000000014611ac45760405162461bcd60e51b815260040161054690612a9b565b3b151590565b6000600661237b836002613021565b612386846001613021565b6123909085613072565b61239a9190613072565b610629919061305e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461062c57600080fd5b600082601f8301126123d8578081fd5b813560206123ed6123e883612ffd565b612fd3565b8281528181019085830183850287018401881015612409578586fd5b855b858110156124275781358452928401929084019060010161240b565b5090979650505050505050565b600082601f830112612444578081fd5b813567ffffffffffffffff81111561245e5761245e6131f5565b61248f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612fd3565b8181528460208386010111156124a3578283fd5b816020850160208301379081016020019190915292915050565b6000602082840312156124ce578081fd5b612059826123a4565b600080604083850312156124e9578081fd5b6124f2836123a4565b9150612500602084016123a4565b90509250929050565b600080600080600060a08688031215612520578081fd5b612529866123a4565b9450612537602087016123a4565b9350604086013567ffffffffffffffff80821115612553578283fd5b61255f89838a016123c8565b94506060880135915080821115612574578283fd5b61258089838a016123c8565b93506080880135915080821115612595578283fd5b506125a288828901612434565b9150509295509295909350565b600080600080600060a086880312156125c6578081fd5b6125cf866123a4565b94506125dd602087016123a4565b93506040860135925060608601359150608086013567ffffffffffffffff811115612606578182fd5b6125a288828901612434565b60008060408385031215612624578182fd5b61262d836123a4565b9150602083013561263d8161330b565b809150509250929050565b6000806040838503121561265a578182fd5b612663836123a4565b946020939093013593505050565b60008060408385031215612683578182fd5b823567ffffffffffffffff8082111561269a578384fd5b818501915085601f8301126126ad578384fd5b813560206126bd6123e883612ffd565b82815281810190858301838502870184018b10156126d9578889fd5b8896505b84871015612702576126ee816123a4565b8352600196909601959183019183016126dd565b5096505086013592505080821115612718578283fd5b50612725858286016123c8565b9150509250929050565b600060208284031215612740578081fd5b81516120598161330b565b60006020828403121561275c578081fd5b81356120598161331c565b600060208284031215612778578081fd5b81516120598161331c565b600060208284031215612794578081fd5b5035919050565b6000602082840312156127ac578081fd5b5051919050565b600080604083850312156127c5578182fd5b50508035926020909101359150565b6000815180845260208085019450808401835b83811015612803578151875295820195908201906001016127e7565b509495945050505050565b600081518084526128268160208601602086016130c6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000835161286a8184602088016130c6565b83519083019061287e8183602088016130c6565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000009101908152600501949350505050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a0604083015261290960a08301866127d4565b828103606084015261291b81866127d4565b9050828103608084015261292f818561280e565b98975050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015283606083015260a0608083015261298060a083018461280e565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9390931683526020830191909152604082015260600190565b60006020825261205960208301846127d4565b600060408252612a0560408301856127d4565b8281036020840152612a1781856127d4565b95945050505050565b901515815260200190565b600060208252612059602083018461280e565b60208082526034908201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e746572000000000000000000000000606082015260800190565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e73000000000000000000000000000000000000000000000000606082015260800190565b6020808252602b908201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60408201527f65726f2061646472657373000000000000000000000000000000000000000000606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201527f6464726573730000000000000000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260408201527f20617070726f7665640000000000000000000000000000000000000000000000606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460408201527f6472657373000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526032908201527f455243313135353a207472616e736665722063616c6c6572206973206e6f742060408201527f6f776e6572206e6f7220617070726f7665640000000000000000000000000000606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201527f72207472616e7366657200000000000000000000000000000000000000000000606082015260800190565b6020808252818101527f5f6d696e74446174614e46542e43617465676f7279206d757374206578697374604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601d908201527f53656e64657220686173207573656420616c6c20697473206d696e7473000000604082015260600190565b6020808252602e908201527f4f6e6c792063616c6c61626c652066726f6d207468652067656e65736973206d60408201527f696e74657220636f6e7472616374000000000000000000000000000000000000606082015260800190565b60208082526029908201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360408201527f20666f722073656c660000000000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860408201527f206d69736d617463680000000000000000000000000000000000000000000000606082015260800190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060408201527f6d69736d61746368000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f2061646472657360408201527f7300000000000000000000000000000000000000000000000000000000000000606082015260800190565b90815260200190565b91825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715612ff557612ff56131f5565b604052919050565b600067ffffffffffffffff821115613017576130176131f5565b5060209081020190565b6000821982111561303457613034613197565b500190565b600060ff821660ff84168060ff0382111561305657613056613197565b019392505050565b60008261306d5761306d6131c6565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156130aa576130aa613197565b500290565b6000828210156130c1576130c1613197565b500390565b60005b838110156130e15781810151838201526020016130c9565b838111156130f0576000848401525b50505050565b60028104600182168061310a57607f821691505b60208210811415613144577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561317c5761317c613197565b5060010190565b600082613192576131926131c6565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60e01c90565b600060443d101561323a57610d23565b600481823e6308c379a061324e8251613224565b1461325857610d23565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3d016004823e80513d67ffffffffffffffff81602484011181841117156132a65750505050610d23565b828401925082519150808211156132c05750505050610d23565b503d830160208284010111156132d857505050610d23565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810160200160405291505090565b801515811461331957600080fd5b50565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461331957600080fdfea2646970667358221220a00221d16c325c1df027a734797cd7ab8d395b2db3e7230f219f93c7b575588164736f6c6343000800003300000000000000000000000084ca8bc7997272c7cfb4d0cd3d55cd942b3c9419000000000000000000000000000000000000000000000001a055690d9db80000000000000000000000000000000000000000000000000002b5e3af16b1880000000000000000000000000000660062a92c8ce918598bad2280ef0db99e4dbcb500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000042697066733a2f2f516d5531794879433835454b455a454e68566361735678466936785047676e394133457568707159744a39774a622f43727970746f50756e6b732f000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102ac5760003560e01c806385a18dc81161017b578063bfd2e577116100d8578063d9761c501161008c578063f242432a11610071578063f242432a146104e3578063f2fde38b146104f6578063f516a2e614610509576102ac565b8063d9761c50146104bd578063e985e9c5146104d0576102ac565b8063c84993af116100bd578063c84993af14610484578063cf2d1b9b14610497578063d5a6c7b7146104aa576102ac565b8063bfd2e57714610469578063c06356be14610471576102ac565b8063b363873d1161012f578063b9a252ed11610114578063b9a252ed14610446578063ba1afe5714610459578063bc011a3514610461576102ac565b8063b363873d14610436578063b95732071461043e576102ac565b80638e9dbd3f116101605780638e9dbd3f146104085780639a65ea261461041b578063a22cb46514610423576102ac565b806385a18dc8146103f85780638da5cb5b14610400576102ac565b806348a2789a11610229578063715018a6116101dd57806377bf44ea116101c257806377bf44ea146103ca5780638008573a146103d2578063851f845e146103e5576102ac565b8063715018a6146103ba578063771b432e146103c2576102ac565b80634e1273f41161020e5780634e1273f41461038a57806364d4be82146103aa57806370d5ae05146103b2576102ac565b806348a2789a146103645780634d0df5fc14610377576102ac565b80631f2698ab116102805780632eb2c2d6116102655780632eb2c2d61461033f5780633013ce2914610354578063486a7e6b1461035c576102ac565b80631f2698ab1461032f578063267c4ae414610337576102ac565b8062fdd58e146102b157806301ffc9a7146102da5780630e89341c146102fa5780631844523a1461031a575b600080fd5b6102c46102bf366004612648565b610511565b6040516102d19190612f98565b60405180910390f35b6102ed6102e836600461274b565b610587565b6040516102d19190612a20565b61030d610308366004612783565b610631565b6040516102d19190612a2b565b61032261067a565b6040516102d191906128af565b6102ed610696565b6102ed6106a4565b61035261034d366004612509565b6106ad565b005b6103226109d7565b6102c46109f3565b6103526103723660046124bd565b6109f9565b6102c46103853660046124bd565b610a99565b61039d610398366004612671565b610aab565b6040516102d191906129df565b610322610c2f565b610322610c4b565b610352610c51565b6102c4610d19565b6102c4610d1f565b6103526103e03660046124bd565b610d26565b6102c46103f33660046127b3565b610dd3565b6102c4610fde565b610322610fe3565b610322610416366004612783565b610fff565b610352611027565b610352610431366004612612565b6110ae565b6102ed6111ce565b6103226111dd565b6102c4610454366004612783565b6111f9565b6102c461120b565b610352611211565b6102c4611294565b61035261047f366004612783565b61129a565b6102c4610492366004612783565b611404565b6103526104a5366004612783565b611416565b6103526104b8366004612783565b611556565b6102c46104cb366004612648565b6115b4565b6102ed6104de3660046124d7565b611890565b6103526104f13660046125af565b6118cb565b6103526105043660046124bd565b611acd565b6102c4611be6565b600073ffffffffffffffffffffffffffffffffffffffff831661054f5760405162461bcd60e51b815260040161054690612af8565b60405180910390fd5b50600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020545b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fd9b67a2600000000000000000000000000000000000000000000000000000000148061061a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e89341c00000000000000000000000000000000000000000000000000000000145b80610629575061062982611bec565b90505b919050565b6060600a82111561064157600a91505b61064a82611c36565b61065383611cca565b604051602001610664929190612858565b6040516020818303038152906040529050919050565b60065473ffffffffffffffffffffffffffffffffffffffff1681565b600b54610100900460ff1681565b600b5460ff1681565b81518351146106ce5760405162461bcd60e51b815260040161054690612ede565b73ffffffffffffffffffffffffffffffffffffffff84166107015760405162461bcd60e51b815260040161054690612c0f565b610709611e76565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614806107495750610749856104de611e76565b6107655760405162461bcd60e51b815260040161054690612c6c565b600061076f611e76565b905061077f8187878787876109cf565b60005b84518110156109425760008582815181106107c6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200260200101519050600085838151811061080b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602090810291909101810151600084815260018352604080822073ffffffffffffffffffffffffffffffffffffffff8e1683529093529190912054909150818110156108695760405162461bcd60e51b815260040161054690612cc9565b61087382826130af565b6001600085815260200190815260200160002060008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550816001600085815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546109279190613021565b925050819055505050508061093b9061314a565b9050610782565b508473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516109b99291906129f2565b60405180910390a46109cf818787878787611e7a565b505050505050565b600f5473ffffffffffffffffffffffffffffffffffffffff1681565b60105481565b610a01611e76565b73ffffffffffffffffffffffffffffffffffffffff16610a1f610fe3565b73ffffffffffffffffffffffffffffffffffffffff1614610a525760405162461bcd60e51b815260040161054690612d5b565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600d6020526000908152604090205481565b60608151835114610ace5760405162461bcd60e51b815260040161054690612e81565b6000835167ffffffffffffffff811115610b11577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051908082528060200260200182016040528015610b3a578160200160208202803683370190505b50905060005b8451811015610c2757610bd3858281518110610b85577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151858381518110610bc6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151610511565b828281518110610c0c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020908102919091010152610c208161314a565b9050610b40565b509392505050565b60055473ffffffffffffffffffffffffffffffffffffffff1681565b61dead81565b610c59611e76565b73ffffffffffffffffffffffffffffffffffffffff16610c77610fe3565b73ffffffffffffffffffffffffffffffffffffffff1614610caa5760405162461bcd60e51b815260040161054690612d5b565b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b60075481565b6007545b90565b610d2e611e76565b73ffffffffffffffffffffffffffffffffffffffff16610d4c610fe3565b73ffffffffffffffffffffffffffffffffffffffff1614610d7f5760405162461bcd60e51b815260040161054690612d5b565b600480547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff938416179182905560058054929093169116179055565b600080610ddf8361200a565b9050600081601154610df18787612045565b610dfb9190613072565b610e05919061305e565b90508460011480610e165750846002145b15610e8057600282601154610e2c600288612045565b610e369190613072565b610e40919061305e565b83601154610e4f600189612045565b610e599190613072565b610e63919061305e565b610e6d9190613021565b610e77919061305e565b92505050610581565b8460031480610e8f5750846004145b80610e9a5750846005145b15610f1457600382601154610eb0600588612045565b610eba9190613072565b610ec4919061305e565b83601154610ed3600489612045565b610edd9190613072565b610ee7919061305e565b84601154610ef660038a612045565b610f009190613072565b610f0a919061305e565b610e639190613021565b8460061480610f235750846007145b80610f2e5750846008145b80610f395750846009145b15610fd657600482601154610f4f600988612045565b610f599190613072565b610f63919061305e565b83601154610f72600889612045565b610f7c9190613072565b610f86919061305e565b84601154610f9560078a612045565b610f9f9190613072565b610fa9919061305e565b85601154610fb860068b612045565b610fc29190613072565b610fcc919061305e565b610f0a9190613021565b949350505050565b600a81565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b60009081526008602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b61102f611e76565b73ffffffffffffffffffffffffffffffffffffffff1661104d610fe3565b73ffffffffffffffffffffffffffffffffffffffff16146110805760405162461bcd60e51b815260040161054690612d5b565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055565b8173ffffffffffffffffffffffffffffffffffffffff166110cd611e76565b73ffffffffffffffffffffffffffffffffffffffff1614156111015760405162461bcd60e51b815260040161054690612e24565b806002600061110e611e76565b73ffffffffffffffffffffffffffffffffffffffff90811682526020808301939093526040918201600090812091871680825291909352912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169215159290921790915561117d611e76565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516111c29190612a20565b60405180910390a35050565b600b5462010000900460ff1681565b60045473ffffffffffffffffffffffffffffffffffffffff1681565b6000908152600a602052604090205490565b600c5481565b611219611e76565b73ffffffffffffffffffffffffffffffffffffffff16611237610fe3565b73ffffffffffffffffffffffffffffffffffffffff161461126a5760405162461bcd60e51b815260040161054690612d5b565b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff169055565b60115481565b6005546040517efdd58e00000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff169062fdd58e906112f1903390869060040161298b565b60206040518083038186803b15801561130957600080fd5b505afa15801561131d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611341919061279b565b1161134b57600080fd5b600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909216600117919091166201000017169055600c8190556040517f3ac60f4dd148ce151982c55ecc19e7741e5f302deab6a6b84b0fb5a3a409329e906113f9908390612f98565b60405180910390a150565b60009081526009602052604090205490565b600b5462010000900460ff161561142c57600080fd5b3360006114398284610511565b1161144357600080fd5b6000828152600960205260409081902054600f5491517fa9059cbb000000000000000000000000000000000000000000000000000000008152909173ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906114ab908590859060040161298b565b602060405180830381600087803b1580156114c557600080fd5b505af11580156114d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114fd919061272f565b61150657600080fd5b60008381526009602052604080822091909155517f3c82435c4b206f0d843119ab50927469b13f586c6b82901b9814c2bb7ca84d0b906115499085908590612fa1565b60405180910390a1505050565b61155e611e76565b73ffffffffffffffffffffffffffffffffffffffff1661157c610fe3565b73ffffffffffffffffffffffffffffffffffffffff16146115af5760405162461bcd60e51b815260040161054690612d5b565b600e55565b60065460009073ffffffffffffffffffffffffffffffffffffffff1633146115ee5760405162461bcd60e51b815260040161054690612dc7565b600b5460ff166116105760405162461bcd60e51b815260040161054690612d26565b600754600a81101561166a575b60008381526008602052604090205473ffffffffffffffffffffffffffffffffffffffff161561166557600a611654846001613021565b61165e9190613183565b925061161d565b61166e565b8092505b60005b61167c600a83612060565b8110156116c857611692816103f3600a85612060565b600082815260096020526040812080549091906116b0908490613021565b909155508190506116c08161314a565b915050611671565b50600e5473ffffffffffffffffffffffffffffffffffffffff85166000908152600d60205260409020541061170f5760405162461bcd60e51b815260040161054690612d90565b61172b8484600160405180602001604052806000815250612077565b600083815260086020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8616179055611782816001613021565b600755600c546005546040517f5173951400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906351739514906117de908490600401612f98565b600060405180830381600087803b1580156117f857600080fd5b505af115801561180c573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff85166000908152600d60205260408120805460019290611846908490613021565b90915550506040517fb2b74b520c5449911caca63eaea39abeb103f3ae116fbfc8d19bf8998215efaa9061187f908790859088906129b1565b60405180910390a150919392505050565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205460ff1690565b73ffffffffffffffffffffffffffffffffffffffff84166118fe5760405162461bcd60e51b815260040161054690612c0f565b611906611e76565b73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614806119465750611946856104de611e76565b6119625760405162461bcd60e51b815260040161054690612bb2565b600061196c611e76565b905061198c81878761197d886121a1565b611986886121a1565b876109cf565b600084815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a168452909152902054838110156119dc5760405162461bcd60e51b815260040161054690612cc9565b6119e684826130af565b600086815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8c81168552925280832093909355881681529081208054869290611a31908490613021565b925050819055508573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628888604051611aae929190612fc5565b60405180910390a4611ac4828888888888612213565b50505050505050565b611ad5611e76565b73ffffffffffffffffffffffffffffffffffffffff16611af3610fe3565b73ffffffffffffffffffffffffffffffffffffffff1614611b265760405162461bcd60e51b815260040161054690612d5b565b73ffffffffffffffffffffffffffffffffffffffff8116611b595760405162461bcd60e51b815260040161054690612b55565b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600e5481565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f01ffc9a70000000000000000000000000000000000000000000000000000000014919050565b606060038054611c45906130f6565b80601f0160208091040260200160405190810160405280929190818152602001828054611c71906130f6565b8015611cbe5780601f10611c9357610100808354040283529160200191611cbe565b820191906000526020600020905b815481529060010190602001808311611ca157829003601f168201915b50505050509050919050565b606081611d0b575060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015261062c565b8160005b8115611d355780611d1f8161314a565b9150611d2e9050600a8361305e565b9150611d0f565b60008167ffffffffffffffff811115611d77577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015611da1576020820181803683370190505b509050815b8515611e6d57611db76001826130af565b90506000611dc6600a8861305e565b611dd190600a613072565b611ddb90886130af565b611de6906030613039565b905060008160f81b905080848481518110611e2a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611e64600a8961305e565b97505050611da6565b50949350505050565b3390565b611e998473ffffffffffffffffffffffffffffffffffffffff16612366565b156109cf576040517fbc197c8100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063bc197c8190611ef890899089908890889088906004016128d0565b602060405180830381600087803b158015611f1257600080fd5b505af1925050508015611f60575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611f5d91810190612767565b60015b611fa957611f6c61322a565b80611f775750611f91565b8060405162461bcd60e51b81526004016105469190612a2b565b60405162461bcd60e51b815260040161054690612a3e565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c810000000000000000000000000000000000000000000000000000000014611ac45760405162461bcd60e51b815260040161054690612a9b565b60008060015b83811161203e576120208161236c565b61202a9083613021565b9150806120368161314a565b915050612010565b5092915050565b600061205961205484846130af565b61236c565b9392505050565b6000818310156120705781612059565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff84166120aa5760405162461bcd60e51b815260040161054690612f3b565b60006120b4611e76565b90506120c68160008761197d886121a1565b600084815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8916845290915281208054859290612105908490613021565b925050819055508473ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f628787604051612183929190612fc5565b60405180910390a461219a81600087878787612213565b5050505050565b60408051600180825281830190925260609160009190602080830190803683370190505090508281600081518110612202577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602090810291909101015292915050565b6122328473ffffffffffffffffffffffffffffffffffffffff16612366565b156109cf576040517ff23a6e6100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063f23a6e6190612291908990899088908890889060040161293b565b602060405180830381600087803b1580156122ab57600080fd5b505af19250505080156122f9575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526122f691810190612767565b60015b61230557611f6c61322a565b7fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e610000000000000000000000000000000000000000000000000000000014611ac45760405162461bcd60e51b815260040161054690612a9b565b3b151590565b6000600661237b836002613021565b612386846001613021565b6123909085613072565b61239a9190613072565b610629919061305e565b803573ffffffffffffffffffffffffffffffffffffffff8116811461062c57600080fd5b600082601f8301126123d8578081fd5b813560206123ed6123e883612ffd565b612fd3565b8281528181019085830183850287018401881015612409578586fd5b855b858110156124275781358452928401929084019060010161240b565b5090979650505050505050565b600082601f830112612444578081fd5b813567ffffffffffffffff81111561245e5761245e6131f5565b61248f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612fd3565b8181528460208386010111156124a3578283fd5b816020850160208301379081016020019190915292915050565b6000602082840312156124ce578081fd5b612059826123a4565b600080604083850312156124e9578081fd5b6124f2836123a4565b9150612500602084016123a4565b90509250929050565b600080600080600060a08688031215612520578081fd5b612529866123a4565b9450612537602087016123a4565b9350604086013567ffffffffffffffff80821115612553578283fd5b61255f89838a016123c8565b94506060880135915080821115612574578283fd5b61258089838a016123c8565b93506080880135915080821115612595578283fd5b506125a288828901612434565b9150509295509295909350565b600080600080600060a086880312156125c6578081fd5b6125cf866123a4565b94506125dd602087016123a4565b93506040860135925060608601359150608086013567ffffffffffffffff811115612606578182fd5b6125a288828901612434565b60008060408385031215612624578182fd5b61262d836123a4565b9150602083013561263d8161330b565b809150509250929050565b6000806040838503121561265a578182fd5b612663836123a4565b946020939093013593505050565b60008060408385031215612683578182fd5b823567ffffffffffffffff8082111561269a578384fd5b818501915085601f8301126126ad578384fd5b813560206126bd6123e883612ffd565b82815281810190858301838502870184018b10156126d9578889fd5b8896505b84871015612702576126ee816123a4565b8352600196909601959183019183016126dd565b5096505086013592505080821115612718578283fd5b50612725858286016123c8565b9150509250929050565b600060208284031215612740578081fd5b81516120598161330b565b60006020828403121561275c578081fd5b81356120598161331c565b600060208284031215612778578081fd5b81516120598161331c565b600060208284031215612794578081fd5b5035919050565b6000602082840312156127ac578081fd5b5051919050565b600080604083850312156127c5578182fd5b50508035926020909101359150565b6000815180845260208085019450808401835b83811015612803578151875295820195908201906001016127e7565b509495945050505050565b600081518084526128268160208601602086016130c6565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000835161286a8184602088016130c6565b83519083019061287e8183602088016130c6565b7f2e6a736f6e0000000000000000000000000000000000000000000000000000009101908152600501949350505050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525060a0604083015261290960a08301866127d4565b828103606084015261291b81866127d4565b9050828103608084015261292f818561280e565b98975050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015283606083015260a0608083015261298060a083018461280e565b979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9390931683526020830191909152604082015260600190565b60006020825261205960208301846127d4565b600060408252612a0560408301856127d4565b8281036020840152612a1781856127d4565b95945050505050565b901515815260200190565b600060208252612059602083018461280e565b60208082526034908201527f455243313135353a207472616e7366657220746f206e6f6e204552433131353560408201527f526563656976657220696d706c656d656e746572000000000000000000000000606082015260800190565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a6563746560408201527f6420746f6b656e73000000000000000000000000000000000000000000000000606082015260800190565b6020808252602b908201527f455243313135353a2062616c616e636520717565727920666f7220746865207a60408201527f65726f2061646472657373000000000000000000000000000000000000000000606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201527f6464726573730000000000000000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f455243313135353a2063616c6c6572206973206e6f74206f776e6572206e6f7260408201527f20617070726f7665640000000000000000000000000000000000000000000000606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f20616460408201527f6472657373000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526032908201527f455243313135353a207472616e736665722063616c6c6572206973206e6f742060408201527f6f776e6572206e6f7220617070726f7665640000000000000000000000000000606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201527f72207472616e7366657200000000000000000000000000000000000000000000606082015260800190565b6020808252818101527f5f6d696e74446174614e46542e43617465676f7279206d757374206578697374604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601d908201527f53656e64657220686173207573656420616c6c20697473206d696e7473000000604082015260600190565b6020808252602e908201527f4f6e6c792063616c6c61626c652066726f6d207468652067656e65736973206d60408201527f696e74657220636f6e7472616374000000000000000000000000000000000000606082015260800190565b60208082526029908201527f455243313135353a2073657474696e6720617070726f76616c2073746174757360408201527f20666f722073656c660000000000000000000000000000000000000000000000606082015260800190565b60208082526029908201527f455243313135353a206163636f756e747320616e6420696473206c656e67746860408201527f206d69736d617463680000000000000000000000000000000000000000000000606082015260800190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e6774682060408201527f6d69736d61746368000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f2061646472657360408201527f7300000000000000000000000000000000000000000000000000000000000000606082015260800190565b90815260200190565b91825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715612ff557612ff56131f5565b604052919050565b600067ffffffffffffffff821115613017576130176131f5565b5060209081020190565b6000821982111561303457613034613197565b500190565b600060ff821660ff84168060ff0382111561305657613056613197565b019392505050565b60008261306d5761306d6131c6565b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156130aa576130aa613197565b500290565b6000828210156130c1576130c1613197565b500390565b60005b838110156130e15781810151838201526020016130c9565b838111156130f0576000848401525b50505050565b60028104600182168061310a57607f821691505b60208210811415613144577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561317c5761317c613197565b5060010190565b600082613192576131926131c6565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60e01c90565b600060443d101561323a57610d23565b600481823e6308c379a061324e8251613224565b1461325857610d23565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3d016004823e80513d67ffffffffffffffff81602484011181841117156132a65750505050610d23565b828401925082519150808211156132c05750505050610d23565b503d830160208284010111156132d857505050610d23565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810160200160405291505090565b801515811461331957600080fd5b50565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461331957600080fdfea2646970667358221220a00221d16c325c1df027a734797cd7ab8d395b2db3e7230f219f93c7b575588164736f6c63430008000033

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

00000000000000000000000084ca8bc7997272c7cfb4d0cd3d55cd942b3c9419000000000000000000000000000000000000000000000001a055690d9db80000000000000000000000000000000000000000000000000002b5e3af16b1880000000000000000000000000000660062a92c8ce918598bad2280ef0db99e4dbcb500000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000042697066733a2f2f516d5531794879433835454b455a454e68566361735678466936785047676e394133457568707159744a39774a622f43727970746f50756e6b732f000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _paymentToken (address): 0x84cA8bc7997272c7CfB4D0Cd3D55cd942B3c9419
Arg [1] : _burnAmount (uint256): 30000000000000000000
Arg [2] : _mintingPoolAmount (uint256): 50000000000000000000
Arg [3] : _DIAGenesisMinterAddr (address): 0x660062A92C8cE918598BAD2280eF0Db99e4DBcb5
Arg [4] : metadataURI (bytes): 0x697066733a2f2f516d5531794879433835454b455a454e68566361735678466936785047676e394133457568707159744a39774a622f43727970746f50756e6b732f

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000084ca8bc7997272c7cfb4d0cd3d55cd942b3c9419
Arg [1] : 000000000000000000000000000000000000000000000001a055690d9db80000
Arg [2] : 000000000000000000000000000000000000000000000002b5e3af16b1880000
Arg [3] : 000000000000000000000000660062a92c8ce918598bad2280ef0db99e4dbcb5
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000042
Arg [6] : 697066733a2f2f516d5531794879433835454b455a454e685663617356784669
Arg [7] : 36785047676e394133457568707159744a39774a622f43727970746f50756e6b
Arg [8] : 732f000000000000000000000000000000000000000000000000000000000000


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.