ETH Price: $2,066.46 (-0.62%)
Gas: 0.47 Gwei
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Safe Transfer Fr...163880582023-01-12 3:32:47803 days ago1673494367IN
Fake_Phishing297791
0 ETH0.0012145221.22777802
Commit159046982022-11-05 15:26:11871 days ago1667661971IN
Fake_Phishing297791
0 ETH0.000612313.71210286
Commit159045682022-11-05 14:59:59871 days ago1667660399IN
Fake_Phishing297791
0 ETH0.0007279916.30308546
Challenge158751512022-11-01 12:23:11875 days ago1667305391IN
Fake_Phishing297791
0 ETH0.0022884214.5741155
Challenge158751482022-11-01 12:22:35875 days ago1667305355IN
Fake_Phishing297791
0 ETH0.0009251915.49454873
Challenge158751092022-11-01 12:14:35875 days ago1667304875IN
Fake_Phishing297791
0 ETH0.0008019113.33443861
Challenge158751022022-11-01 12:13:11875 days ago1667304791IN
Fake_Phishing297791
0 ETH0.0007682512.77287517
Challenge158750972022-11-01 12:12:11875 days ago1667304731IN
Fake_Phishing297791
0 ETH0.0008086913.83820679
Commit158750082022-11-01 11:54:23875 days ago1667303663IN
Fake_Phishing297791
0 ETH0.0004683210.48787505
Commit158734242022-11-01 6:32:11875 days ago1667284331IN
Fake_Phishing297791
0 ETH0.000400568.970363
Challenge158733562022-11-01 6:18:35875 days ago1667283515IN
Fake_Phishing297791
0 ETH0.0015508610.98696727
Challenge158733542022-11-01 6:18:11875 days ago1667283491IN
Fake_Phishing297791
0 ETH0.0006712511.24868645
Challenge158733522022-11-01 6:17:47875 days ago1667283467IN
Fake_Phishing297791
0 ETH0.000667610.95266305
Commit158732842022-11-01 6:04:11875 days ago1667282651IN
Fake_Phishing297791
0 ETH0.000482810.81205447
Challenge158719182022-11-01 1:27:47875 days ago1667266067IN
Fake_Phishing297791
0 ETH0.0020486813.33994419
Challenge158718892022-11-01 1:21:59875 days ago1667265719IN
Fake_Phishing297791
0 ETH0.0010218914.17605064
Commit158717852022-11-01 1:01:11875 days ago1667264471IN
Fake_Phishing297791
0 ETH0.0009693821.70878173
Commit158717712022-11-01 0:58:23875 days ago1667264303IN
Fake_Phishing297791
0 ETH0.0007334416.42497411
Commit158717142022-11-01 0:46:59875 days ago1667263619IN
Fake_Phishing297791
0 ETH0.0006516914.59443223
Commit158716902022-11-01 0:42:11875 days ago1667263331IN
Fake_Phishing297791
0 ETH0.0007130715.97327117
Commit158714692022-10-31 23:57:59875 days ago1667260679IN
Fake_Phishing297791
0 ETH0.0013982431.31288771
Challenge158700102022-10-31 19:04:23875 days ago1667243063IN
Fake_Phishing297791
0 ETH0.0060633731.17783362
Challenge158699792022-10-31 18:58:11875 days ago1667242691IN
Fake_Phishing297791
0 ETH0.0025099826.06102592
Commit158695942022-10-31 17:40:23875 days ago1667238023IN
Fake_Phishing297791
0 ETH0.001557234.8727536
Commit158678882022-10-31 11:57:11876 days ago1667217431IN
Fake_Phishing297791
0 ETH0.0008141418.23238199
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Optimizor

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 13 : Optimizor.sol
//
//
//               .+++++++++++++++++++            +++++++++++++++++++++.
//               .+++++++++++++++++++            +++++++++++++++++++++.
//                  +++++++++++++++++++.           +++++++++++++++++++++
//                  +++++++++++++++++++.           +++++++++++++++++++-:
//            +: .+++++++++++++++++++++++    +=  +++++++++++++++++++++.
//            +-.:+++++++++=======+++++++    +=..+++++++++============.
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++:     :+++++++    +++++++++++++:
//            +++++++++++++++++++++++++++    +++++++++++++++++++++++++.
//            +++++++++++++++++++++++++++    +++++++++++++++++++++++++.
//            +++++++++++++++++++++++++++    +++++++++++++++++++++++++++
//            +++++++++++++++++++++++++++    +++++++++++++++++++++++++++
//             .+++++++++++++++++++++++.       +++++++++++++++++++++++++
//             .+++++++++++++++++++++++.       +++++++++++++++++++++++++
//               .+++++++++++++++++++            +++++++++++++++++++++.
//               .+++++++++++++++++++            +++++++++++++++++++++.
//
//
// The Optimizor Club NFT collection rewards gas efficient people and machines by
// minting new items whenever a cheaper solution is submitted for a certain challenge.
//

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {OptimizorAdmin, OptimizorNFT} from "src/OptimizorAdmin.sol";
import {IPurityChecker} from "src/IPurityChecker.sol";
import {packTokenId} from "src/DataHelpers.sol";
import {ERC721} from "solmate/tokens/ERC721.sol";

uint256 constant EPOCH = 64;

contract Optimizor is OptimizorAdmin {
    struct Submission {
        address sender;
        uint96 blockNumber;
    }

    /// Maps a submitted key to its sender and submission block number.
    mapping(bytes32 => Submission) public submissions;

    // Commit errors
    error CodeAlreadySubmitted();
    error TooEarlyToChallenge();

    // Input filtering
    error InvalidRecipient();
    error CodeNotSubmitted();
    error NotPure();

    // Sadness
    error NotOptimizor();

    constructor(IPurityChecker _purityChecker) OptimizorAdmin(_purityChecker) {}

    /// Commit a `key` derived using
    /// `keccak256(abi.encode(sender, codehash, salt))`
    /// where
    /// - `sender`: the `msg.sender` for the call to `challenge(...)`,
    /// - `target`: the address of your solution contract,
    /// - `salt`: `uint256` secret number.
    function commit(bytes32 key) external {
        if (submissions[key].sender != address(0)) {
            revert CodeAlreadySubmitted();
        }
        submissions[key] = Submission({sender: msg.sender, blockNumber: uint96(block.number)});
    }

    /// After committing and waiting for at least 256 blocks, challenge can be
    /// called to claim an Optimizor Club NFT, if it beats the previous solution
    /// in terms of runtime gas.
    ///
    /// @param id The unique identifier for the challenge.
    /// @param target The address of your solution contract.
    /// @param recipient The address that receives the Optimizor Club NFT.
    /// @param salt The secret number used for deriving the committed key.
    function challenge(uint256 id, address target, address recipient, uint256 salt) external {
        ChallengeInfo storage chl = challenges[id];

        bytes32 key = keccak256(abi.encode(msg.sender, target.codehash, salt));

        // Frontrunning cannot steal the submission, but can block
        // it for users at the expense of the frontrunner's gas.
        // We consider that a non-issue.
        if (submissions[key].blockNumber + EPOCH >= block.number) {
            revert TooEarlyToChallenge();
        }

        if (submissions[key].sender == address(0)) {
            revert CodeNotSubmitted();
        }

        if (address(chl.target) == address(0)) {
            revert ChallengeNotFound(id);
        }

        if (recipient == address(0)) {
            revert InvalidRecipient();
        }

        if (!purityChecker.check(target)) {
            revert NotPure();
        }

        uint32 gas = chl.target.run(target, block.difficulty);

        uint256 leaderTokenId = packTokenId(id, chl.solutions);
        uint32 leaderGas = extraDetails[leaderTokenId].gas;

        if ((leaderGas != 0) && (leaderGas <= gas)) {
            revert NotOptimizor();
        }

        unchecked {
            ++chl.solutions;
        }

        uint256 tokenId = packTokenId(id, chl.solutions);
        ERC721._mint(recipient, tokenId);
        extraDetails[tokenId] = ExtraDetails(target, recipient, gas);
    }
}

File 2 of 13 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

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

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

File 3 of 13 : ERC721.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) public view virtual returns (address owner) {
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) public view virtual returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = _ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == _ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(_ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = _ownerOf[id];

        require(owner != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            _balanceOf[owner]--;
        }

        delete _ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

File 4 of 13 : LibString.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Efficient library for creating string representations of integers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
/// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol)
library LibString {
    function toString(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes
            // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the
            // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes.
            let newFreeMemoryPointer := add(mload(0x40), 160)

            // Update the free memory pointer to avoid overriding our string.
            mstore(0x40, newFreeMemoryPointer)

            // Assign str to the end of the zone of newly allocated memory.
            str := sub(newFreeMemoryPointer, 32)

            // Clean the last word of memory it may not be overwritten.
            mstore(str, 0)

            // Cache the end of the memory to calculate the length later.
            let end := str

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // prettier-ignore
            for { let temp := value } 1 {} {
                // Move the pointer 1 byte to the left.
                str := sub(str, 1)

                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))

                // Keep dividing temp until zero.
                temp := div(temp, 10)

                 // prettier-ignore
                if iszero(temp) { break }
            }

            // Compute and cache the final total length of the string.
            let length := sub(end, str)

            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 32)

            // Store the string's length at the start of memory allocated for our string.
            mstore(str, length)
        }
    }
}

File 5 of 13 : Base64.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <[email protected]>
library Base64 {
    bytes private constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /// @notice Encodes some bytes to the base64 representation
    function encode(bytes memory data) internal pure returns (string memory result) {
        uint256 len = data.length;
        if (len == 0) return "";

        // multiply by 4/3 rounded up
        uint256 encodedLen;
        unchecked {
            // We assume reaching overflow is unfeasible in our use cases.
            encodedLen = 4 * ((len + 2) / 3);
        }

        // Add some extra buffer at the end
        unchecked {
            result = new string(encodedLen + 32);
        }

        // Until constants are supported in inline assembly.
        bytes memory table = TABLE;

        assembly ("memory-safe") {
            let tablePtr := add(table, 1)
            let resultPtr := add(result, 32)

            for { let i := 0 } lt(i, len) {} {
                i := add(i, 3)
                let input := and(mload(add(data, i)), 0xffffff)

                let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
                out := shl(8, out)
                out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))
                out := shl(8, out)
                out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))
                out := shl(8, out)
                out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
                out := shl(224, out)

                mstore(resultPtr, out)

                resultPtr := add(resultPtr, 4)
            }

            switch mod(len, 3)
            case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
            case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }

            mstore(result, encodedLen)
        }

        return result;
    }
}

File 6 of 13 : DataHelpers.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

function packTokenId(uint256 challengeId, uint32 solutionId) pure returns (uint256) {
    return (challengeId << 32) | solutionId;
}

function unpackTokenId(uint256 tokenId) pure returns (uint256 challengeId, uint32 solutionId) {
    challengeId = tokenId >> 32;
    solutionId = uint32(tokenId);
}

File 7 of 13 : HexString.sol
// This file is derived from https://github.com/Uniswap/v3-periphery/blob/b771ff9a20a0fd7c3233df0eb70d4fa084766cde/contracts/libraries/HexStrings.sol
// which in turn originates from OpenZeppelin under an MIT license.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

library HexString {
    /// Provided length is insufficient to store the value.
    error HexLengthInsufficient();

    bytes16 private constant ALPHABET = "0123456789abcdef";

    function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length);
        unchecked {
            for (uint256 i = buffer.length; i > 0; --i) {
                buffer[i - 1] = ALPHABET[value & 0xf];
                value >>= 4;
            }
        }
        if (value != 0) revert HexLengthInsufficient();
        return string(buffer);
    }

    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        unchecked {
            for (uint256 i = 2 * length + 1; i > 1; --i) {
                buffer[i] = ALPHABET[value & 0xf];
                value >>= 4;
            }
        }
        if (value != 0) revert HexLengthInsufficient();
        return string(buffer);
    }
}

File 8 of 13 : IChallenge.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface IChallenge {
    /// Execute a given solution, using the seed to generate inputs. The actual
    /// implementation is specific to the challenge.
    /// @return The amount of gas consumed by the solution.
    function run(address target, uint256 seed) external view returns (uint32);

    /// @return An SVG snippet, which is embedded in the main NFT.
    function svg(uint256 tokenId) external view returns (string memory);

    /// @return The name of the challenge.
    function name() external view returns (string memory);

    /// @return The description of the challenge.
    /// @notice Should not have line breaks.
    function description() external view returns (string memory);
}

File 9 of 13 : IPurityChecker.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface IPurityChecker {
    /// @return True if the code of the given account satisfies the code purity requirements.
    function check(address account) external view returns (bool);
}

File 10 of 13 : NFTSVG.sol
// This file is derived from https://github.com/Uniswap/v3-periphery/blob/b771ff9a20a0fd7c3233df0eb70d4fa084766cde/contracts/libraries/NFTSVG.sol

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.17;

import {Base64} from "src/Base64.sol";
import {HexString} from "src/HexString.sol";

import {LibString} from "solmate/utils/LibString.sol";

/// @title NFTSVG
/// @notice Provides a function for generating an SVG associated with a Uniswap NFT
library NFTSVG {
    struct SVGParams {
        string projectName;
        string challengeName;
        string solverAddr;
        string challengeAddr;
        uint256 gasUsed;
        uint256 gasOpti;
        uint256 tokenId;
        uint32 rank;
        uint32 participants;
        string color;
        uint256 x1;
        uint256 y1;
        uint256 x2;
        uint256 y2;
        uint256 x3;
        uint256 y3;
    }

    function generateSVG(SVGParams memory params, string memory challengeSVG)
        internal
        pure
        returns (string memory svg)
    {
        return string.concat(
            generateSVGDefs(params),
            generateSVGBorderText(params.projectName, params.challengeName, params.solverAddr, params.challengeAddr),
            generateSVGCardMantle(params.challengeName, params.rank, params.participants),
            generateRankBorder(params.rank),
            generateSvgCurve(challengeSVG),
            generateSVGPositionDataAndLocationCurve(LibString.toString(params.tokenId), params.gasUsed, params.gasOpti),
            generateOptimizorIcon(),
            "</svg>"
        );
    }

    function generateSVGDefs(SVGParams memory params) private pure returns (string memory svg) {
        svg = string.concat(
            '<svg width="290" height="500" viewBox="0 0 290 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'
            "<defs>"
            '<filter id="icon"><feImage result="icon" xlink:href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTY2LjU5NyIgaGVpZ2h0PSIxMjguOTQxIiB2aWV3Qm94PSIwIDAgNDQuMDc5IDM0LjExNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMjAuNzkzIDEzLjMyMWgtLjYyM1YxMi43aC02LjIyNXYuNjIyaC42MjJ2LjYyM2gtLjYyMnYuNjIyaC0uNjIzdi0uNjIySDEyLjd2Ni4yMjVoLjYyMnYuNjIzaC42MjN2LjYyMmg2LjIyNXYtLjYyMmguNjIzdi0uNjIzaC42MjJ2LTYuMjI1aC0uNjIyem0tMy43MzUgNS42MDN2LTQuMzU4aDEuODY3djQuMzU4em0xMy42OTgtNi4yMjVoLTYuODQ4di42MjJoLjYyM3YuNjIzaC0uNjIzdi42MjJoLS42MjJ2LS42MjJoLS42MjN2Ni4yMjVoLjYyM3YuNjIzaC42MjJ2LjYyMmg2Ljg0OHYtLjYyMmguNjIydi0xLjI0NWgtLjYyMnYtLjYyM0gyNy4wMnYtNC4zNThoMy43MzV2LS42MjJoLjYyMnYtLjYyM2gtLjYyMnoiIHN0eWxlPSJmaWxsOiM2NjYiLz48L3N2Zz4="/></filter>'
            '<filter id="f1"><feImage result="p0" xlink:href="data:image/svg+xml;base64,',
            Base64.encode(
                bytes(
                    string.concat(
                        "<svg width='290' height='500' viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><rect width='290' height='500' fill='#",
                        params.color,
                        "'/></svg>"
                    )
                )
            ),
            '"/><feImage result="p1" xlink:href="data:image/svg+xml;base64,',
            Base64.encode(
                bytes(
                    string.concat(
                        "<svg width='290' height='500' viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><circle cx='",
                        LibString.toString(params.x1),
                        "' cy='",
                        LibString.toString(params.y1),
                        "' r='120' fill='#",
                        params.color,
                        "'/></svg>"
                    )
                )
            ),
            '"/><feImage result="p2" xlink:href="data:image/svg+xml;base64,',
            Base64.encode(
                bytes(
                    string.concat(
                        "<svg width='290' height='500' viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><circle cx='",
                        LibString.toString(params.x2),
                        "' cy='",
                        LibString.toString(params.y2),
                        "' r='120' fill='#",
                        params.color,
                        "'/></svg>"
                    )
                )
            ),
            '" />',
            '<feImage result="p3" xlink:href="data:image/svg+xml;base64,',
            Base64.encode(
                bytes(
                    string.concat(
                        "<svg width='290' height='500' viewBox='0 0 290 500' xmlns='http://www.w3.org/2000/svg'><circle cx='",
                        LibString.toString(params.x3),
                        "' cy='",
                        LibString.toString(params.y3),
                        "' r='100' fill='#",
                        params.color,
                        "'/></svg>"
                    )
                )
            ),
            '"/><feBlend mode="overlay" in="p0" in2="p1"/><feBlend mode="exclusion" in2="p2"/><feBlend mode="overlay" in2="p3" result="blendOut"/><feGaussianBlur '
            'in="blendOut" stdDeviation="42"/></filter><clipPath id="corners"><rect width="290" height="500" rx="42" ry="42"/></clipPath>'
            '<path id="text-path-a" d="M40 12 H250 A28 28 0 0 1 278 40 V460 A28 28 0 0 1 250 488 H40 A28 28 0 0 1 12 460 V40 A28 28 0 0 1 40 12 z"/>'
            '<path id="minimap" d="M234 444C234 457.949 242.21 463 253 463"/>'
            '<filter id="top-region-blur"><feGaussianBlur in="SourceGraphic" stdDeviation="24"/></filter>'
            '<linearGradient id="grad-up" x1="1" x2="0" y1="1" y2="0"><stop offset="0.0" stop-color="#fff" stop-opacity="1"/>'
            '<stop offset=".9" stop-color="#fff" stop-opacity="0"/></linearGradient>'
            '<linearGradient id="grad-down" x1="0" x2="1" y1="0" y2="1"><stop offset="0.0" stop-color="#fff" stop-opacity="1"/><stop offset="0.9" stop-color="#fff" stop-opacity="0"/></linearGradient>'
            '<mask id="fade-up" maskContentUnits="objectBoundingBox"><rect width="1" height="1" fill="url(#grad-up)"/></mask>'
            '<mask id="fade-down" maskContentUnits="objectBoundingBox"><rect width="1" height="1" fill="url(#grad-down)"/></mask>'
            '<mask id="none" maskContentUnits="objectBoundingBox"><rect width="1" height="1" fill="#fff"/></mask>'
            '<linearGradient id="grad-symbol"><stop offset="0.7" stop-color="#fff" stop-opacity="1"/><stop offset=".95" stop-color="#fff" stop-opacity="0"/></linearGradient>'
            '<mask id="fade-symbol" maskContentUnits="userSpaceOnUse"><rect width="290" height="200" fill="url(#grad-symbol)"/></mask></defs>'
            '<g clip-path="url(#corners)">' '<rect fill="',
            params.color,
            '" x="0" y="0" width="290" height="500"/>'
            '<rect style="filter: url(#f1)" x="0" y="0" width="290" height="500"/>'
            '<g style="filter:url(#top-region-blur); transform:scale(1.5); transform-origin:center top;">'
            '<rect fill="none" x="0" y="0" width="290" height="500"/>'
            '<ellipse cx="50%" cy="0" rx="180" ry="120" fill="#000" opacity="0.85"/></g>'
            '<rect x="0" y="0" width="290" height="500" rx="42" ry="42" fill="rgba(0,0,0,0)" stroke="rgba(255,255,255,0.2)"/></g>'
        );
    }

    function generateSVGBorderText(
        string memory projectName,
        string memory challengeName,
        string memory solverAddr,
        string memory challengeAddr
    ) private pure returns (string memory svg) {
        svg = string.concat(
            '<text text-rendering="optimizeSpeed">'
            '<textPath startOffset="-100%" fill="#fff" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">',
            challengeName,
            unicode" • ",
            challengeAddr,
            '<animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite"/>'
            '</textPath> <textPath startOffset="0%" fill="#fff" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">',
            challengeName,
            unicode" • ",
            challengeAddr,
            '<animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite"/></textPath>'
            '<textPath startOffset="50%" fill="#fff" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">',
            projectName,
            unicode" • ",
            solverAddr,
            '<animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s"'
            ' repeatCount="indefinite"/></textPath><textPath startOffset="-50%" fill="#fff" font-family="\'Courier New\', monospace" font-size="10px" xlink:href="#text-path-a">',
            projectName,
            unicode" • ",
            solverAddr,
            '<animate additive="sum" attributeName="startOffset" from="0%" to="100%" begin="0s" dur="30s" repeatCount="indefinite"/></textPath></text>'
        );
    }

    function generateSVGCardMantle(string memory challengeName, uint32 rank, uint32 participants)
        private
        pure
        returns (string memory svg)
    {
        svg = string.concat(
            '<g mask="url(#fade-symbol)"><rect fill="none" x="0" y="0" width="290" height="200"/><text y="70" x="32" fill="#fff" font-family="\'Courier New\', monospace" font-weight="200" font-size="28px">',
            challengeName,
            '</text><text y="115" x="32" fill="#fff" font-family="\'Courier New\', monospace" font-weight="200" font-size="20px">'
            "Rank ",
            LibString.toString(rank),
            " of ",
            LibString.toString(participants),
            "</text></g>"
        );
    }

    function generateRankBorder(uint32 rank) private pure returns (string memory svg) {
        string memory color;
        if (rank == 1) {
            // Golden accent.
            color = "rgba(255,215,0,1.0)";
        } else if (rank == 2) {
            // Silver accent.
            color = "rgba(255,255,255,1.0)";
        } else if (rank == 3) {
            // Bronze accent.
            color = "rgba(205,127,50,1.0)";
        } else {
            // Default (grey) accent. Assuming rank 0 is invalid, this case is for rank > 3.
            color = "rgba(255,255,255,0.2)";
        }
        svg = string.concat(
            '<rect x="16" y="16" width="258" height="468" rx="26" ry="26" fill="rgba(0,0,0,0)" stroke="', color, '"/>'
        );
    }

    function generateSvgCurve(string memory challengeSVG) private pure returns (string memory svg) {
        svg = string.concat('<g mask="url(#none)"', ' style="transform:translate(30px,130px)">', challengeSVG, "</g>");
    }

    function generateSVGPositionDataAndLocationCurve(string memory tokenId, uint256 gasUsed, uint256 gasOpti)
        private
        pure
        returns (string memory svg)
    {
        string memory gasUsedStr = LibString.toString(gasUsed);
        string memory gasOptiStr = LibString.toString(gasOpti);
        uint256 str1length = bytes(tokenId).length + 4;
        uint256 str2length = bytes(gasUsedStr).length + 10;
        uint256 str3length = bytes(gasOptiStr).length + 14;
        svg = string.concat(
            '<g font-family="\'Courier New\', monospace" font-size="12" fill="#fff">'
            '<g style="transform:translate(29px, 384px)">' '<rect width="',
            LibString.toString(uint256(7 * (str1length + 4))),
            '" height="26" rx="8" ry="8" fill="rgba(0,0,0,0.6)"/>' '<text x="12" y="17"><tspan fill="#999">ID: </tspan>',
            tokenId,
            "</text></g>" '<g style="transform:translate(29px, 414px)">' '<rect width="',
            LibString.toString(uint256(7 * (str2length + 4))),
            '" height="26" rx="8" ry="8" fill="rgba(0,0,0,0.6)"/>'
            '<text x="12" y="17"><tspan fill="#999">Gas used: </tspan>',
            gasUsedStr,
            "</text></g>" '<g style="transform:translate(29px, 444px)">' '<rect width="',
            LibString.toString(uint256(7 * (str3length + 4))),
            '" height="26" rx="8" ry="8" fill="rgba(0,0,0,0.6)"/>'
            '<text x="12" y="17"><tspan fill="#999">Improvement: </tspan>',
            gasOptiStr,
            "%" "</text></g></g>"
        );
    }

    function generateOptimizorIcon() private pure returns (string memory svg) {
        return
        '<g style="transform:translate(180px, 365px)"><rect style="filter: url(#icon)" x="0" y="0" width="83" height="64"/></g>';
    }

    // This picks a "random number" out of a tokenAddress/offset/tokenId tuple.
    // Assumes offset <= 158.
    function getCircleCoord(address tokenAddress, uint256 offset, uint256 tokenId) internal pure returns (uint8) {
        unchecked {
            // This can wrap around by design.
            return uint8((((uint256(uint160(tokenAddress)) >> offset) & 0xFF) * tokenId) % 255);
        }
    }
}

File 11 of 13 : OptimizorAdmin.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {OptimizorNFT} from "src/OptimizorNFT.sol";
import {IPurityChecker} from "src/IPurityChecker.sol";
import {IChallenge} from "src/IChallenge.sol";

import {Owned} from "solmate/auth/Owned.sol";

contract OptimizorAdmin is OptimizorNFT, Owned {
    /// The address of the currently used purity checker.
    IPurityChecker public purityChecker;

    error ChallengeExists(uint256 challengeId);

    event PurityCheckerUpdated(IPurityChecker newPurityChecker);
    event ChallengeAdded(uint256 challengeId, IChallenge);

    constructor(IPurityChecker _purityChecker) Owned(msg.sender) {
        updatePurityChecker(_purityChecker);
    }

    /// @dev Purity checker may need to be updated when there are EVM changes.
    function updatePurityChecker(IPurityChecker _purityChecker) public onlyOwner {
        purityChecker = _purityChecker;

        emit PurityCheckerUpdated(_purityChecker);
    }

    function addChallenge(uint256 id, IChallenge challenge) external onlyOwner {
        ChallengeInfo storage chl = challenges[id];
        if (address(chl.target) != address(0)) {
            revert ChallengeExists(id);
        }

        chl.target = challenge;

        emit ChallengeAdded(id, challenge);
    }
}

File 12 of 13 : OptimizorNFT.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {IChallenge} from "src/IChallenge.sol";
import {Base64} from "src/Base64.sol";
import {packTokenId, unpackTokenId} from "src/DataHelpers.sol";
import {NFTSVG} from "src/NFTSVG.sol";
import {TokenDetails} from "src/TokenDetails.sol";
import {HexString} from "src/HexString.sol";

import {ERC721} from "solmate/tokens/ERC721.sol";
import {LibString} from "solmate/utils/LibString.sol";

contract OptimizorNFT is ERC721 {
    // Invalid inputs
    error InvalidSolutionId(uint256 challengeId, uint32 solutionId);

    // Challenge id errors
    error ChallengeNotFound(uint256 challengeId);

    struct ChallengeInfo {
        /// The address of the challenge contract.
        IChallenge target;
        /// The number of valid solutions so far.
        uint32 solutions;
    }

    struct ExtraDetails {
        /// The address of the solution contract.
        address code;
        /// The address of the challenger who called `challenge`.
        address solver;
        /// The amount of gas spent by this solution.
        uint32 gas;
    }

    /// Maps challenge ids to their contracts and amount of solutions.
    mapping(uint256 => ChallengeInfo) public challenges;

    /// Maps token ids to extra details about the solution.
    mapping(uint256 => ExtraDetails) public extraDetails;

    constructor() ERC721("Optimizor Club", "OC") {}

    function contractURI() external pure returns (string memory) {
        return
        "data:application/json;base64,eyJuYW1lIjoiT3B0aW1pem9yIENsdWIiLCJkZXNjcmlwdGlvbiI6IlRoZSBPcHRpbWl6b3IgQ2x1YiBORlQgY29sbGVjdGlvbiByZXdhcmRzIGdhcyBlZmZpY2llbnQgcGVvcGxlIGFuZCBtYWNoaW5lcyBieSBtaW50aW5nIG5ldyBpdGVtcyB3aGVuZXZlciBhIGNoZWFwZXIgc29sdXRpb24gaXMgc3VibWl0dGVkIGZvciBhIGNlcnRhaW4gY2hhbGxlbmdlLiIsImltYWdlIjoiZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCM2FXUjBhRDBpTVRZMkxqVTVOeUlnYUdWcFoyaDBQU0l4TWpndU9UUXhJaUIyYVdWM1FtOTRQU0l3SURBZ05EUXVNRGM1SURNMExqRXhOaUlnZUcxc2JuTTlJbWgwZEhBNkx5OTNkM2N1ZHpNdWIzSm5Mekl3TURBdmMzWm5JajQ4Y0dGMGFDQmtQU0pOTWpBdU56a3pJREV6TGpNeU1XZ3RMall5TTFZeE1pNDNhQzAyTGpJeU5YWXVOakl5YUM0Mk1qSjJMall5TTJndExqWXlNbll1TmpJeWFDMHVOakl6ZGkwdU5qSXlTREV5TGpkMk5pNHlNalZvTGpZeU1uWXVOakl6YUM0Mk1qTjJMall5TW1nMkxqSXlOWFl0TGpZeU1tZ3VOakl6ZGkwdU5qSXphQzQyTWpKMkxUWXVNakkxYUMwdU5qSXllbTB0TXk0M016VWdOUzQyTUROMkxUUXVNelU0YURFdU9EWTNkalF1TXpVNGVtMHhNeTQyT1RndE5pNHlNalZvTFRZdU9EUTRkaTQyTWpKb0xqWXlNM1l1TmpJemFDMHVOakl6ZGk0Mk1qSm9MUzQyTWpKMkxTNDJNakpvTFM0Mk1qTjJOaTR5TWpWb0xqWXlNM1l1TmpJemFDNDJNakoyTGpZeU1tZzJMamcwT0hZdExqWXlNbWd1TmpJeWRpMHhMakkwTldndExqWXlNbll0TGpZeU0wZ3lOeTR3TW5ZdE5DNHpOVGhvTXk0M016VjJMUzQyTWpKb0xqWXlNbll0TGpZeU0yZ3RMall5TW5vaUlITjBlV3hsUFNKbWFXeHNPaU0yTmpZaUx6NDhMM04yWno0PSIsImV4dGVybmFsX2xpbmsiOiJodHRwczovL29wdGltaXpvci5jbHViLyJ9";
    }

    function tokenDetails(uint256 tokenId) public view returns (TokenDetails memory) {
        (uint256 challengeId, uint32 solutionId) = unpackTokenId(tokenId);
        if (solutionId == 0) revert InvalidSolutionId(challengeId, solutionId);

        ChallengeInfo storage chl = challenges[challengeId];
        if (address(chl.target) == address(0)) revert ChallengeNotFound(challengeId);
        if (solutionId > chl.solutions) revert InvalidSolutionId(challengeId, solutionId);

        ExtraDetails storage details = extraDetails[tokenId];

        uint256 leaderTokenId = packTokenId(challengeId, chl.solutions);
        ExtraDetails storage leaderDetails = extraDetails[leaderTokenId];

        uint32 leaderSolutionId = chl.solutions;
        uint32 rank = leaderSolutionId - solutionId + 1;

        // This means the first holder will have a 0% improvement.
        uint32 percentage = 0;
        if (solutionId > 1) {
            ExtraDetails storage prevDetails = extraDetails[tokenId - 1];
            percentage = (details.gas * 100) / prevDetails.gas;
        }

        return TokenDetails({
            challengeId: challengeId,
            challenge: chl.target,
            leaderGas: leaderDetails.gas,
            leaderSolutionId: leaderSolutionId,
            leaderSolver: leaderDetails.solver,
            leaderOwner: _ownerOf[leaderTokenId],
            leaderSubmission: leaderDetails.code,
            gas: details.gas,
            solutionId: solutionId,
            rank: rank,
            improvementPercentage: percentage,
            solver: details.solver,
            owner: _ownerOf[tokenId],
            submission: details.code
        });
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        TokenDetails memory details = tokenDetails(tokenId);

        string memory description = string.concat(details.challenge.description(), "\\n\\n", leaderboardString(tokenId));

        return string.concat(
            "data:application/json;base64,",
            Base64.encode(
                bytes(
                    string.concat(
                        '{"name":"Optimizor Club: ',
                        details.challenge.name(),
                        '","description":"',
                        description,
                        '","attributes":',
                        attributesJSON(details),
                        ',"image":"data:image/svg+xml;base64,',
                        Base64.encode(bytes(svg(tokenId, details))),
                        '"}'
                    )
                )
            )
        );
    }

    function leaderboard(uint256 tokenId) public view returns (address[] memory board) {
        (uint256 challengeId,) = unpackTokenId(tokenId);
        uint32 winners = challenges[challengeId].solutions;
        board = new address[](winners);
        unchecked {
            for (uint32 i = 1; i <= winners; ++i) {
                ExtraDetails storage details = extraDetails[packTokenId(challengeId, i)];
                board[i - 1] = details.solver;
            }
        }
    }

    function leaderboardString(uint256 tokenId) private view returns (string memory) {
        address[] memory leaders = leaderboard(tokenId);
        string memory leadersStr = "";
        uint256 lIdx = leaders.length;
        unchecked {
            for (uint256 i = 0; i < leaders.length; ++i) {
                leadersStr = string.concat(
                    "\\n",
                    LibString.toString(lIdx),
                    ". ",
                    HexString.toHexString(uint256(uint160(leaders[i])), 20),
                    leadersStr
                );
                --lIdx;
            }
        }
        return string.concat("Leaderboard:\\n", leadersStr);
    }

    function attributesJSON(TokenDetails memory details) private view returns (string memory attributes) {
        uint32 rank = details.rank;

        attributes = string.concat(
            '[{"trait_type":"Challenge","value":"',
            details.challenge.name(),
            '"},{"trait_type":"Gas used","value":',
            LibString.toString(details.gas),
            ',"display_type":"number"},{"trait_type":"Code size","value":',
            LibString.toString(details.submission.code.length),
            ',"display_type":"number"},{"trait_type":"Improvement percentage","value":"',
            LibString.toString(details.improvementPercentage),
            '%"},{"trait_type":"Solver","value":"',
            HexString.toHexString(uint256(uint160(details.solver)), 20),
            '"},{"trait_type":"Rank","value":',
            LibString.toString(rank),
            ',"display_type":"number"},{"trait_type":"Leader","value":"',
            (rank == 1) ? "Yes" : "No",
            '"},{"trait_type":"Top 3","value":"',
            (rank <= 3) ? "Yes" : "No",
            '"},{"trait_type":"Top 10","value":"',
            (rank <= 10) ? "Yes" : "No",
            '"}]'
        );
    }

    // This scales the value from [0,255] to [minOut,maxOut].
    // Assumes 255*maxOut <= 2^256-1.
    function scale(uint8 value, uint256 minOut, uint256 maxOut) private pure returns (uint256) {
        unchecked {
            return ((uint256(value) * (maxOut - minOut)) / 255) + minOut;
        }
    }

    function svg(uint256 tokenId, TokenDetails memory details) private view returns (string memory) {
        uint256 gradRgb = 0;
        if (details.rank > 10) {
            gradRgb = 0xbebebe;
        } else if (details.rank > 3) {
            uint256 fRank;
            uint256 init = 40;
            uint256 factor = 15;
            unchecked {
                fRank = init + details.rank * factor;
            }
            gradRgb = (uint256(fRank) << 16) | (uint256(fRank) << 8) | uint256(fRank);
        }

        NFTSVG.SVGParams memory svgParams = NFTSVG.SVGParams({
            projectName: "Optimizor Club",
            challengeName: details.challenge.name(),
            solverAddr: HexString.toHexString(uint256(uint160(address(details.owner))), 20),
            challengeAddr: HexString.toHexString(uint256(uint160(address(details.challenge))), 20),
            gasUsed: details.gas,
            gasOpti: details.improvementPercentage,
            tokenId: tokenId,
            rank: details.rank,
            // The leader is the last player, e.g. its solution id equals the number of players.
            participants: details.leaderSolutionId,
            color: HexString.toHexStringNoPrefix(gradRgb, 3),
            x1: scale(NFTSVG.getCircleCoord(address(details.challenge), 16, tokenId), 16, 274),
            y1: scale(NFTSVG.getCircleCoord(address(details.solver), 16, tokenId), 100, 484),
            x2: scale(NFTSVG.getCircleCoord(address(details.challenge), 32, tokenId), 16, 274),
            y2: scale(NFTSVG.getCircleCoord(address(details.solver), 32, tokenId), 100, 484),
            x3: scale(NFTSVG.getCircleCoord(address(details.challenge), 48, tokenId), 16, 274),
            y3: scale(NFTSVG.getCircleCoord(address(details.solver), 48, tokenId), 100, 484)
        });

        return NFTSVG.generateSVG(svgParams, details.challenge.svg(tokenId));
    }
}

File 13 of 13 : TokenDetails.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {IChallenge} from "src/IChallenge.sol";

struct TokenDetails {
    /// The ID of the challenge.
    uint256 challengeId;
    /// The address of the challenge contract.
    IChallenge challenge;
    /// Details of the leader (aka rank 1).
    uint32 leaderGas;
    uint32 leaderSolutionId;
    address leaderSolver;
    address leaderOwner;
    address leaderSubmission;
    /// Details of the current token (can be the same as the leader).
    uint32 gas;
    uint32 solutionId;
    uint32 rank;
    /// Improvement percentage compared to the previous rank.
    uint32 improvementPercentage;
    address solver;
    address owner;
    address submission;
}

Settings
{
  "remappings": [
    "ds-test/=lib/solmate/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "puretea/=lib/puretea/src/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200,
    "details": {
      "constantOptimizer": true,
      "yul": true
    }
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IPurityChecker","name":"_purityChecker","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"challengeId","type":"uint256"}],"name":"ChallengeExists","type":"error"},{"inputs":[{"internalType":"uint256","name":"challengeId","type":"uint256"}],"name":"ChallengeNotFound","type":"error"},{"inputs":[],"name":"CodeAlreadySubmitted","type":"error"},{"inputs":[],"name":"CodeNotSubmitted","type":"error"},{"inputs":[],"name":"HexLengthInsufficient","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[{"internalType":"uint256","name":"challengeId","type":"uint256"},{"internalType":"uint32","name":"solutionId","type":"uint32"}],"name":"InvalidSolutionId","type":"error"},{"inputs":[],"name":"NotOptimizor","type":"error"},{"inputs":[],"name":"NotPure","type":"error"},{"inputs":[],"name":"TooEarlyToChallenge","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","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":"challengeId","type":"uint256"},{"indexed":false,"internalType":"contract IChallenge","name":"","type":"address"}],"name":"ChallengeAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IPurityChecker","name":"newPurityChecker","type":"address"}],"name":"PurityCheckerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"contract IChallenge","name":"challenge","type":"address"}],"name":"addChallenge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"salt","type":"uint256"}],"name":"challenge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"challenges","outputs":[{"internalType":"contract IChallenge","name":"target","type":"address"},{"internalType":"uint32","name":"solutions","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"commit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"extraDetails","outputs":[{"internalType":"address","name":"code","type":"address"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"uint32","name":"gas","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"leaderboard","outputs":[{"internalType":"address[]","name":"board","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"purityChecker","outputs":[{"internalType":"contract IPurityChecker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","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":"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":"bytes32","name":"","type":"bytes32"}],"name":"submissions","outputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint96","name":"blockNumber","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenDetails","outputs":[{"components":[{"internalType":"uint256","name":"challengeId","type":"uint256"},{"internalType":"contract IChallenge","name":"challenge","type":"address"},{"internalType":"uint32","name":"leaderGas","type":"uint32"},{"internalType":"uint32","name":"leaderSolutionId","type":"uint32"},{"internalType":"address","name":"leaderSolver","type":"address"},{"internalType":"address","name":"leaderOwner","type":"address"},{"internalType":"address","name":"leaderSubmission","type":"address"},{"internalType":"uint32","name":"gas","type":"uint32"},{"internalType":"uint32","name":"solutionId","type":"uint32"},{"internalType":"uint32","name":"rank","type":"uint32"},{"internalType":"uint32","name":"improvementPercentage","type":"uint32"},{"internalType":"address","name":"solver","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"submission","type":"address"}],"internalType":"struct TokenDetails","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPurityChecker","name":"_purityChecker","type":"address"}],"name":"updatePurityChecker","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608034620003b3576001600160401b0390601f601f196200509a3881900383810183168501868111868210176200039d57859282916040528339602094859181010312620003b357516001600160a01b0381169290839003620003b35762000066620003b8565b90600e82526d27b83a34b6b4bd37b91021b63ab160911b858301526200008b620003b8565b60028152614f4360f01b868201528251938785116200039d576000948554946001958681811c9116801562000392575b8a8210146200037e579081868493116200032b575b508990868311600114620002ca578892620002be575b5050600019600383901b1c191690851b1785555b8151978811620002aa5783548481811c911680156200029f575b888210146200028b5783811162000243575b5086928811600114620001cd575095808493926000805160206200507a83398151915298879692620001c1575b5050600019600383901b1c191690821b1790555b60088054336001600160a01b03199182168117909255917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a36009541617600955604051908152a1604051614ca19081620003d98239f35b01519050388062000153565b8385528685209291908816855b8181106200022d57509284939289926000805160206200507a8339815191529a899897951062000213575b505050811b01905562000167565b015160001960f88460031b161c1916905538808062000205565b82840151855593850193928801928801620001da565b84865287862084808b0160051c8201928a8c1062000281575b0160051c019085905b8281106200027557505062000126565b87815501859062000265565b925081926200025c565b634e487b7160e01b86526022600452602486fd5b90607f169062000114565b634e487b7160e01b85526041600452602485fd5b015190503880620000e6565b9084889416918980528b8a20928a5b8d828210620003145750508411620002fa575b505050811b018555620000fa565b015160001960f88460031b161c19169055388080620002ec565b8385015186558b97909501949384019301620002d9565b9091508780528988208680850160051c8201928c861062000374575b918991869594930160051c01915b82811062000365575050620000d0565b8a815585945089910162000355565b9250819262000347565b634e487b7160e01b88526022600452602488fd5b90607f1690620000bb565b634e487b7160e01b600052604160045260246000fd5b600080fd5b60408051919082016001600160401b038111838210176200039d5760405256fe608080604052600436101561001357600080fd5b60003560e01c908163016ef9fe146140e05750806301ffc9a71461407257806306fdde0314613fb6578063081812fc14613f82578063095ea7b314613ec65780631d29a86214613e5157806323b872dd14613e3a57806342842e0e14613d795780636352211e14613d0a57806370a0823114613c965780638da5cb5b14613c6d5780638f1d377614613c2c57806395d89b4114613b39578063a22cb46514613ab4578063a8d45bbc14613a8b578063b88d4fde14613955578063bf368399146138ec578063c5c9c0a2146138b1578063c87b56dd14610e58578063df0de0d114610a8b578063e8a3d4851461043e578063e985e9c5146103e8578063f14fcbc814610332578063f2fde38b146102c4578063f77c34b5146102185763fc314e311461013d57600080fd5b34610213576020366003190112610213576101c061015c600435614482565b604051908051825260018060a01b0380602083015116602084015263ffffffff8060408401511660408501528060608401511660608501528160808401511660808501528160a08401511660a08501528160c08401511660c08501528060e08401511660e085015261010081818501511690850152610120818185015116908501526101409081840151169084015261016081818401511690840152610180818184015116908401526101a0809201511690820152f35b600080fd5b34610213576040366003190112610213576004356024356001600160a01b03818116918290036102135761025181600854163314614236565b82600052600660205260406000209081549081166102ab576001600160a01b031916821790556040805192835260208301919091527fa74c71f615eb53caa07a622aaa53fd5204fe3f04f0b8ee7f2feeaba5ad38e09791a1005b60405163ad407e2160e01b815260048101859052602490fd5b34610213576020366003190112610213576102dd6141d5565b600854906001600160a01b03906102f73383851614614236565b1680916001600160601b0360a01b1617600855337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b34610213576020366003190112610213576004356000818152600a60205260409020546001600160a01b03919082166103d65760405191604083018381106001600160401b038211176103c05760405233835260208301916001600160601b0343168352600052600a6020526040600020925116906001600160601b0360a01b905160a01b16179055600080f35b634e487b7160e01b600052604160045260246000fd5b604051630499821d60e21b8152600490fd5b34610213576040366003190112610213576104016141d5565b6104096141eb565b9060018060a01b03809116600052600560205260406000209116600052602052602060ff604060002054166040519015158152f35b34610213576000366003190112610213576040516105208101908082106001600160401b038311176103c057610a87916040526104f181527f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c65794a60208201527f755957316c496a6f695433423061573170656d397949454e73645749694c434a60408201527f6b5a584e6a636d6c7764476c7662694936496c526f5a5342506348527062576c60608201527f3662334967513278315969424f526c5167593239736247566a64476c7662694260808201527f795a586468636d527a494764686379426c5a6d5a7059326c6c626e516763475660a08201527f766347786c494746755a43427459574e6f6157356c637942696553427461573560c08201527f306157356e4947356c647942706447567463794233614756755a585a6c63694260e08201527f6849474e6f5a5746775a58496763323973645852706232346761584d676333566101008201527f6962576c306447566b49475a766369426849474e6c636e5268615734675932686101208201527f686247786c626d646c4c694973496d6c745957646c496a6f695a4746305954706101408201527f706257466e5a53397a646d6372654731734f324a68633255324e4378515345346101608201527f79576e6c434d324658556a4268524442705456525a4d6b78715654564f65556c6101808201527f6e5955645763466f796144425155306c345457706e645539555558684a6155496101a08201527f79595664574d3146744f54525155306c33535552425a3035455558564e52474d6101c08201527f315355524e4d4578715258684f61556c6e5a55637863324a7554546c4a6257676101e08201527f775a4568424e6b78354f544e6b4d324e315a48704e6457497a536d354d656b6c6102008201527f3354555242646d4d7a576d354a616a5134593064474d474644516d74515530706102208201527f4f54577042645535366133704a524556365447704e655531585a33524d616c6c6102408201527f355454465a654531704e444e68517a41795447704a655535595758564f616b6c6102608201527f3559554d304d6b3171536a4a4d616c6c3554544a6e6445787157586c4e626c6c6102808201527f31546d704a655746444d48564f616b6c365a476b776455357153586c545245566102a08201527f355447706b4d6b35704e486c4e616c5a765447705a655531755758564f616b6c6102c08201527f3659554d304d6b3171546a4a4d616c6c355457316e4d6b787153586c4f57466c6102e08201527f305447705a655531745a33564f616b6c365a476b776455357153587068517a516103008201527f795457704b4d6b78555758564e616b6b7859554d776455357153586c6c6254426103208201527f3054586b304d3031365657644f557a51795455524f4d6b78555558564e656c556103408201527f30595552466455394557544e6b616c4631545870564e4756744d48684e6554516103608201527f795431526e644535704e486c4e616c5a765446525a645539455554526b6154516103808201527f795457704b6230787157586c4e4d316c31546d704a656d46444d48564f616b6c6103a08201527f365a476b304d6b3171536d394d557a51795457704b4d6b78544e444a4e616b706103c08201527f7654464d304d6b3171546a4a4f61545235545770576230787157586c4e4d316c6103e08201527f31546d704a656d46444e444a4e616b6f795447705a655531745a7a4a4d616d636104008201527f775430685a6445787157586c4e62576431546d704a655752704d48684d616b6b6104208201527f77546c646e6445787157586c4e626c6c305447705a655530775a336c4f6554526104408201527f335457355a644535444e48704f5647687654586b304d303136566a4a4d557a516104608201527f795457704b6230787157586c4e626c6c305447705a655530795a33524d616c6c6104808201527f355457357661556c49546a426c5633687355464e4b6257465865484e506155306104a08201527f79546d705a615578364e44684d4d303479576e6f3050534973496d56346447566104c08201527f79626d467358327870626d73694f694a6f64485277637a6f764c32397764476c6104e08201527074615870766369356a624856694c794a3960781b610500820152604051918291826141a9565b0390f35b3461021357608036600319011261021357600435610aa76141eb565b906001600160a01b036044358181169290839003610213578060005260209360068552604060002092813f916040519287840190338252604085015260643560608501526060845260808401906001600160401b0394808310868411176103c057826040525190209081600052600a895260406000205460a01c60408101809111610e4257431115610e335750600052600a8752816040600020541615610e2157845494828616948515610e09578715610df7578389816009541694602460405180948193631846d2f560e31b835216978860048301525afa908115610da357600091610dc1575b5015610daf578860449660405197888092630381fd1960e41b82528760048301524460248301525afa958615610da357600096610d67575b5063ffffffff809760a01c1690891b9181831760005260078a528760016040600020015460a01c168015159081610d5a575b50610d4857805463ffffffff60a01b1916600192909201881660a01b63ffffffff60a01b1691909117815586905460a01c16179687600052600281528260406000205416610d1357866000526003815260406000206001815401905587600052600281526040600020936001600160601b0360a01b94888682541617905560405191898960007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a460608301918211838310176103c057610d11996001946007936040528452818401998a5288604085019816885260005252826040600020915116848254161781550194511690845416178355511681549063ffffffff60a01b9060a01b169063ffffffff60a01b1916179055565b005b6064906040519062461bcd60e51b82526004820152600e60248201526d1053149150511657d3525395115160921b6044820152fd5b60405163d8d359ef60e01b8152600490fd5b905088881610158b610bf9565b9095508881813d8311610d9c575b610d7f8183614165565b81010312610213575163ffffffff81168103610213579489610bc7565b503d610d75565b6040513d6000823e3d90fd5b6040516324acf8b560e11b8152600490fd5b90508981813d8311610df0575b610dd88183614165565b8101031261021357518015158103610213578a610b8f565b503d610dce565b604051634e46966960e11b8152600490fd5b60249060405190630679b58960e51b82526004820152fd5b60405163229405c560e11b8152600490fd5b63efc54ea560e01b8152600490fd5b634e487b7160e01b600052601160045260246000fd5b3461021357602036600319011261021357610e74600435614482565b6020810151604051633942720b60e11b815290600090829060049082906001600160a01b03165afa908115610da357600091613896575b50610eb760043561496b565b91604051602081018181106001600160401b038211176103c05760405260008152908351906000925b8551841015610f8c57600190610f7e610ef885614a21565b610f12848060a01b03610f0b898c614957565b5116614a71565b90604051938491612e3760f11b602084015261017160f51b8151610f3f8160229460208689019101614186565b840191820152835190610f5b8260249660208885019101614186565b01610f6f8251809360208785019101614186565b01036004810184520182614165565b926000190193019291610ee0565b90611013611021602487600495604051610fde602e8260208101946d2632b0b232b93137b0b9321d2e3760911b8652610fce8151809260208686019101614186565b810103600e810184520182614165565b6040519583610ff7889551809260208089019101614186565b840191632e372e3760e11b602084015251809386840190614186565b010385810184520182614165565b60208201516040516306fdde0360e01b81529360009185919082906001600160a01b03165afa928315610da357600093613879575b5063ffffffff61012083015116926004600060018060a01b03602086015116604051928380926306fdde0360e01b82525afa908115610da35760009161385e575b506110ab63ffffffff60e086015116614a21565b6101a08501519091906110c7906001600160a01b03163b614a21565b956110dc63ffffffff61014088015116614a21565b6101608701519097906110f7906001600160a01b0316614a71565b9061110183614a21565b906001840361385057611112614b3e565b925b6003851161384057600a611126614b3e565b955b1161383257611135614b3e565b955b6040519b8c9860208a017f5b7b2274726169745f74797065223a224368616c6c656e6765222c2276616c7590526332911d1160e11b928360408c01528051908160448d01916020019161118992614186565b7f227d2c7b2274726169745f74797065223a224761732075736564222c2276616c6044918c0191820152633ab2911d60e11b60648201528151916111d69083906068840190602001614186565b01937f2c22646973706c61795f74797065223a226e756d626572227d2c7b227472616994856068820152608881017f745f74797065223a22436f64652073697a65222c2276616c7565223a0000000090528151918260a48301916020019161123d92614186565b018460a482015260c481017f745f74797065223a22496d70726f76656d656e742070657263656e746167652290526916113b30b63ab2911d1160b11b60e48201528151918260ee8301916020019161129492614186565b019060ee82017f25227d2c7b2274726169745f74797065223a22536f6c766572222c2276616c75905261010e820152815190610112928284830191602001916112dc92614186565b019081017f227d2c7b2274726169745f74797065223a2252616e6b222c2276616c7565223a90528251906101329382858301916020019161131c92614186565b019182015261015281017f745f74797065223a224c6561646572222c2276616c7565223a22000000000000905281519061016c9282848301916020019161136292614186565b019081017f227d2c7b2274726169745f74797065223a22546f702033222c2276616c7565229052611d1160f11b61018c82015281519061018e928284830191602001916113ae92614186565b019081017f227d2c7b2274726169745f74797065223a22546f70203130222c2276616c7565905262111d1160e91b6101ae8201528151906101b1928284830191602001916113fb92614186565b019062227d5d60e81b9082015203610194810185526101b40161141e9085614165565b61012083015160049360009163ffffffff16600a811115613809575062bebebe91505b60208101516040516306fdde0360e01b81529560009187919082906001600160a01b03165afa948515610da3576000956137ec575b5061018081015161148f906001600160a01b0316614a71565b60208201519091906114a9906001600160a01b0316614a71565b9563ffffffff60e0830151169363ffffffff610140840151169063ffffffff6101208501511663ffffffff6060860151169190604051916114e98361414a565b60068352602036818501378251805b61379357506137815760208601519361016087015190604051998a6102008101106001600160401b036102008d0111176103c05761010260ff60249f81998e839960009f9b859a60649f9987996101809f97899860109d61020089016040526115646102008a0161414a565b600e6102008a01526d27b83a34b6b4bd37b91021b63ab160911b6102208a015261020089018952602089015260408801526060870152608086015260a085015260043560c085015260e084015261010083015261012082015286838681806004358188871c160206160204016101408201528c838c81808c81600435918e1c160206160204016101608201528683868180600435818860201c160206160204018b8201526101a08d848d81808d816004359160201c16020616020401910152816004359160301c160206160204016101c08a0152816004359160301c160206160204016101e0840152602060018060a01b0391015116604051958680926344b285db60e01b825260043560048301525afa918215610da3576301037b3160e51b957f222f3e3c6665496d61676520726573756c743d2270312220786c696e6b3a68729560009461375c575b50612830610c8361179c61012086015161179760a660405180937f3c7376672077696474683d2732393027206865696768743d273530302720766960208301527f6577426f783d2730203020323930203530302720786d6c6e733d27687474703a60408301527f2f2f7777772e77332e6f72672f323030302f737667273e3c726563742077696460608301527f74683d2732393027206865696768743d27353030272066696c6c3d27230000006080830152611775815180926020609d86019101614186565b81016813979f1e17b9bb339f60b91b609d820152036086810184520182614165565b6147b3565b7f2220783d22302220793d2230222077696474683d2232393022206865696768746117eb6117976117d16101408a0151614a21565b6117df6101608b0151614a21565b6101208b015191614bde565b7f222f3e3c6665426c656e64206d6f64653d226f7665726c61792220696e3d227061183a6117976118206101808c0151614a21565b61182e6101a08d0151614a21565b6101208d015191614bde565b6118f56020611797818d6118526101c0820151614a21565b906101206118646101e0830151614a21565b9101519060405195869361188961187c838701614b5d565b9182815194859201614186565b0165272063793d2760d01b81526118a98251809387600685019101614186565b01702720723d27313030272066696c6c3d272360781b60068201526118d78251809386601785019101614186565b016813979f1e17b9bb339f60b91b6017820152038084520182614165565b926101208b0151956040519e8f7f3c7376672077696474683d2232393022206865696768743d223530302220766960208201527f6577426f783d2230203020323930203530302220786d6c6e733d22687474703a60408201527f2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c6960608201527f6e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b60808201527f223e3c646566733e3c66696c7465722069643d2269636f6e223e3c6665496d6160a08201527f676520726573756c743d2269636f6e2220786c696e6b3a687265663d2264617460c08201527f613a696d6167652f7376672b786d6c3b6261736536342c50484e325a7942336160e08201527f575230614430694d5459324c6a55354e794967614756705a326830505349784d6101008201527f6a67754f5451784969423261575633516d393450534977494441674e4451754d6101208201527f44633549444d304c6a45784e69496765473173626e4d39496d6830644841364c6101408201527f79393364336375647a4d7562334a6e4c7a49774d44417663335a6e496a3438636101608201527f4746306143426b50534a4e4d6a41754e7a6b7a4944457a4c6a4d794d5767744c6101808201527f6a59794d3159784d693433614330324c6a49794e5859754e6a4979614334324d6101a08201527f6a4a324c6a59794d3267744c6a59794d6e59754e6a4979614330754e6a497a646101c08201527f6930754e6a4979534445794c6a64324e6934794d6a566f4c6a59794d6e59754e6101e08201527f6a497a614334324d6a4e324c6a59794d6d67324c6a49794e5859744c6a59794d6102008201527f6d67754e6a497a646930754e6a497a614334324d6a4a324c5459754d6a4931616102208201527f4330754e6a4979656d30744d7934334d7a55674e5334324d444e324c5451754d6102408201527f7a5534614445754f445933646a51754d7a5534656d30784d7934324f5467744e6102608201527f6934794d6a566f4c5459754f445134646934324d6a4a6f4c6a59794d3359754e6102808201527f6a497a614330754e6a497a646934324d6a4a6f4c5334324d6a4a324c5334324d6102a08201527f6a4a6f4c5334324d6a4e324e6934794d6a566f4c6a59794d3359754e6a497a616102c08201527f4334324d6a4a324c6a59794d6d67324c6a67304f4859744c6a59794d6d67754e6102e08201527f6a4979646930784c6a49304e5767744c6a59794d6e59744c6a59794d3067794e6103008201527f7934774d6e59744e43347a4e54686f4d7934334d7a56324c5334324d6a4a6f4c6103208201527f6a59794d6e59744c6a59794d3267744c6a59794d6e6f6949484e306557786c506103408201527f534a6d615778734f694d324e6a59694c7a34384c334e325a7a343d222f3e3c2f6103608201527f66696c7465723e3c66696c7465722069643d226631223e3c6665496d616765206103808201527f726573756c743d2270302220786c696e6b3a687265663d22646174613a696d616103a08201527119d94bdcdd99cade1b5b0ed8985cd94d8d0b60721b6103c0820152825190611d99826103d29560208785019101614186565b01918201527f222f3e3c6665496d61676520726573756c743d2270322220786c696e6b3a68727f65663d22646174613a696d6167652f7376672b786d6c3b6261736536342c000091826103f2820152835190611dff826104109660208885019101614186565b0192830152610430820152815190611e218261044e9460208685019101614186565b0190631110179f60e11b908201527f3c6665496d61676520726573756c743d2270332220786c696e6b3a687265663d6104528201527f22646174613a696d6167652f7376672b786d6c3b6261736536342c0000000000610472820152825190611e948261048d9560208785019101614186565b01918201527f302220696e323d227031222f3e3c6665426c656e64206d6f64653d226578636c6104ad8201527f7573696f6e2220696e323d227032222f3e3c6665426c656e64206d6f64653d226104cd8201527f6f7665726c61792220696e323d2270332220726573756c743d22626c656e644f6104ed8201527f7574222f3e3c6665476175737369616e426c757220696e3d22626c656e644f7561050d8201527f742220737464446576696174696f6e3d223432222f3e3c2f66696c7465723e3c61052d8201527f636c6970506174682069643d22636f726e657273223e3c72656374207769647461054d8201527f683d2232393022206865696768743d22353030222072783d223432222072793d61056d8201527f223432222f3e3c2f636c6970506174683e3c706174682069643d22746578742d61058d8201527f706174682d612220643d224d34302031322048323530204132382032382030206105ad8201527f30203120323738203430205634363020413238203238203020302031203235306105cd8201527f20343838204834302041323820323820302030203120313220343630205634306105ed8201527f20413238203238203020302031203430203132207a222f3e3c7061746820696461060d8201527f3d226d696e696d61702220643d224d3233342034343443323334203435372e3961062d8201527f3439203234322e3231203436332032353320343633222f3e3c66696c7465722061064d8201527f69643d22746f702d726567696f6e2d626c7572223e3c6665476175737369616e61066d8201527f426c757220696e3d22536f75726365477261706869632220737464446576696161068d8201527f74696f6e3d223234222f3e3c2f66696c7465723e3c6c696e65617247726164696106ad8201527f656e742069643d22677261642d7570222078313d2231222078323d22302220796106cd8201527f313d2231222079323d2230223e3c73746f70206f66667365743d22302e3022206106ed8201527f73746f702d636f6c6f723d2223666666222073746f702d6f7061636974793d2261070d8201527f31222f3e3c73746f70206f66667365743d222e39222073746f702d636f6c6f7261072d8201527f3d2223666666222073746f702d6f7061636974793d2230222f3e3c2f6c696e6561074d8201527f61724772616469656e743e3c6c696e6561724772616469656e742069643d226761076d8201527f7261642d646f776e222078313d2230222078323d2231222079313d223022207961078d8201527f323d2231223e3c73746f70206f66667365743d22302e30222073746f702d636f6107ad8201527f6c6f723d2223666666222073746f702d6f7061636974793d2231222f3e3c73746107cd8201527f6f70206f66667365743d22302e39222073746f702d636f6c6f723d22236666666107ed8201527f222073746f702d6f7061636974793d2230222f3e3c2f6c696e6561724772616461080d8201527f69656e743e3c6d61736b2069643d22666164652d757022206d61736b436f6e7461082d8201527f656e74556e6974733d226f626a656374426f756e64696e67426f78223e3c726561084d8201527f63742077696474683d223122206865696768743d2231222066696c6c3d22757261086d8201527f6c2823677261642d757029222f3e3c2f6d61736b3e3c6d61736b2069643d226661088d8201527f6164652d646f776e22206d61736b436f6e74656e74556e6974733d226f626a656108ad8201527f6374426f756e64696e67426f78223e3c726563742077696474683d22312220686108cd8201527f65696768743d2231222066696c6c3d2275726c2823677261642d646f776e29226108ed8201527f2f3e3c2f6d61736b3e3c6d61736b2069643d226e6f6e6522206d61736b436f6e61090d8201527f74656e74556e6974733d226f626a656374426f756e64696e67426f78223e3c7261092d8201527f6563742077696474683d223122206865696768743d2231222066696c6c3d222361094d8201527f666666222f3e3c2f6d61736b3e3c6c696e6561724772616469656e742069643d61096d8201527f22677261642d73796d626f6c223e3c73746f70206f66667365743d22302e372261098d8201527f2073746f702d636f6c6f723d2223666666222073746f702d6f7061636974793d6109ad8201527f2231222f3e3c73746f70206f66667365743d222e3935222073746f702d636f6c6109cd8201527f6f723d2223666666222073746f702d6f7061636974793d2230222f3e3c2f6c696109ed8201527f6e6561724772616469656e743e3c6d61736b2069643d22666164652d73796d62610a0d8201527f6f6c22206d61736b436f6e74656e74556e6974733d227573657253706163654f610a2d8201527f6e557365223e3c726563742077696474683d2232393022206865696768743d22610a4d8201527f323030222066696c6c3d2275726c2823677261642d73796d626f6c29222f3e3c610a6d8201527f2f6d61736b3e3c2f646566733e3c6720636c69702d706174683d2275726c2823610a8d8201527531b7b93732b93994911f1e3932b1ba103334b6361e9160511b610aad82015282519061262082610ac39560208785019101614186565b01918201527f3d22353030222f3e3c72656374207374796c653d2266696c7465723a2075726c610ae38201527f28236631292220783d22302220793d2230222077696474683d22323930222068610b038201527f65696768743d22353030222f3e3c67207374796c653d2266696c7465723a7572610b238201527f6c2823746f702d726567696f6e2d626c7572293b207472616e73666f726d3a73610b438201527f63616c6528312e35293b207472616e73666f726d2d6f726967696e3a63656e74610b638201527f657220746f703b223e3c726563742066696c6c3d226e6f6e652220783d223022610b838201527f20793d2230222077696474683d2232393022206865696768743d22353030222f610ba38201527f3e3c656c6c697073652063783d22353025222063793d2230222072783d223138610bc38201527f30222072793d22313230222066696c6c3d222330303022206f7061636974793d610be38201527f22302e3835222f3e3c2f673e3c7265637420783d22302220793d223022207769610c038201527f6474683d2232393022206865696768743d22353030222072783d223432222072610c238201527f793d223432222066696c6c3d227267626128302c302c302c302922207374726f610c4382015288610c63917f6b653d2272676261283235352c3235352c3235352c302e3229222f3e3c2f673e838201520390810189520187614165565b825193612c71610453602086015196604087015190606088015198604051998a937f3c7465787420746578742d72656e646572696e673d226f7074696d697a65537060208601527f656564223e3c74657874506174682073746172744f66667365743d222d31303060408601527f25222066696c6c3d22236666662220666f6e742d66616d696c793d2227436f7560608601527f72696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d60808601527f22313070782220786c696e6b3a687265663d2223746578742d706174682d612260a0860152601f60f91b60c0860152825192602081019361292f8160c1890187614186565b860164010714051160dd1b928360c1830152845160208601926129568260c6830186614186565b01937f3c616e696d6174652061646469746976653d2273756d22206174747269627574938460c68701527f654e616d653d2273746172744f6666736574222066726f6d3d2230252220746f958660e68201527f3d22313030252220626567696e3d22307322206475723d2233307322207265709788610106830152867f656174436f756e743d22696e646566696e697465222f3e3c2f746578745061749a8b6101268501527f683e203c74657874506174682073746172744f66667365743d223025222066696101468501527f6c6c3d22236666662220666f6e742d66616d696c793d2227436f7572696572209283610166860152867f4e6577272c206d6f6e6f73706163652220666f6e742d73697a653d223130707895866101868201527f2220786c696e6b3a687265663d2223746578742d706174682d61223e0000000097886101a68301525190612ab1826101c29687840190614186565b01928301525190612ac9826101c79a8b840190614186565b0196870152876101e787015288610207870152896102278701527f683e3c74657874506174682073746172744f66667365743d22353025222066696102478701526102678601526102878501526102a78401528751928160208a01946102c392612b368285830189614186565b019182015282519885602085019a8b93612b57826102c89687840190614186565b0192830152866102e883015287610308830152886103288301527f683e3c74657874506174682073746172744f66667365743d222d3530252220666103488301527f696c6c3d22236666662220666f6e742d66616d696c793d2227436f75726965726103688301527f204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d223130706103888301527f782220786c696e6b3a687265663d2223746578742d706174682d61223e0000006103a88301525190612c20826103c59687840190614186565b01928301525190612c38826103ca9889840190614186565b01948501526103ea84015261040a83015261042a82015268341f1e17ba32bc3a1f60b91b61044a82015203610433810188520186614165565b612e96610164602086015163ffffffff60e0880151166a1e17ba32bc3a1f1e17b39f60a91b612cb4612cae63ffffffff6101008c01511693614a21565b92614a21565b916040519d8e947f3c67206d61736b3d2275726c2823666164652d73796d626f6c29223e3c72656360208701527f742066696c6c3d226e6f6e652220783d22302220793d2230222077696474683d60408701527f2232393022206865696768743d22323030222f3e3c7465787420793d2237302260608701527f20783d223332222066696c6c3d22236666662220666f6e742d66616d696c793d60808701527f2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d60a08701527f7765696768743d223230302220666f6e742d73697a653d2232387078223e000060c0870152612db381518092602060de8a019101614186565b85017f3c2f746578743e3c7465787420793d223131352220783d223332222066696c6c60de8201527f3d22236666662220666f6e742d66616d696c793d2227436f7572696572204e6560fe8201527f77272c206d6f6e6f73706163652220666f6e742d7765696768743d223230302261011e8201527f20666f6e742d73697a653d2232307078223e52616e6b2000000000000000000061013e820152825190612e66826101559560208785019101614186565b0191820152825190612e82826101599560208785019101614186565b01918201520361014481018b520189614165565b60e084015163ffffffff16600181036136b15750604051612eb68161414a565b601381527272676261283235352c3231352c302c312e302960681b6020820152945b612f84607d60405180987f3c7265637420783d2231362220793d223136222077696474683d22323538222060208301527f6865696768743d22343638222072783d223236222072793d223236222066696c60408301527f6c3d227267626128302c302c302c302922207374726f6b653d220000000000006060830152612f68815180926020607a86019101614186565b81016211179f60e91b607a82015203605d810189520187614165565b61301360616040518094731e339036b0b9b59e913ab9361411b737b7329491831b60208301527f207374796c653d227472616e73666f726d3a7472616e736c617465283330707860348301526816189998383c14911f60b91b6054830152612ff6815180926020605d86019101614186565b8101631e17b39f60e11b605d820152036041810185520183614165565b61302060c0860151614a21565b61303c61303660a0608089015198015197614a21565b96614a21565b908051906004820192838311610e4257885190600a8201808311610e4257815190600e820195868311610e4257600801809711610e42576007968088029088820403610e425761308d600e91614a21565b9401809111610e42578087029087820403610e42576130ad601291614a21565b9101809511610e425785858102048503610e42576130d261027a956133d19702614a21565b936040519b8c947f3c6720666f6e742d66616d696c793d2227436f7572696572204e6577272c206d60208701527f6f6e6f73706163652220666f6e742d73697a653d223132222066696c6c3d222360408701527f666666223e3c67207374796c653d227472616e73666f726d3a7472616e736c6160608701527f746528323970782c20333834707829223e3c726563742077696474683d2200006080870152613185815180926020609e8a019101614186565b8501927f22206865696768743d223236222072783d2238222072793d2238222066696c6c9283609e8601527f3d227267626128302c302c302c302e3629222f3e3c7465787420783d22313222948560be8201527f20793d223137223e3c747370616e2066696c6c3d2223393939223e49443a203c60de8201526617ba39b830b71f60c91b60fe820152815190613225826101059460208685019101614186565b01917f3c2f746578743e3c2f673e3c67207374796c653d227472616e73666f726d3a7480928401527f72616e736c61746528323970782c20343134707829223e3c726563742077696461012584015284633a341e9160e11b938461014582015282519061329c826101499560208785019101614186565b0191820152856101698201527f20793d223137223e3c747370616e2066696c6c3d2223393939223e47617320756101898201526c39b2b21d101e17ba39b830b71f60991b6101a98201528351906132fd826101b69660208885019101614186565b01928301527f72616e736c61746528323970782c20343434707829223e3c72656374207769646101d68301526101f6820152855190613346826101fa9860208a85019101614186565b019485015261021a8401527f20793d223137223e3c747370616e2066696c6c3d2223393939223e496d70726f61023a8401526f129e17ba32bc3a1f1e17b39f1e17b39f60811b61025a936f3b32b6b2b73a1d101e17ba39b830b71f60811b858201528251906133bf8261026a9560208785019101614186565b01918201520390810188520186614165565b604051958660a08101106001600160401b0360a0890111176103c05760266136529988607f986135529661179795610a879f60a06117979e01604052607685527f3c67207374796c653d227472616e73666f726d3a7472616e736c61746528313860208601527f3070782c20333635707829223e3c72656374207374796c653d2266696c74657260408601527f3a2075726c282369636f6e292220783d22302220793d2230222077696474683d606086015275111c1991103432b4b3b43a1e911b1a11179f1e17b39f60511b608086015260405198866134bb8b985180926020808c019101614186565b87016134d08251809360208085019101614186565b016134e48251809360208085019101614186565b016134f88251809360208085019101614186565b0161350c8251809360208085019101614186565b016135208251809360208085019101614186565b016135348251809360208085019101614186565b01651e17b9bb339f60d11b6020820152036006810184520182614165565b906040519586937f7b226e616d65223a224f7074696d697a6f7220436c75623a20000000000000006020860152613593815180926020603989019101614186565b8401701116113232b9b1b934b83a34b7b7111d1160791b60398201526135c3825180936020604a85019101614186565b016e11161130ba3a3934b13aba32b9911d60891b604a8201526135f0825180936020605985019101614186565b017f2c22696d616765223a22646174613a696d6167652f7376672b786d6c3b626173605982015263194d8d0b60e21b6079820152613638825180936020607d85019101614186565b0161227d60f01b607d82015203605f810184520182614165565b6136a5603d60405180937f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000060208301526136958151809260208686019101614186565b810103601d810184520182614165565b604051918291826141a9565b600281036136ee57506040516136c68161414a565b601581527472676261283235352c3235352c3235352c312e302960581b602082015294612ed8565b600303613728576040516137018161414a565b601481527372676261283230352c3132372c35302c312e302960601b602082015294612ed8565b6040516137348161414a565b601581527472676261283235352c3235352c3235352c302e322960581b602082015294612ed8565b61377a9194503d806000833e6137728183614165565b810190614752565b92876116af565b6040516310ca44ad60e11b8152600490fd5b906010600f821610156137d6576f181899199a1a9b1b9c1cb0b131b232b360811b600f82161a6137c7600019840186614a60565b5360041c9060001901806114f8565b634e487b7160e01b600052603260045260246000fd5b6138029195503d806000833e6137728183614165565b9386611476565b60038111613818575b50611441565b600f919250026028018060081b8160101b17179086613812565b61383a614b20565b95611137565b600a61384a614b20565b95611128565b613858614b20565b92611114565b61387391503d806000833e6137728183614165565b85611097565b61388f9193503d806000833e6137728183614165565b9183611056565b6138ab91503d806000833e6137728183614165565b82610eab565b3461021357602036600319011261021357600435600052600a6020526040806000205481519060018060a01b038116825260a01c6020820152f35b34610213576020806003193601126102135761390960043561496b565b906040519181839283018184528251809152816040850193019160005b82811061393557505050500390f35b83516001600160a01b031685528695509381019392810192600101613926565b346102135760803660031901126102135761396e6141d5565b6139766141eb565b604435606435916001600160401b03938484116102135736602385011215610213578360040135948511610213573660248686010111610213576139bb8383836142ae565b813b159384156139cf575b610d1185614428565b6020939450600086939260a4602493604051998a9788968793630a85bd0160e11b9c8d865233600487015260018060a01b038098168387015260448601526080606486015282608486015201848401378181018301859052601f01601f19168101030193165af18015610da357610d1192600091613a5d575b506001600160e01b03191614828080806139c6565b613a7e915060203d8111613a84575b613a768183614165565b810190614408565b83613a48565b503d613a6c565b34610213576000366003190112610213576009546040516001600160a01b039091168152602090f35b3461021357604036600319011261021357613acd6141d5565b6024358015158091036102135733600052600560205260406000209160018060a01b03169182600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b3461021357600036600319011261021357604051600090600180549081811c90808316928315613c22575b6020938484108114613c0c57838652908115613bec5750600114613b93575b610a87846136a581880382614165565b60008181529294507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b828410613bd95750505081610a87936136a59282010193613b83565b8054858501870152928501928101613bbd565b60ff1916858501525050151560051b82010191506136a581610a87613b83565b634e487b7160e01b600052602260045260246000fd5b91607f1691613b64565b346102135760203660031901126102135760043560005260066020526040806000205463ffffffff82519160018060a01b038116835260a01c166020820152f35b34610213576000366003190112610213576008546040516001600160a01b039091168152602090f35b34610213576020366003190112610213576001600160a01b03613cb76141d5565b168015613cd65760005260036020526020604060002054604051908152f35b60405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606490fd5b34610213576020366003190112610213576004356000908152600260205260409020546001600160a01b03168015613d4757602090604051908152f35b60405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606490fd5b3461021357613d8736614201565b9091613d948284836142ae565b823b15928315613da8575b610d1184614428565b604051630a85bd0160e11b8082523360048301526001600160a01b039384166024830152604482019490945260806064820152600060848201819052909450602092859260a49284929091165af18015610da357610d1192600091613e1c575b506001600160e01b03191614908280613d9f565b613e34915060203d8111613a8457613a768183614165565b83613e08565b3461021357610d11613e4b36614201565b916142ae565b34610213576020366003190112610213576004356001600160a01b0381811691829003610213577fd661c5a1b9e30d4cf3f1f304a69b11aee9f019da0cc8ca1e99595281a7ff9f7b91613eab602092600854163314614236565b600980546001600160a01b03191682179055604051908152a1005b3461021357604036600319011261021357613edf6141d5565b6024359081600052600260205260018060a01b038060406000205416908133148015613f59575b613f0f90614271565b8360005260046020526040600020921691826001600160601b0360a01b8254161790557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4005b50816000526005602052604060002033600052602052613f0f60ff604060002054169050613f06565b34610213576020366003190112610213576004356000526004602052602060018060a01b0360406000205416604051908152f35b3461021357600036600319011261021357604051600090600054600181811c90808316928315614068575b6020938484108114613c0c57838652908115613bec575060011461400f57610a87846136a581880382614165565b60008080529294507f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8284106140555750505081610a87936136a59282010193613b83565b8054858501870152928501928101614039565b91607f1691613fe1565b346102135760203660031901126102135760043563ffffffff60e01b8116809103610213576020906301ffc9a760e01b81149081156140cf575b81156140be575b506040519015158152f35b635b5e139f60e01b149050826140b3565b6380ac58cd60e01b811491506140ac565b3461021357602036600319011261021357606090600435600052600760205263ffffffff604060002060018060a01b036001818354169201549184528116602084015260a01c166040820152f35b6101c081019081106001600160401b038211176103c057604052565b604081019081106001600160401b038211176103c057604052565b90601f801991011681019081106001600160401b038211176103c057604052565b60005b8381106141995750506000910152565b8181015183820152602001614189565b604091602082526141c98151809281602086015260208686019101614186565b601f01601f1916010190565b600435906001600160a01b038216820361021357565b602435906001600160a01b038216820361021357565b6060906003190112610213576001600160a01b0390600435828116810361021357916024359081168103610213579060443590565b1561423d57565b60405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606490fd5b1561427857565b60405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606490fd5b6000838152600260209081526040808320546001600160a01b03959486169490861685036143d757851694851561439f579061431f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef949392863314908115614382575b811561436c575b50614271565b84835260038252808320600019815401905585835280832060018154019055868352600282526004818420926001600160601b0360a01b93888582541617905552822090815416905580a4565b9050888552600484528285205416331438614319565b8786526005855283862033875285528386205460ff169150614312565b815162461bcd60e51b81526004810184905260116024820152701253959053125117d49150d25412515395607a1b6044820152606490fd5b815162461bcd60e51b815260048101849052600a60248201526957524f4e475f46524f4d60b01b6044820152606490fd5b9081602091031261021357516001600160e01b0319811681036102135790565b1561442f57565b60405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606490fd5b6001600160401b0381116103c057601f01601f191660200190565b60006101a06040516144938161412e565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152015263ffffffff81161561470e578060201c60005260066020526040600020549060018060a01b038216156147375763ffffffff8260a01c1663ffffffff82161161470e57806000526007602052604060002063ffffffff8360a01c1663ffffffff19831617600052604060002063ffffffff831663ffffffff8560a01c160363ffffffff8111610e425763ffffffff60018183160111610e4257600090600163ffffffff861611614699575b60018381015460a088901c63ffffffff1663ffffffff1988161760009081526002602052604080822054965493880154898352918190205497549051996001600160a01b0391821699988216989297929482169391909216916145f28b61412e565b8460201c8b52600160a01b60019003811660208c01528160a01c63ffffffff1660408c015260a01c63ffffffff1660608b0152600160a01b600190031660808a015260a089015260c08801528360a01c63ffffffff1660e088015263ffffffff1661010087015263ffffffff1660010163ffffffff1661012086015263ffffffff16610140850152600160a01b60019003166101608401526101808301526101a082015290565b905083600019810111610e4257600019840160005260076020526040600020606463ffffffff600186015460a01c1602908163ffffffff811603610e42576001015460a01c63ffffffff169081156146f85763ffffffff160490614590565b634e487b7160e01b600052601260045260246000fd5b604051630583584d60e11b8152602082901c600482015263ffffffff9091166024820152604490fd5b60249060405190630679b58960e51b825260201c6004820152fd5b602081830312610213578051906001600160401b038211610213570181601f8201121561021357805161478481614467565b926147926040519485614165565b81845260208284010111610213576147b09160208085019101614186565b90565b805191821561491a57600380600285010460021b9360208501936147ef6147d986614467565b956147e76040519788614165565b808752614467565b602086019490601f190136863760405194606086018681106001600160401b038211176103c057604098979852604086527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208701527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040870152966000975b88858110156148d357908680600493019a860101516001603f9080828460121c168c010151918b60ff9384848488600c1c1684010151168585600894868a60061c160101511691831b01821b01901b93168b010151160160e01b815201614871565b509493925095945095500680600114614906576002146148f4575b50815290565b603d60f81b60001990910152386148ee565b50613d3d60f01b60011990910152386148ee565b915050604051602081018181106001600160401b038211176103c0576040526000815290565b6001600160401b0381116103c05760051b60200190565b80518210156137d65760209160051b010190565b90602091600081841c81526006845263ffffffff916040838184205460a01c169261499584614940565b916149a281519384614165565b848352601f196149b186614940565b01368985013782976001958695865b6149d0575b505050505050505050565b88871696828811614a1b5763ffffffff19821690971785526007835283852088015488978a918991906001600160a01b0316614a12600019830185168b614957565b520116966149c0565b506149c5565b9060405160a08101604052608081019260008452925b6000190192600a906030828206018553049283614a3757809350608091030191601f1901918252565b9081518110156137d6570160200190565b60405190606082018281106001600160401b038211176103c057604052602a82526020820160403682378251156137d6576030905381516001908110156137d657607860218401536029905b808211614acd5750506137815790565b9091600f81166010811015614b0b576f181899199a1a9b1b9c1cb0b131b232b360811b901a614afc8486614a60565b5360041c916000190190614abd565b60246000634e487b7160e01b81526032600452fd5b60405190614b2d8261414a565b60028252614e6f60f01b6020830152565b60405190614b4b8261414a565b600382526259657360e81b6020830152565b7f3c7376672077696474683d2732393027206865696768743d273530302720766981527f6577426f783d2730203020323930203530302720786d6c6e733d27687474703a60208201527f2f2f7777772e77332e6f72672f323030302f737667273e3c636972636c652063604082015262783d2760e81b606082015260630190565b60209392908491614c6993604051968793614bfd61187c838701614b5d565b0165272063793d2760d01b8152614c1d8251809387600685019101614186565b01702720723d27313230272066696c6c3d272360781b6006820152614c4b8251809386601785019101614186565b016813979f1e17b9bb339f60b91b6017820152038085520183614165565b56fea264697066735822122078b0a4de7ba025bfec1224c4217c0a9a7a4b31a9f4df00ce2805d3589340786564736f6c63430008110033d661c5a1b9e30d4cf3f1f304a69b11aee9f019da0cc8ca1e99595281a7ff9f7b0000000000000000000000005c71fcd090948dcc5e8a1a01ad8fa26313422022

Deployed Bytecode

0x608080604052600436101561001357600080fd5b60003560e01c908163016ef9fe146140e05750806301ffc9a71461407257806306fdde0314613fb6578063081812fc14613f82578063095ea7b314613ec65780631d29a86214613e5157806323b872dd14613e3a57806342842e0e14613d795780636352211e14613d0a57806370a0823114613c965780638da5cb5b14613c6d5780638f1d377614613c2c57806395d89b4114613b39578063a22cb46514613ab4578063a8d45bbc14613a8b578063b88d4fde14613955578063bf368399146138ec578063c5c9c0a2146138b1578063c87b56dd14610e58578063df0de0d114610a8b578063e8a3d4851461043e578063e985e9c5146103e8578063f14fcbc814610332578063f2fde38b146102c4578063f77c34b5146102185763fc314e311461013d57600080fd5b34610213576020366003190112610213576101c061015c600435614482565b604051908051825260018060a01b0380602083015116602084015263ffffffff8060408401511660408501528060608401511660608501528160808401511660808501528160a08401511660a08501528160c08401511660c08501528060e08401511660e085015261010081818501511690850152610120818185015116908501526101409081840151169084015261016081818401511690840152610180818184015116908401526101a0809201511690820152f35b600080fd5b34610213576040366003190112610213576004356024356001600160a01b03818116918290036102135761025181600854163314614236565b82600052600660205260406000209081549081166102ab576001600160a01b031916821790556040805192835260208301919091527fa74c71f615eb53caa07a622aaa53fd5204fe3f04f0b8ee7f2feeaba5ad38e09791a1005b60405163ad407e2160e01b815260048101859052602490fd5b34610213576020366003190112610213576102dd6141d5565b600854906001600160a01b03906102f73383851614614236565b1680916001600160601b0360a01b1617600855337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b34610213576020366003190112610213576004356000818152600a60205260409020546001600160a01b03919082166103d65760405191604083018381106001600160401b038211176103c05760405233835260208301916001600160601b0343168352600052600a6020526040600020925116906001600160601b0360a01b905160a01b16179055600080f35b634e487b7160e01b600052604160045260246000fd5b604051630499821d60e21b8152600490fd5b34610213576040366003190112610213576104016141d5565b6104096141eb565b9060018060a01b03809116600052600560205260406000209116600052602052602060ff604060002054166040519015158152f35b34610213576000366003190112610213576040516105208101908082106001600160401b038311176103c057610a87916040526104f181527f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c65794a60208201527f755957316c496a6f695433423061573170656d397949454e73645749694c434a60408201527f6b5a584e6a636d6c7764476c7662694936496c526f5a5342506348527062576c60608201527f3662334967513278315969424f526c5167593239736247566a64476c7662694260808201527f795a586468636d527a494764686379426c5a6d5a7059326c6c626e516763475660a08201527f766347786c494746755a43427459574e6f6157356c637942696553427461573560c08201527f306157356e4947356c647942706447567463794233614756755a585a6c63694260e08201527f6849474e6f5a5746775a58496763323973645852706232346761584d676333566101008201527f6962576c306447566b49475a766369426849474e6c636e5268615734675932686101208201527f686247786c626d646c4c694973496d6c745957646c496a6f695a4746305954706101408201527f706257466e5a53397a646d6372654731734f324a68633255324e4378515345346101608201527f79576e6c434d324658556a4268524442705456525a4d6b78715654564f65556c6101808201527f6e5955645763466f796144425155306c345457706e645539555558684a6155496101a08201527f79595664574d3146744f54525155306c33535552425a3035455558564e52474d6101c08201527f315355524e4d4578715258684f61556c6e5a55637863324a7554546c4a6257676101e08201527f775a4568424e6b78354f544e6b4d324e315a48704e6457497a536d354d656b6c6102008201527f3354555242646d4d7a576d354a616a5134593064474d474644516d74515530706102208201527f4f54577042645535366133704a524556365447704e655531585a33524d616c6c6102408201527f355454465a654531704e444e68517a41795447704a655535595758564f616b6c6102608201527f3559554d304d6b3171536a4a4d616c6c3554544a6e6445787157586c4e626c6c6102808201527f31546d704a655746444d48564f616b6c365a476b776455357153586c545245566102a08201527f355447706b4d6b35704e486c4e616c5a765447705a655531755758564f616b6c6102c08201527f3659554d304d6b3171546a4a4d616c6c355457316e4d6b787153586c4f57466c6102e08201527f305447705a655531745a33564f616b6c365a476b776455357153587068517a516103008201527f795457704b4d6b78555758564e616b6b7859554d776455357153586c6c6254426103208201527f3054586b304d3031365657644f557a51795455524f4d6b78555558564e656c556103408201527f30595552466455394557544e6b616c4631545870564e4756744d48684e6554516103608201527f795431526e644535704e486c4e616c5a765446525a645539455554526b6154516103808201527f795457704b6230787157586c4e4d316c31546d704a656d46444d48564f616b6c6103a08201527f365a476b304d6b3171536d394d557a51795457704b4d6b78544e444a4e616b706103c08201527f7654464d304d6b3171546a4a4f61545235545770576230787157586c4e4d316c6103e08201527f31546d704a656d46444e444a4e616b6f795447705a655531745a7a4a4d616d636104008201527f775430685a6445787157586c4e62576431546d704a655752704d48684d616b6b6104208201527f77546c646e6445787157586c4e626c6c305447705a655530775a336c4f6554526104408201527f335457355a644535444e48704f5647687654586b304d303136566a4a4d557a516104608201527f795457704b6230787157586c4e626c6c305447705a655530795a33524d616c6c6104808201527f355457357661556c49546a426c5633687355464e4b6257465865484e506155306104a08201527f79546d705a615578364e44684d4d303479576e6f3050534973496d56346447566104c08201527f79626d467358327870626d73694f694a6f64485277637a6f764c32397764476c6104e08201527074615870766369356a624856694c794a3960781b610500820152604051918291826141a9565b0390f35b3461021357608036600319011261021357600435610aa76141eb565b906001600160a01b036044358181169290839003610213578060005260209360068552604060002092813f916040519287840190338252604085015260643560608501526060845260808401906001600160401b0394808310868411176103c057826040525190209081600052600a895260406000205460a01c60408101809111610e4257431115610e335750600052600a8752816040600020541615610e2157845494828616948515610e09578715610df7578389816009541694602460405180948193631846d2f560e31b835216978860048301525afa908115610da357600091610dc1575b5015610daf578860449660405197888092630381fd1960e41b82528760048301524460248301525afa958615610da357600096610d67575b5063ffffffff809760a01c1690891b9181831760005260078a528760016040600020015460a01c168015159081610d5a575b50610d4857805463ffffffff60a01b1916600192909201881660a01b63ffffffff60a01b1691909117815586905460a01c16179687600052600281528260406000205416610d1357866000526003815260406000206001815401905587600052600281526040600020936001600160601b0360a01b94888682541617905560405191898960007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8180a460608301918211838310176103c057610d11996001946007936040528452818401998a5288604085019816885260005252826040600020915116848254161781550194511690845416178355511681549063ffffffff60a01b9060a01b169063ffffffff60a01b1916179055565b005b6064906040519062461bcd60e51b82526004820152600e60248201526d1053149150511657d3525395115160921b6044820152fd5b60405163d8d359ef60e01b8152600490fd5b905088881610158b610bf9565b9095508881813d8311610d9c575b610d7f8183614165565b81010312610213575163ffffffff81168103610213579489610bc7565b503d610d75565b6040513d6000823e3d90fd5b6040516324acf8b560e11b8152600490fd5b90508981813d8311610df0575b610dd88183614165565b8101031261021357518015158103610213578a610b8f565b503d610dce565b604051634e46966960e11b8152600490fd5b60249060405190630679b58960e51b82526004820152fd5b60405163229405c560e11b8152600490fd5b63efc54ea560e01b8152600490fd5b634e487b7160e01b600052601160045260246000fd5b3461021357602036600319011261021357610e74600435614482565b6020810151604051633942720b60e11b815290600090829060049082906001600160a01b03165afa908115610da357600091613896575b50610eb760043561496b565b91604051602081018181106001600160401b038211176103c05760405260008152908351906000925b8551841015610f8c57600190610f7e610ef885614a21565b610f12848060a01b03610f0b898c614957565b5116614a71565b90604051938491612e3760f11b602084015261017160f51b8151610f3f8160229460208689019101614186565b840191820152835190610f5b8260249660208885019101614186565b01610f6f8251809360208785019101614186565b01036004810184520182614165565b926000190193019291610ee0565b90611013611021602487600495604051610fde602e8260208101946d2632b0b232b93137b0b9321d2e3760911b8652610fce8151809260208686019101614186565b810103600e810184520182614165565b6040519583610ff7889551809260208089019101614186565b840191632e372e3760e11b602084015251809386840190614186565b010385810184520182614165565b60208201516040516306fdde0360e01b81529360009185919082906001600160a01b03165afa928315610da357600093613879575b5063ffffffff61012083015116926004600060018060a01b03602086015116604051928380926306fdde0360e01b82525afa908115610da35760009161385e575b506110ab63ffffffff60e086015116614a21565b6101a08501519091906110c7906001600160a01b03163b614a21565b956110dc63ffffffff61014088015116614a21565b6101608701519097906110f7906001600160a01b0316614a71565b9061110183614a21565b906001840361385057611112614b3e565b925b6003851161384057600a611126614b3e565b955b1161383257611135614b3e565b955b6040519b8c9860208a017f5b7b2274726169745f74797065223a224368616c6c656e6765222c2276616c7590526332911d1160e11b928360408c01528051908160448d01916020019161118992614186565b7f227d2c7b2274726169745f74797065223a224761732075736564222c2276616c6044918c0191820152633ab2911d60e11b60648201528151916111d69083906068840190602001614186565b01937f2c22646973706c61795f74797065223a226e756d626572227d2c7b227472616994856068820152608881017f745f74797065223a22436f64652073697a65222c2276616c7565223a0000000090528151918260a48301916020019161123d92614186565b018460a482015260c481017f745f74797065223a22496d70726f76656d656e742070657263656e746167652290526916113b30b63ab2911d1160b11b60e48201528151918260ee8301916020019161129492614186565b019060ee82017f25227d2c7b2274726169745f74797065223a22536f6c766572222c2276616c75905261010e820152815190610112928284830191602001916112dc92614186565b019081017f227d2c7b2274726169745f74797065223a2252616e6b222c2276616c7565223a90528251906101329382858301916020019161131c92614186565b019182015261015281017f745f74797065223a224c6561646572222c2276616c7565223a22000000000000905281519061016c9282848301916020019161136292614186565b019081017f227d2c7b2274726169745f74797065223a22546f702033222c2276616c7565229052611d1160f11b61018c82015281519061018e928284830191602001916113ae92614186565b019081017f227d2c7b2274726169745f74797065223a22546f70203130222c2276616c7565905262111d1160e91b6101ae8201528151906101b1928284830191602001916113fb92614186565b019062227d5d60e81b9082015203610194810185526101b40161141e9085614165565b61012083015160049360009163ffffffff16600a811115613809575062bebebe91505b60208101516040516306fdde0360e01b81529560009187919082906001600160a01b03165afa948515610da3576000956137ec575b5061018081015161148f906001600160a01b0316614a71565b60208201519091906114a9906001600160a01b0316614a71565b9563ffffffff60e0830151169363ffffffff610140840151169063ffffffff6101208501511663ffffffff6060860151169190604051916114e98361414a565b60068352602036818501378251805b61379357506137815760208601519361016087015190604051998a6102008101106001600160401b036102008d0111176103c05761010260ff60249f81998e839960009f9b859a60649f9987996101809f97899860109d61020089016040526115646102008a0161414a565b600e6102008a01526d27b83a34b6b4bd37b91021b63ab160911b6102208a015261020089018952602089015260408801526060870152608086015260a085015260043560c085015260e084015261010083015261012082015286838681806004358188871c160206160204016101408201528c838c81808c81600435918e1c160206160204016101608201528683868180600435818860201c160206160204018b8201526101a08d848d81808d816004359160201c16020616020401910152816004359160301c160206160204016101c08a0152816004359160301c160206160204016101e0840152602060018060a01b0391015116604051958680926344b285db60e01b825260043560048301525afa918215610da3576301037b3160e51b957f222f3e3c6665496d61676520726573756c743d2270312220786c696e6b3a68729560009461375c575b50612830610c8361179c61012086015161179760a660405180937f3c7376672077696474683d2732393027206865696768743d273530302720766960208301527f6577426f783d2730203020323930203530302720786d6c6e733d27687474703a60408301527f2f2f7777772e77332e6f72672f323030302f737667273e3c726563742077696460608301527f74683d2732393027206865696768743d27353030272066696c6c3d27230000006080830152611775815180926020609d86019101614186565b81016813979f1e17b9bb339f60b91b609d820152036086810184520182614165565b6147b3565b7f2220783d22302220793d2230222077696474683d2232393022206865696768746117eb6117976117d16101408a0151614a21565b6117df6101608b0151614a21565b6101208b015191614bde565b7f222f3e3c6665426c656e64206d6f64653d226f7665726c61792220696e3d227061183a6117976118206101808c0151614a21565b61182e6101a08d0151614a21565b6101208d015191614bde565b6118f56020611797818d6118526101c0820151614a21565b906101206118646101e0830151614a21565b9101519060405195869361188961187c838701614b5d565b9182815194859201614186565b0165272063793d2760d01b81526118a98251809387600685019101614186565b01702720723d27313030272066696c6c3d272360781b60068201526118d78251809386601785019101614186565b016813979f1e17b9bb339f60b91b6017820152038084520182614165565b926101208b0151956040519e8f7f3c7376672077696474683d2232393022206865696768743d223530302220766960208201527f6577426f783d2230203020323930203530302220786d6c6e733d22687474703a60408201527f2f2f7777772e77332e6f72672f323030302f7376672220786d6c6e733a786c6960608201527f6e6b3d22687474703a2f2f7777772e77332e6f72672f313939392f786c696e6b60808201527f223e3c646566733e3c66696c7465722069643d2269636f6e223e3c6665496d6160a08201527f676520726573756c743d2269636f6e2220786c696e6b3a687265663d2264617460c08201527f613a696d6167652f7376672b786d6c3b6261736536342c50484e325a7942336160e08201527f575230614430694d5459324c6a55354e794967614756705a326830505349784d6101008201527f6a67754f5451784969423261575633516d393450534977494441674e4451754d6101208201527f44633549444d304c6a45784e69496765473173626e4d39496d6830644841364c6101408201527f79393364336375647a4d7562334a6e4c7a49774d44417663335a6e496a3438636101608201527f4746306143426b50534a4e4d6a41754e7a6b7a4944457a4c6a4d794d5767744c6101808201527f6a59794d3159784d693433614330324c6a49794e5859754e6a4979614334324d6101a08201527f6a4a324c6a59794d3267744c6a59794d6e59754e6a4979614330754e6a497a646101c08201527f6930754e6a4979534445794c6a64324e6934794d6a566f4c6a59794d6e59754e6101e08201527f6a497a614334324d6a4e324c6a59794d6d67324c6a49794e5859744c6a59794d6102008201527f6d67754e6a497a646930754e6a497a614334324d6a4a324c5459754d6a4931616102208201527f4330754e6a4979656d30744d7934334d7a55674e5334324d444e324c5451754d6102408201527f7a5534614445754f445933646a51754d7a5534656d30784d7934324f5467744e6102608201527f6934794d6a566f4c5459754f445134646934324d6a4a6f4c6a59794d3359754e6102808201527f6a497a614330754e6a497a646934324d6a4a6f4c5334324d6a4a324c5334324d6102a08201527f6a4a6f4c5334324d6a4e324e6934794d6a566f4c6a59794d3359754e6a497a616102c08201527f4334324d6a4a324c6a59794d6d67324c6a67304f4859744c6a59794d6d67754e6102e08201527f6a4979646930784c6a49304e5767744c6a59794d6e59744c6a59794d3067794e6103008201527f7934774d6e59744e43347a4e54686f4d7934334d7a56324c5334324d6a4a6f4c6103208201527f6a59794d6e59744c6a59794d3267744c6a59794d6e6f6949484e306557786c506103408201527f534a6d615778734f694d324e6a59694c7a34384c334e325a7a343d222f3e3c2f6103608201527f66696c7465723e3c66696c7465722069643d226631223e3c6665496d616765206103808201527f726573756c743d2270302220786c696e6b3a687265663d22646174613a696d616103a08201527119d94bdcdd99cade1b5b0ed8985cd94d8d0b60721b6103c0820152825190611d99826103d29560208785019101614186565b01918201527f222f3e3c6665496d61676520726573756c743d2270322220786c696e6b3a68727f65663d22646174613a696d6167652f7376672b786d6c3b6261736536342c000091826103f2820152835190611dff826104109660208885019101614186565b0192830152610430820152815190611e218261044e9460208685019101614186565b0190631110179f60e11b908201527f3c6665496d61676520726573756c743d2270332220786c696e6b3a687265663d6104528201527f22646174613a696d6167652f7376672b786d6c3b6261736536342c0000000000610472820152825190611e948261048d9560208785019101614186565b01918201527f302220696e323d227031222f3e3c6665426c656e64206d6f64653d226578636c6104ad8201527f7573696f6e2220696e323d227032222f3e3c6665426c656e64206d6f64653d226104cd8201527f6f7665726c61792220696e323d2270332220726573756c743d22626c656e644f6104ed8201527f7574222f3e3c6665476175737369616e426c757220696e3d22626c656e644f7561050d8201527f742220737464446576696174696f6e3d223432222f3e3c2f66696c7465723e3c61052d8201527f636c6970506174682069643d22636f726e657273223e3c72656374207769647461054d8201527f683d2232393022206865696768743d22353030222072783d223432222072793d61056d8201527f223432222f3e3c2f636c6970506174683e3c706174682069643d22746578742d61058d8201527f706174682d612220643d224d34302031322048323530204132382032382030206105ad8201527f30203120323738203430205634363020413238203238203020302031203235306105cd8201527f20343838204834302041323820323820302030203120313220343630205634306105ed8201527f20413238203238203020302031203430203132207a222f3e3c7061746820696461060d8201527f3d226d696e696d61702220643d224d3233342034343443323334203435372e3961062d8201527f3439203234322e3231203436332032353320343633222f3e3c66696c7465722061064d8201527f69643d22746f702d726567696f6e2d626c7572223e3c6665476175737369616e61066d8201527f426c757220696e3d22536f75726365477261706869632220737464446576696161068d8201527f74696f6e3d223234222f3e3c2f66696c7465723e3c6c696e65617247726164696106ad8201527f656e742069643d22677261642d7570222078313d2231222078323d22302220796106cd8201527f313d2231222079323d2230223e3c73746f70206f66667365743d22302e3022206106ed8201527f73746f702d636f6c6f723d2223666666222073746f702d6f7061636974793d2261070d8201527f31222f3e3c73746f70206f66667365743d222e39222073746f702d636f6c6f7261072d8201527f3d2223666666222073746f702d6f7061636974793d2230222f3e3c2f6c696e6561074d8201527f61724772616469656e743e3c6c696e6561724772616469656e742069643d226761076d8201527f7261642d646f776e222078313d2230222078323d2231222079313d223022207961078d8201527f323d2231223e3c73746f70206f66667365743d22302e30222073746f702d636f6107ad8201527f6c6f723d2223666666222073746f702d6f7061636974793d2231222f3e3c73746107cd8201527f6f70206f66667365743d22302e39222073746f702d636f6c6f723d22236666666107ed8201527f222073746f702d6f7061636974793d2230222f3e3c2f6c696e6561724772616461080d8201527f69656e743e3c6d61736b2069643d22666164652d757022206d61736b436f6e7461082d8201527f656e74556e6974733d226f626a656374426f756e64696e67426f78223e3c726561084d8201527f63742077696474683d223122206865696768743d2231222066696c6c3d22757261086d8201527f6c2823677261642d757029222f3e3c2f6d61736b3e3c6d61736b2069643d226661088d8201527f6164652d646f776e22206d61736b436f6e74656e74556e6974733d226f626a656108ad8201527f6374426f756e64696e67426f78223e3c726563742077696474683d22312220686108cd8201527f65696768743d2231222066696c6c3d2275726c2823677261642d646f776e29226108ed8201527f2f3e3c2f6d61736b3e3c6d61736b2069643d226e6f6e6522206d61736b436f6e61090d8201527f74656e74556e6974733d226f626a656374426f756e64696e67426f78223e3c7261092d8201527f6563742077696474683d223122206865696768743d2231222066696c6c3d222361094d8201527f666666222f3e3c2f6d61736b3e3c6c696e6561724772616469656e742069643d61096d8201527f22677261642d73796d626f6c223e3c73746f70206f66667365743d22302e372261098d8201527f2073746f702d636f6c6f723d2223666666222073746f702d6f7061636974793d6109ad8201527f2231222f3e3c73746f70206f66667365743d222e3935222073746f702d636f6c6109cd8201527f6f723d2223666666222073746f702d6f7061636974793d2230222f3e3c2f6c696109ed8201527f6e6561724772616469656e743e3c6d61736b2069643d22666164652d73796d62610a0d8201527f6f6c22206d61736b436f6e74656e74556e6974733d227573657253706163654f610a2d8201527f6e557365223e3c726563742077696474683d2232393022206865696768743d22610a4d8201527f323030222066696c6c3d2275726c2823677261642d73796d626f6c29222f3e3c610a6d8201527f2f6d61736b3e3c2f646566733e3c6720636c69702d706174683d2275726c2823610a8d8201527531b7b93732b93994911f1e3932b1ba103334b6361e9160511b610aad82015282519061262082610ac39560208785019101614186565b01918201527f3d22353030222f3e3c72656374207374796c653d2266696c7465723a2075726c610ae38201527f28236631292220783d22302220793d2230222077696474683d22323930222068610b038201527f65696768743d22353030222f3e3c67207374796c653d2266696c7465723a7572610b238201527f6c2823746f702d726567696f6e2d626c7572293b207472616e73666f726d3a73610b438201527f63616c6528312e35293b207472616e73666f726d2d6f726967696e3a63656e74610b638201527f657220746f703b223e3c726563742066696c6c3d226e6f6e652220783d223022610b838201527f20793d2230222077696474683d2232393022206865696768743d22353030222f610ba38201527f3e3c656c6c697073652063783d22353025222063793d2230222072783d223138610bc38201527f30222072793d22313230222066696c6c3d222330303022206f7061636974793d610be38201527f22302e3835222f3e3c2f673e3c7265637420783d22302220793d223022207769610c038201527f6474683d2232393022206865696768743d22353030222072783d223432222072610c238201527f793d223432222066696c6c3d227267626128302c302c302c302922207374726f610c4382015288610c63917f6b653d2272676261283235352c3235352c3235352c302e3229222f3e3c2f673e838201520390810189520187614165565b825193612c71610453602086015196604087015190606088015198604051998a937f3c7465787420746578742d72656e646572696e673d226f7074696d697a65537060208601527f656564223e3c74657874506174682073746172744f66667365743d222d31303060408601527f25222066696c6c3d22236666662220666f6e742d66616d696c793d2227436f7560608601527f72696572204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d60808601527f22313070782220786c696e6b3a687265663d2223746578742d706174682d612260a0860152601f60f91b60c0860152825192602081019361292f8160c1890187614186565b860164010714051160dd1b928360c1830152845160208601926129568260c6830186614186565b01937f3c616e696d6174652061646469746976653d2273756d22206174747269627574938460c68701527f654e616d653d2273746172744f6666736574222066726f6d3d2230252220746f958660e68201527f3d22313030252220626567696e3d22307322206475723d2233307322207265709788610106830152867f656174436f756e743d22696e646566696e697465222f3e3c2f746578745061749a8b6101268501527f683e203c74657874506174682073746172744f66667365743d223025222066696101468501527f6c6c3d22236666662220666f6e742d66616d696c793d2227436f7572696572209283610166860152867f4e6577272c206d6f6e6f73706163652220666f6e742d73697a653d223130707895866101868201527f2220786c696e6b3a687265663d2223746578742d706174682d61223e0000000097886101a68301525190612ab1826101c29687840190614186565b01928301525190612ac9826101c79a8b840190614186565b0196870152876101e787015288610207870152896102278701527f683e3c74657874506174682073746172744f66667365743d22353025222066696102478701526102678601526102878501526102a78401528751928160208a01946102c392612b368285830189614186565b019182015282519885602085019a8b93612b57826102c89687840190614186565b0192830152866102e883015287610308830152886103288301527f683e3c74657874506174682073746172744f66667365743d222d3530252220666103488301527f696c6c3d22236666662220666f6e742d66616d696c793d2227436f75726965726103688301527f204e6577272c206d6f6e6f73706163652220666f6e742d73697a653d223130706103888301527f782220786c696e6b3a687265663d2223746578742d706174682d61223e0000006103a88301525190612c20826103c59687840190614186565b01928301525190612c38826103ca9889840190614186565b01948501526103ea84015261040a83015261042a82015268341f1e17ba32bc3a1f60b91b61044a82015203610433810188520186614165565b612e96610164602086015163ffffffff60e0880151166a1e17ba32bc3a1f1e17b39f60a91b612cb4612cae63ffffffff6101008c01511693614a21565b92614a21565b916040519d8e947f3c67206d61736b3d2275726c2823666164652d73796d626f6c29223e3c72656360208701527f742066696c6c3d226e6f6e652220783d22302220793d2230222077696474683d60408701527f2232393022206865696768743d22323030222f3e3c7465787420793d2237302260608701527f20783d223332222066696c6c3d22236666662220666f6e742d66616d696c793d60808701527f2227436f7572696572204e6577272c206d6f6e6f73706163652220666f6e742d60a08701527f7765696768743d223230302220666f6e742d73697a653d2232387078223e000060c0870152612db381518092602060de8a019101614186565b85017f3c2f746578743e3c7465787420793d223131352220783d223332222066696c6c60de8201527f3d22236666662220666f6e742d66616d696c793d2227436f7572696572204e6560fe8201527f77272c206d6f6e6f73706163652220666f6e742d7765696768743d223230302261011e8201527f20666f6e742d73697a653d2232307078223e52616e6b2000000000000000000061013e820152825190612e66826101559560208785019101614186565b0191820152825190612e82826101599560208785019101614186565b01918201520361014481018b520189614165565b60e084015163ffffffff16600181036136b15750604051612eb68161414a565b601381527272676261283235352c3231352c302c312e302960681b6020820152945b612f84607d60405180987f3c7265637420783d2231362220793d223136222077696474683d22323538222060208301527f6865696768743d22343638222072783d223236222072793d223236222066696c60408301527f6c3d227267626128302c302c302c302922207374726f6b653d220000000000006060830152612f68815180926020607a86019101614186565b81016211179f60e91b607a82015203605d810189520187614165565b61301360616040518094731e339036b0b9b59e913ab9361411b737b7329491831b60208301527f207374796c653d227472616e73666f726d3a7472616e736c617465283330707860348301526816189998383c14911f60b91b6054830152612ff6815180926020605d86019101614186565b8101631e17b39f60e11b605d820152036041810185520183614165565b61302060c0860151614a21565b61303c61303660a0608089015198015197614a21565b96614a21565b908051906004820192838311610e4257885190600a8201808311610e4257815190600e820195868311610e4257600801809711610e42576007968088029088820403610e425761308d600e91614a21565b9401809111610e42578087029087820403610e42576130ad601291614a21565b9101809511610e425785858102048503610e42576130d261027a956133d19702614a21565b936040519b8c947f3c6720666f6e742d66616d696c793d2227436f7572696572204e6577272c206d60208701527f6f6e6f73706163652220666f6e742d73697a653d223132222066696c6c3d222360408701527f666666223e3c67207374796c653d227472616e73666f726d3a7472616e736c6160608701527f746528323970782c20333834707829223e3c726563742077696474683d2200006080870152613185815180926020609e8a019101614186565b8501927f22206865696768743d223236222072783d2238222072793d2238222066696c6c9283609e8601527f3d227267626128302c302c302c302e3629222f3e3c7465787420783d22313222948560be8201527f20793d223137223e3c747370616e2066696c6c3d2223393939223e49443a203c60de8201526617ba39b830b71f60c91b60fe820152815190613225826101059460208685019101614186565b01917f3c2f746578743e3c2f673e3c67207374796c653d227472616e73666f726d3a7480928401527f72616e736c61746528323970782c20343134707829223e3c726563742077696461012584015284633a341e9160e11b938461014582015282519061329c826101499560208785019101614186565b0191820152856101698201527f20793d223137223e3c747370616e2066696c6c3d2223393939223e47617320756101898201526c39b2b21d101e17ba39b830b71f60991b6101a98201528351906132fd826101b69660208885019101614186565b01928301527f72616e736c61746528323970782c20343434707829223e3c72656374207769646101d68301526101f6820152855190613346826101fa9860208a85019101614186565b019485015261021a8401527f20793d223137223e3c747370616e2066696c6c3d2223393939223e496d70726f61023a8401526f129e17ba32bc3a1f1e17b39f1e17b39f60811b61025a936f3b32b6b2b73a1d101e17ba39b830b71f60811b858201528251906133bf8261026a9560208785019101614186565b01918201520390810188520186614165565b604051958660a08101106001600160401b0360a0890111176103c05760266136529988607f986135529661179795610a879f60a06117979e01604052607685527f3c67207374796c653d227472616e73666f726d3a7472616e736c61746528313860208601527f3070782c20333635707829223e3c72656374207374796c653d2266696c74657260408601527f3a2075726c282369636f6e292220783d22302220793d2230222077696474683d606086015275111c1991103432b4b3b43a1e911b1a11179f1e17b39f60511b608086015260405198866134bb8b985180926020808c019101614186565b87016134d08251809360208085019101614186565b016134e48251809360208085019101614186565b016134f88251809360208085019101614186565b0161350c8251809360208085019101614186565b016135208251809360208085019101614186565b016135348251809360208085019101614186565b01651e17b9bb339f60d11b6020820152036006810184520182614165565b906040519586937f7b226e616d65223a224f7074696d697a6f7220436c75623a20000000000000006020860152613593815180926020603989019101614186565b8401701116113232b9b1b934b83a34b7b7111d1160791b60398201526135c3825180936020604a85019101614186565b016e11161130ba3a3934b13aba32b9911d60891b604a8201526135f0825180936020605985019101614186565b017f2c22696d616765223a22646174613a696d6167652f7376672b786d6c3b626173605982015263194d8d0b60e21b6079820152613638825180936020607d85019101614186565b0161227d60f01b607d82015203605f810184520182614165565b6136a5603d60405180937f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000060208301526136958151809260208686019101614186565b810103601d810184520182614165565b604051918291826141a9565b600281036136ee57506040516136c68161414a565b601581527472676261283235352c3235352c3235352c312e302960581b602082015294612ed8565b600303613728576040516137018161414a565b601481527372676261283230352c3132372c35302c312e302960601b602082015294612ed8565b6040516137348161414a565b601581527472676261283235352c3235352c3235352c302e322960581b602082015294612ed8565b61377a9194503d806000833e6137728183614165565b810190614752565b92876116af565b6040516310ca44ad60e11b8152600490fd5b906010600f821610156137d6576f181899199a1a9b1b9c1cb0b131b232b360811b600f82161a6137c7600019840186614a60565b5360041c9060001901806114f8565b634e487b7160e01b600052603260045260246000fd5b6138029195503d806000833e6137728183614165565b9386611476565b60038111613818575b50611441565b600f919250026028018060081b8160101b17179086613812565b61383a614b20565b95611137565b600a61384a614b20565b95611128565b613858614b20565b92611114565b61387391503d806000833e6137728183614165565b85611097565b61388f9193503d806000833e6137728183614165565b9183611056565b6138ab91503d806000833e6137728183614165565b82610eab565b3461021357602036600319011261021357600435600052600a6020526040806000205481519060018060a01b038116825260a01c6020820152f35b34610213576020806003193601126102135761390960043561496b565b906040519181839283018184528251809152816040850193019160005b82811061393557505050500390f35b83516001600160a01b031685528695509381019392810192600101613926565b346102135760803660031901126102135761396e6141d5565b6139766141eb565b604435606435916001600160401b03938484116102135736602385011215610213578360040135948511610213573660248686010111610213576139bb8383836142ae565b813b159384156139cf575b610d1185614428565b6020939450600086939260a4602493604051998a9788968793630a85bd0160e11b9c8d865233600487015260018060a01b038098168387015260448601526080606486015282608486015201848401378181018301859052601f01601f19168101030193165af18015610da357610d1192600091613a5d575b506001600160e01b03191614828080806139c6565b613a7e915060203d8111613a84575b613a768183614165565b810190614408565b83613a48565b503d613a6c565b34610213576000366003190112610213576009546040516001600160a01b039091168152602090f35b3461021357604036600319011261021357613acd6141d5565b6024358015158091036102135733600052600560205260406000209160018060a01b03169182600052602052604060002060ff1981541660ff83161790556040519081527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b3461021357600036600319011261021357604051600090600180549081811c90808316928315613c22575b6020938484108114613c0c57838652908115613bec5750600114613b93575b610a87846136a581880382614165565b60008181529294507fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b828410613bd95750505081610a87936136a59282010193613b83565b8054858501870152928501928101613bbd565b60ff1916858501525050151560051b82010191506136a581610a87613b83565b634e487b7160e01b600052602260045260246000fd5b91607f1691613b64565b346102135760203660031901126102135760043560005260066020526040806000205463ffffffff82519160018060a01b038116835260a01c166020820152f35b34610213576000366003190112610213576008546040516001600160a01b039091168152602090f35b34610213576020366003190112610213576001600160a01b03613cb76141d5565b168015613cd65760005260036020526020604060002054604051908152f35b60405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606490fd5b34610213576020366003190112610213576004356000908152600260205260409020546001600160a01b03168015613d4757602090604051908152f35b60405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606490fd5b3461021357613d8736614201565b9091613d948284836142ae565b823b15928315613da8575b610d1184614428565b604051630a85bd0160e11b8082523360048301526001600160a01b039384166024830152604482019490945260806064820152600060848201819052909450602092859260a49284929091165af18015610da357610d1192600091613e1c575b506001600160e01b03191614908280613d9f565b613e34915060203d8111613a8457613a768183614165565b83613e08565b3461021357610d11613e4b36614201565b916142ae565b34610213576020366003190112610213576004356001600160a01b0381811691829003610213577fd661c5a1b9e30d4cf3f1f304a69b11aee9f019da0cc8ca1e99595281a7ff9f7b91613eab602092600854163314614236565b600980546001600160a01b03191682179055604051908152a1005b3461021357604036600319011261021357613edf6141d5565b6024359081600052600260205260018060a01b038060406000205416908133148015613f59575b613f0f90614271565b8360005260046020526040600020921691826001600160601b0360a01b8254161790557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a4005b50816000526005602052604060002033600052602052613f0f60ff604060002054169050613f06565b34610213576020366003190112610213576004356000526004602052602060018060a01b0360406000205416604051908152f35b3461021357600036600319011261021357604051600090600054600181811c90808316928315614068575b6020938484108114613c0c57838652908115613bec575060011461400f57610a87846136a581880382614165565b60008080529294507f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8284106140555750505081610a87936136a59282010193613b83565b8054858501870152928501928101614039565b91607f1691613fe1565b346102135760203660031901126102135760043563ffffffff60e01b8116809103610213576020906301ffc9a760e01b81149081156140cf575b81156140be575b506040519015158152f35b635b5e139f60e01b149050826140b3565b6380ac58cd60e01b811491506140ac565b3461021357602036600319011261021357606090600435600052600760205263ffffffff604060002060018060a01b036001818354169201549184528116602084015260a01c166040820152f35b6101c081019081106001600160401b038211176103c057604052565b604081019081106001600160401b038211176103c057604052565b90601f801991011681019081106001600160401b038211176103c057604052565b60005b8381106141995750506000910152565b8181015183820152602001614189565b604091602082526141c98151809281602086015260208686019101614186565b601f01601f1916010190565b600435906001600160a01b038216820361021357565b602435906001600160a01b038216820361021357565b6060906003190112610213576001600160a01b0390600435828116810361021357916024359081168103610213579060443590565b1561423d57565b60405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606490fd5b1561427857565b60405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606490fd5b6000838152600260209081526040808320546001600160a01b03959486169490861685036143d757851694851561439f579061431f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef949392863314908115614382575b811561436c575b50614271565b84835260038252808320600019815401905585835280832060018154019055868352600282526004818420926001600160601b0360a01b93888582541617905552822090815416905580a4565b9050888552600484528285205416331438614319565b8786526005855283862033875285528386205460ff169150614312565b815162461bcd60e51b81526004810184905260116024820152701253959053125117d49150d25412515395607a1b6044820152606490fd5b815162461bcd60e51b815260048101849052600a60248201526957524f4e475f46524f4d60b01b6044820152606490fd5b9081602091031261021357516001600160e01b0319811681036102135790565b1561442f57565b60405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606490fd5b6001600160401b0381116103c057601f01601f191660200190565b60006101a06040516144938161412e565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152015263ffffffff81161561470e578060201c60005260066020526040600020549060018060a01b038216156147375763ffffffff8260a01c1663ffffffff82161161470e57806000526007602052604060002063ffffffff8360a01c1663ffffffff19831617600052604060002063ffffffff831663ffffffff8560a01c160363ffffffff8111610e425763ffffffff60018183160111610e4257600090600163ffffffff861611614699575b60018381015460a088901c63ffffffff1663ffffffff1988161760009081526002602052604080822054965493880154898352918190205497549051996001600160a01b0391821699988216989297929482169391909216916145f28b61412e565b8460201c8b52600160a01b60019003811660208c01528160a01c63ffffffff1660408c015260a01c63ffffffff1660608b0152600160a01b600190031660808a015260a089015260c08801528360a01c63ffffffff1660e088015263ffffffff1661010087015263ffffffff1660010163ffffffff1661012086015263ffffffff16610140850152600160a01b60019003166101608401526101808301526101a082015290565b905083600019810111610e4257600019840160005260076020526040600020606463ffffffff600186015460a01c1602908163ffffffff811603610e42576001015460a01c63ffffffff169081156146f85763ffffffff160490614590565b634e487b7160e01b600052601260045260246000fd5b604051630583584d60e11b8152602082901c600482015263ffffffff9091166024820152604490fd5b60249060405190630679b58960e51b825260201c6004820152fd5b602081830312610213578051906001600160401b038211610213570181601f8201121561021357805161478481614467565b926147926040519485614165565b81845260208284010111610213576147b09160208085019101614186565b90565b805191821561491a57600380600285010460021b9360208501936147ef6147d986614467565b956147e76040519788614165565b808752614467565b602086019490601f190136863760405194606086018681106001600160401b038211176103c057604098979852604086527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208701527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040870152966000975b88858110156148d357908680600493019a860101516001603f9080828460121c168c010151918b60ff9384848488600c1c1684010151168585600894868a60061c160101511691831b01821b01901b93168b010151160160e01b815201614871565b509493925095945095500680600114614906576002146148f4575b50815290565b603d60f81b60001990910152386148ee565b50613d3d60f01b60011990910152386148ee565b915050604051602081018181106001600160401b038211176103c0576040526000815290565b6001600160401b0381116103c05760051b60200190565b80518210156137d65760209160051b010190565b90602091600081841c81526006845263ffffffff916040838184205460a01c169261499584614940565b916149a281519384614165565b848352601f196149b186614940565b01368985013782976001958695865b6149d0575b505050505050505050565b88871696828811614a1b5763ffffffff19821690971785526007835283852088015488978a918991906001600160a01b0316614a12600019830185168b614957565b520116966149c0565b506149c5565b9060405160a08101604052608081019260008452925b6000190192600a906030828206018553049283614a3757809350608091030191601f1901918252565b9081518110156137d6570160200190565b60405190606082018281106001600160401b038211176103c057604052602a82526020820160403682378251156137d6576030905381516001908110156137d657607860218401536029905b808211614acd5750506137815790565b9091600f81166010811015614b0b576f181899199a1a9b1b9c1cb0b131b232b360811b901a614afc8486614a60565b5360041c916000190190614abd565b60246000634e487b7160e01b81526032600452fd5b60405190614b2d8261414a565b60028252614e6f60f01b6020830152565b60405190614b4b8261414a565b600382526259657360e81b6020830152565b7f3c7376672077696474683d2732393027206865696768743d273530302720766981527f6577426f783d2730203020323930203530302720786d6c6e733d27687474703a60208201527f2f2f7777772e77332e6f72672f323030302f737667273e3c636972636c652063604082015262783d2760e81b606082015260630190565b60209392908491614c6993604051968793614bfd61187c838701614b5d565b0165272063793d2760d01b8152614c1d8251809387600685019101614186565b01702720723d27313230272066696c6c3d272360781b6006820152614c4b8251809386601785019101614186565b016813979f1e17b9bb339f60b91b6017820152038085520183614165565b56fea264697066735822122078b0a4de7ba025bfec1224c4217c0a9a7a4b31a9f4df00ce2805d3589340786564736f6c63430008110033

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

0000000000000000000000005c71fcd090948dcc5e8a1a01ad8fa26313422022

-----Decoded View---------------
Arg [0] : _purityChecker (address): 0x5C71fcd090948dCC5E8A1a01ad8Fa26313422022

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000005c71fcd090948dcc5e8a1a01ad8fa26313422022


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.