false
true
0

Contract Address Details

0x2d9AABE9Ed2958DBAF46d57C16f97dd865F6A02F

Contract Name
GemFab
Creator
0xc07f6b–2a8e1a at 0x361e62–6fcea5
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
2 Transactions
Transfers
0 Transfers
Gas Used
2,078,222
Last Balance Update
26121300
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
GemFab




Optimization enabled
true
Compiler version
v0.8.28+commit.7893614a




Optimization runs
100
EVM Version
paris




Verified at
2026-03-26T13:12:32.549134Z

contracts/rich/gem.sol

/// SPDX-License-Identifier: AGPL-3.0-only

// Copyright (C) 2021 kevin and his friends
// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, version 3.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

pragma solidity ^0.8.25;

contract Gem {
    // === METADATA ===
    string public name;
    string public symbol;
    uint8 public constant decimals = 18;
    uint256 public totalSupply;

    // === UI REGISTRY (ORIGINAL CALLER ONLY, SURVIVES RENOUNCE) ===
    // The original caller (passed via factory) has permanent UI update rights
    address public immutable deployer;
    string public uiIpfsCid;     // e.g. "Qm..."
    uint256 public uiVersion;    // incremental version number

    event UIUpdated(string indexed ipfsCid, uint256 indexed version, address indexed updater);

    error ErrNotDeployer();

    // === OPTIONAL: backward compat bytes32 ===
    bytes32 public immutable nameBytes32;
    bytes32 public immutable symbolBytes32;

    // === ERC20 STATE ===
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;
    mapping(address => uint256) public nonces;

    // === AUTH (wards) ===
    mapping(address => bool) public wards;

    event Ward(address indexed usr, bool authed);

    // === EIP-2612 ===
    bytes32 public immutable DOMAIN_SEPARATOR;
    bytes32 public constant PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    // === EVENTS ===
    event Approval(address indexed src, address indexed guy, uint256 wad);
    event Transfer(address indexed src, address indexed dst, uint256 wad);

    // === ERRORS ===
    error ErrWard();
    error ErrUnderflow();
    error ErrOverflow();
    error ErrZeroDst();
    error ErrPermit();

    /// @notice Constructor takes explicit original deployer address
    /// @param name_ Token name
    /// @param symbol_ Token symbol
    /// @param initialDeployer_ The original caller who will have permanent UI update rights
    constructor(string memory name_, string memory symbol_, address initialDeployer_) payable {
        name = name_;
        symbol = symbol_;

        // Backward compat
        nameBytes32 = bytes32(bytes(name_));
        symbolBytes32 = bytes32(bytes(symbol_));

        // Immutable deployer = original caller (passed by factory)
        deployer = initialDeployer_;

        // Initial ward = factory caller (standard pattern)
        wards[msg.sender] = true;
        emit Ward(msg.sender, true);

        // EIP-712 domain separator
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256(bytes(name_)),
                keccak256(bytes("1")),
                block.chainid,
                address(this)
            )
        );
    }

    // === AUTH MODIFIERS ===
    modifier auth() {
        if (!wards[msg.sender]) revert ErrWard();
        _;
    }

    function rely(address usr) external auth {
        wards[usr] = true;
        emit Ward(usr, true);
    }

    function deny(address usr) external auth {
        wards[usr] = false;
        emit Ward(usr, false);
    }

    // === UI REGISTRY — ORIGINAL DEPLOYER ONLY (SURVIVES RENOUNCE) ===
    /// @notice Update the official UI IPFS CID and version
    /// @dev Only the original deployer (set at construction) can call this
    /// @param ipfsCid The new IPFS CID (e.g. "QmXYZ...")
    /// @param version Incremental version number
    function setUI(string calldata ipfsCid, uint256 version) external {
        if (msg.sender != deployer) revert ErrNotDeployer();
        uiIpfsCid = ipfsCid;
        uiVersion = version;
        emit UIUpdated(ipfsCid, version, msg.sender);
    }

    // === MINT / BURN (WARD-ONLY) ===
    function mint(address usr, uint256 wad) external auth {
        unchecked {
            uint256 supply = totalSupply;
            totalSupply = supply + wad;
            balanceOf[usr] += wad;
            if (supply + wad < supply) revert ErrOverflow();
        }
        emit Transfer(address(0), usr, wad);
    }

    function burn(address usr, uint256 wad) external auth {
        uint256 bal = balanceOf[usr];
        balanceOf[usr] = bal - wad;
        totalSupply -= wad;
        if (bal < wad) revert ErrUnderflow();
        emit Transfer(usr, address(0), wad);
    }

    // === ERC20 ===
    function transfer(address dst, uint256 wad) external returns (bool) {
        uint256 bal = balanceOf[msg.sender];
        balanceOf[msg.sender] = bal - wad;
        balanceOf[dst] += wad;
        if (bal < wad) revert ErrUnderflow();
        if (dst == address(0)) revert ErrZeroDst();
        emit Transfer(msg.sender, dst, wad);
        return true;
    }

    function transferFrom(address src, address dst, uint256 wad) external returns (bool) {
        uint256 allowed = allowance[src][msg.sender];
        if (allowed != type(uint256).max) {
            allowance[src][msg.sender] = allowed - wad;
            if (allowed < wad) revert ErrUnderflow();
        }

        uint256 bal = balanceOf[src];
        balanceOf[src] = bal - wad;
        balanceOf[dst] += wad;
        if (bal < wad) revert ErrUnderflow();
        if (dst == address(0)) revert ErrZeroDst();

        emit Transfer(src, dst, wad);
        return true;
    }

    function approve(address usr, uint256 wad) external returns (bool) {
        allowance[msg.sender][usr] = wad;
        emit Approval(msg.sender, usr, wad);
        return true;
    }

    // === EIP-2612 permit ===
    function permit(
        address owner, address spender, uint256 value, uint256 deadline,
        uint8 v, bytes32 r, bytes32 s
    ) external {
        if (block.timestamp > deadline) revert ErrPermit();
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
            )
        );
        address recovered = ecrecover(digest, v, r, s);
        if (recovered == address(0) || recovered != owner) revert ErrPermit();

        allowance[owner][spender] = value;
        emit Approval(owner, spender, value);
    }
}

// Updated Fab — passes original caller as immutable deployer
contract GemFab {
    mapping(address => bool) public built;

    event Build(address indexed caller, string name, string symbol, address indexed gem);

    /// @notice Build a new Gem token
    /// @dev Passes msg.sender (original caller) as the immutable deployer for UI updates
    function build(string calldata name_, string calldata symbol_)
        external payable returns (Gem gem)
    {
        gem = new Gem(name_, symbol_, msg.sender); // ← CRITICAL FIX: pass original caller as deployer
        built[address(gem)] = true;
        gem.rely(msg.sender);  // Standard: give original caller ward control
        emit Build(msg.sender, name_, symbol_, address(gem));
    }
}
        

Compiler Settings

{"remappings":[],"optimizer":{"runs":100,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"paris","compilationTarget":{"contracts/rich/gem.sol":"GemFab"}}
              

Contract ABI

[{"type":"event","name":"Build","inputs":[{"type":"address","name":"caller","internalType":"address","indexed":true},{"type":"string","name":"name","internalType":"string","indexed":false},{"type":"string","name":"symbol","internalType":"string","indexed":false},{"type":"address","name":"gem","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"payable","outputs":[{"type":"address","name":"gem","internalType":"contract Gem"}],"name":"build","inputs":[{"type":"string","name":"name_","internalType":"string"},{"type":"string","name":"symbol_","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"built","inputs":[{"type":"address","name":"","internalType":"address"}]}]
              

Contract Creation Code

0x6080604052348015600f57600080fd5b5061188e8061001f6000396000f3fe6080604052600436106100295760003560e01c80632cc23e841461002e57806354c7352214610073575b600080fd5b34801561003a57600080fd5b5061005e6100493660046101b7565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b610086610081366004610230565b61009e565b6040516001600160a01b03909116815260200161006a565b600084848484336040516100b1906101aa565b6100bf9594939291906102ca565b604051809103906000f0801580156100db573d6000803e3d6000fd5b506001600160a01b03811660008181526020819052604090819020805460ff19166001179055516332fd71af60e11b8152336004820152919250906365fae35e90602401600060405180830381600087803b15801561013957600080fd5b505af115801561014d573d6000803e3d6000fd5b50505050806001600160a01b0316336001600160a01b03167ffc37f1120bb19f2ba2904dfdb1d08b4d06a197c96aa10a1980159e0d704ea44c8787878760405161019a949392919061030c565b60405180910390a3949350505050565b61151a8061033f83390190565b6000602082840312156101c957600080fd5b81356001600160a01b03811681146101e057600080fd5b9392505050565b60008083601f8401126101f957600080fd5b50813567ffffffffffffffff81111561021157600080fd5b60208301915083602082850101111561022957600080fd5b9250929050565b6000806000806040858703121561024657600080fd5b843567ffffffffffffffff81111561025d57600080fd5b610269878288016101e7565b909550935050602085013567ffffffffffffffff81111561028957600080fd5b610295878288016101e7565b95989497509550505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006102de6060830187896102a1565b82810360208401526102f18186886102a1565b91505060018060a01b03831660408301529695505050505050565b6040815260006103206040830186886102a1565b82810360208401526103338185876102a1565b97965050505050505056fe61010060405260405161151a38038061151a8339810160408190526100239161020e565b600061002f8482610322565b50600161003c8382610322565b50610046836103e0565b60a052610052826103e0565b60c0526001600160a01b03811660805233600081815260086020908152604091829020805460ff1916600190811790915591519182527fa76edbbd439cab73baed08320eede7980d3894c8bc741d7a50801efcf024552e910160405180910390a25050805160209182012060408051808201825260018152603160f81b9084015280517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81850152808201929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528151808403909101815260c09092019052805191012060e052610404565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261017c57600080fd5b81516001600160401b0381111561019557610195610155565b604051601f8201601f19908116603f011681016001600160401b03811182821017156101c3576101c3610155565b6040528181528382016020018510156101db57600080fd5b60005b828110156101fa576020818601810151838301820152016101de565b506000918101602001919091529392505050565b60008060006060848603121561022357600080fd5b83516001600160401b0381111561023957600080fd5b6102458682870161016b565b602086015190945090506001600160401b0381111561026357600080fd5b61026f8682870161016b565b604086015190935090506001600160a01b038116811461028e57600080fd5b809150509250925092565b600181811c908216806102ad57607f821691505b6020821081036102cd57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561031d57806000526020600020601f840160051c810160208510156102fa5750805b601f840160051c820191505b8181101561031a5760008155600101610306565b50505b505050565b81516001600160401b0381111561033b5761033b610155565b61034f816103498454610299565b846102d3565b6020601f821160018114610383576000831561036b5750848201515b600019600385901b1c1916600184901b17845561031a565b600084815260208120601f198516915b828110156103b35787850151825560209485019460019092019101610393565b50848210156103d15786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b805160208083015191908110156102cd5760001960209190910360031b1b16919050565b60805160a05160c05160e0516110cf61044b6000396000818161020e0152610ab301526000610325015260006103c901526000818161035f015261071501526110cf6000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c80637ecebe00116100c3578063bf353dbb1161007c578063bf353dbb146102fd578063c466145e14610320578063d505accf14610347578063d5f394881461035a578063dd62ed3e14610399578063eafb3e4d146103c457600080fd5b80637ecebe001461029357806395d89b41146102b35780639c52a7f1146102bb5780639dc29fac146102ce578063a9059cbb146102e1578063b79b772a146102f457600080fd5b80633644e515116101155780633644e515146102095780633ba78d4c1461023057806340c10f191461023857806360cf9d621461024d57806365fae35e1461026057806370a082311461027357600080fd5b806306fdde031461015d578063095ea7b31461017b57806318160ddd1461019e57806323b872dd146101b557806330adf81f146101c8578063313ce567146101ef575b600080fd5b6101656103eb565b6040516101729190610ca3565b60405180910390f35b61018e610189366004610d0d565b610479565b6040519015158152602001610172565b6101a760025481565b604051908152602001610172565b61018e6101c3366004610d37565b6104e6565b6101a77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6101f7601281565b60405160ff9091168152602001610172565b6101a77f000000000000000000000000000000000000000000000000000000000000000081565b61016561064f565b61024b610246366004610d0d565b61065c565b005b61024b61025b366004610d74565b61070a565b61024b61026e366004610ded565b6107af565b6101a7610281366004610ded565b60056020526000908152604090205481565b6101a76102a1366004610ded565b60076020526000908152604090205481565b61016561083d565b61024b6102c9366004610ded565b61084a565b61024b6102dc366004610d0d565b6108c9565b61018e6102ef366004610d0d565b6109a4565b6101a760045481565b61018e61030b366004610ded565b60086020526000908152604090205460ff1681565b6101a77f000000000000000000000000000000000000000000000000000000000000000081565b61024b610355366004610e0f565b610a76565b6103817f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610172565b6101a76103a7366004610e82565b600660209081526000928352604080842090915290825290205481565b6101a77f000000000000000000000000000000000000000000000000000000000000000081565b600080546103f890610eb5565b80601f016020809104026020016040519081016040528092919081815260200182805461042490610eb5565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b505050505081565b3360008181526006602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906104d49086815260200190565b60405180910390a35060015b92915050565b6001600160a01b038316600090815260066020908152604080832033845290915281205460001981146105625761051d8382610f05565b6001600160a01b03861660009081526006602090815260408083203384529091529020558281101561056257604051634240f8e160e11b815260040160405180910390fd5b6001600160a01b0385166000908152600560205260409020546105858482610f05565b6001600160a01b0380881660009081526005602052604080822093909355908716815290812080548692906105bb908490610f18565b9091555050838110156105e157604051634240f8e160e11b815260040160405180910390fd5b6001600160a01b038516610608576040516327fabe0560e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b031660008051602061107a8339815191528660405161063b91815260200190565b60405180910390a350600195945050505050565b600380546103f890610eb5565b3360009081526008602052604090205460ff1661068c57604051637999b8d160e01b815260040160405180910390fd5b60028054828101918290556001600160a01b0384166000908152600560205260409020805484019055908111156106d657604051633b13fa2560e11b815260040160405180910390fd5b506040518181526001600160a01b0383169060009060008051602061107a8339815191529060200160405180910390a35050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461075357604051631ad48b0b60e11b815260040160405180910390fd5b6003610760838583610f90565b5060048190556040513390829061077a9086908690611050565b604051908190038120907f38cead06e44b5ed72886c30e80d644275953b75d6560f40147cb80e1d88fb12890600090a4505050565b3360009081526008602052604090205460ff166107df57604051637999b8d160e01b815260040160405180910390fd5b6001600160a01b038116600081815260086020908152604091829020805460ff1916600190811790915591519182527fa76edbbd439cab73baed08320eede7980d3894c8bc741d7a50801efcf024552e91015b60405180910390a250565b600180546103f890610eb5565b3360009081526008602052604090205460ff1661087a57604051637999b8d160e01b815260040160405180910390fd5b6001600160a01b0381166000818152600860209081526040808320805460ff19169055519182527fa76edbbd439cab73baed08320eede7980d3894c8bc741d7a50801efcf024552e9101610832565b3360009081526008602052604090205460ff166108f957604051637999b8d160e01b815260040160405180910390fd5b6001600160a01b03821660009081526005602052604090205461091c8282610f05565b6001600160a01b0384166000908152600560205260408120919091556002805484929061094a908490610f05565b90915550508181101561097057604051634240f8e160e11b815260040160405180910390fd5b6040518281526000906001600160a01b0385169060008051602061107a8339815191529060200160405180910390a3505050565b336000908152600560205260408120546109be8382610f05565b33600090815260056020526040808220929092556001600160a01b038616815290812080548592906109f1908490610f18565b909155505082811015610a1757604051634240f8e160e11b815260040160405180910390fd5b6001600160a01b038416610a3e576040516327fabe0560e01b815260040160405180910390fd5b6040518381526001600160a01b03851690339060008051602061107a8339815191529060200160405180910390a35060019392505050565b83421115610a9757604051630fc24c3160e31b815260040160405180910390fd5b6001600160a01b038716600090815260076020526040812080547f0000000000000000000000000000000000000000000000000000000000000000917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9187610b0583611060565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001610b7e92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015610be9573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580610c1e5750886001600160a01b0316816001600160a01b031614155b15610c3c57604051630fc24c3160e31b815260040160405180910390fd5b6001600160a01b038981166000818152600660209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b602081526000825180602084015260005b81811015610cd15760208186018101516040868401015201610cb4565b506000604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114610d0857600080fd5b919050565b60008060408385031215610d2057600080fd5b610d2983610cf1565b946020939093013593505050565b600080600060608486031215610d4c57600080fd5b610d5584610cf1565b9250610d6360208501610cf1565b929592945050506040919091013590565b600080600060408486031215610d8957600080fd5b833567ffffffffffffffff811115610da057600080fd5b8401601f81018613610db157600080fd5b803567ffffffffffffffff811115610dc857600080fd5b866020828401011115610dda57600080fd5b6020918201979096509401359392505050565b600060208284031215610dff57600080fd5b610e0882610cf1565b9392505050565b600080600080600080600060e0888a031215610e2a57600080fd5b610e3388610cf1565b9650610e4160208901610cf1565b95506040880135945060608801359350608088013560ff81168114610e6557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215610e9557600080fd5b610e9e83610cf1565b9150610eac60208401610cf1565b90509250929050565b600181811c90821680610ec957607f821691505b602082108103610ee957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156104e0576104e0610eef565b808201808211156104e0576104e0610eef565b634e487b7160e01b600052604160045260246000fd5b601f821115610f8b57806000526020600020601f840160051c81016020851015610f685750805b601f840160051c820191505b81811015610f885760008155600101610f74565b50505b505050565b67ffffffffffffffff831115610fa857610fa8610f2b565b610fbc83610fb68354610eb5565b83610f41565b6000601f841160018114610ff05760008515610fd85750838201355b600019600387901b1c1916600186901b178355610f88565b600083815260209020601f19861690835b828110156110215786850135825560209485019460019092019101611001565b508682101561103e5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8183823760009101908152919050565b60006001820161107257611072610eef565b506001019056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220c543742ca3f2ad14ad7b20a04b6bf875915baa1dbc3caf06c509e7c755d633a464736f6c634300081c0033a26469706673582212205eec11df4ae86f396390b90d6246886cab040271d398d32753a30e1a8d47b1b864736f6c634300081c0033

Deployed ByteCode

0x6080604052600436106100295760003560e01c80632cc23e841461002e57806354c7352214610073575b600080fd5b34801561003a57600080fd5b5061005e6100493660046101b7565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b610086610081366004610230565b61009e565b6040516001600160a01b03909116815260200161006a565b600084848484336040516100b1906101aa565b6100bf9594939291906102ca565b604051809103906000f0801580156100db573d6000803e3d6000fd5b506001600160a01b03811660008181526020819052604090819020805460ff19166001179055516332fd71af60e11b8152336004820152919250906365fae35e90602401600060405180830381600087803b15801561013957600080fd5b505af115801561014d573d6000803e3d6000fd5b50505050806001600160a01b0316336001600160a01b03167ffc37f1120bb19f2ba2904dfdb1d08b4d06a197c96aa10a1980159e0d704ea44c8787878760405161019a949392919061030c565b60405180910390a3949350505050565b61151a8061033f83390190565b6000602082840312156101c957600080fd5b81356001600160a01b03811681146101e057600080fd5b9392505050565b60008083601f8401126101f957600080fd5b50813567ffffffffffffffff81111561021157600080fd5b60208301915083602082850101111561022957600080fd5b9250929050565b6000806000806040858703121561024657600080fd5b843567ffffffffffffffff81111561025d57600080fd5b610269878288016101e7565b909550935050602085013567ffffffffffffffff81111561028957600080fd5b610295878288016101e7565b95989497509550505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006102de6060830187896102a1565b82810360208401526102f18186886102a1565b91505060018060a01b03831660408301529695505050505050565b6040815260006103206040830186886102a1565b82810360208401526103338185876102a1565b97965050505050505056fe61010060405260405161151a38038061151a8339810160408190526100239161020e565b600061002f8482610322565b50600161003c8382610322565b50610046836103e0565b60a052610052826103e0565b60c0526001600160a01b03811660805233600081815260086020908152604091829020805460ff1916600190811790915591519182527fa76edbbd439cab73baed08320eede7980d3894c8bc741d7a50801efcf024552e910160405180910390a25050805160209182012060408051808201825260018152603160f81b9084015280517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81850152808201929092527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528151808403909101815260c09092019052805191012060e052610404565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261017c57600080fd5b81516001600160401b0381111561019557610195610155565b604051601f8201601f19908116603f011681016001600160401b03811182821017156101c3576101c3610155565b6040528181528382016020018510156101db57600080fd5b60005b828110156101fa576020818601810151838301820152016101de565b506000918101602001919091529392505050565b60008060006060848603121561022357600080fd5b83516001600160401b0381111561023957600080fd5b6102458682870161016b565b602086015190945090506001600160401b0381111561026357600080fd5b61026f8682870161016b565b604086015190935090506001600160a01b038116811461028e57600080fd5b809150509250925092565b600181811c908216806102ad57607f821691505b6020821081036102cd57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561031d57806000526020600020601f840160051c810160208510156102fa5750805b601f840160051c820191505b8181101561031a5760008155600101610306565b50505b505050565b81516001600160401b0381111561033b5761033b610155565b61034f816103498454610299565b846102d3565b6020601f821160018114610383576000831561036b5750848201515b600019600385901b1c1916600184901b17845561031a565b600084815260208120601f198516915b828110156103b35787850151825560209485019460019092019101610393565b50848210156103d15786840151600019600387901b60f8161c191681555b50505050600190811b01905550565b805160208083015191908110156102cd5760001960209190910360031b1b16919050565b60805160a05160c05160e0516110cf61044b6000396000818161020e0152610ab301526000610325015260006103c901526000818161035f015261071501526110cf6000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c80637ecebe00116100c3578063bf353dbb1161007c578063bf353dbb146102fd578063c466145e14610320578063d505accf14610347578063d5f394881461035a578063dd62ed3e14610399578063eafb3e4d146103c457600080fd5b80637ecebe001461029357806395d89b41146102b35780639c52a7f1146102bb5780639dc29fac146102ce578063a9059cbb146102e1578063b79b772a146102f457600080fd5b80633644e515116101155780633644e515146102095780633ba78d4c1461023057806340c10f191461023857806360cf9d621461024d57806365fae35e1461026057806370a082311461027357600080fd5b806306fdde031461015d578063095ea7b31461017b57806318160ddd1461019e57806323b872dd146101b557806330adf81f146101c8578063313ce567146101ef575b600080fd5b6101656103eb565b6040516101729190610ca3565b60405180910390f35b61018e610189366004610d0d565b610479565b6040519015158152602001610172565b6101a760025481565b604051908152602001610172565b61018e6101c3366004610d37565b6104e6565b6101a77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6101f7601281565b60405160ff9091168152602001610172565b6101a77f000000000000000000000000000000000000000000000000000000000000000081565b61016561064f565b61024b610246366004610d0d565b61065c565b005b61024b61025b366004610d74565b61070a565b61024b61026e366004610ded565b6107af565b6101a7610281366004610ded565b60056020526000908152604090205481565b6101a76102a1366004610ded565b60076020526000908152604090205481565b61016561083d565b61024b6102c9366004610ded565b61084a565b61024b6102dc366004610d0d565b6108c9565b61018e6102ef366004610d0d565b6109a4565b6101a760045481565b61018e61030b366004610ded565b60086020526000908152604090205460ff1681565b6101a77f000000000000000000000000000000000000000000000000000000000000000081565b61024b610355366004610e0f565b610a76565b6103817f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610172565b6101a76103a7366004610e82565b600660209081526000928352604080842090915290825290205481565b6101a77f000000000000000000000000000000000000000000000000000000000000000081565b600080546103f890610eb5565b80601f016020809104026020016040519081016040528092919081815260200182805461042490610eb5565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b505050505081565b3360008181526006602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906104d49086815260200190565b60405180910390a35060015b92915050565b6001600160a01b038316600090815260066020908152604080832033845290915281205460001981146105625761051d8382610f05565b6001600160a01b03861660009081526006602090815260408083203384529091529020558281101561056257604051634240f8e160e11b815260040160405180910390fd5b6001600160a01b0385166000908152600560205260409020546105858482610f05565b6001600160a01b0380881660009081526005602052604080822093909355908716815290812080548692906105bb908490610f18565b9091555050838110156105e157604051634240f8e160e11b815260040160405180910390fd5b6001600160a01b038516610608576040516327fabe0560e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b031660008051602061107a8339815191528660405161063b91815260200190565b60405180910390a350600195945050505050565b600380546103f890610eb5565b3360009081526008602052604090205460ff1661068c57604051637999b8d160e01b815260040160405180910390fd5b60028054828101918290556001600160a01b0384166000908152600560205260409020805484019055908111156106d657604051633b13fa2560e11b815260040160405180910390fd5b506040518181526001600160a01b0383169060009060008051602061107a8339815191529060200160405180910390a35050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461075357604051631ad48b0b60e11b815260040160405180910390fd5b6003610760838583610f90565b5060048190556040513390829061077a9086908690611050565b604051908190038120907f38cead06e44b5ed72886c30e80d644275953b75d6560f40147cb80e1d88fb12890600090a4505050565b3360009081526008602052604090205460ff166107df57604051637999b8d160e01b815260040160405180910390fd5b6001600160a01b038116600081815260086020908152604091829020805460ff1916600190811790915591519182527fa76edbbd439cab73baed08320eede7980d3894c8bc741d7a50801efcf024552e91015b60405180910390a250565b600180546103f890610eb5565b3360009081526008602052604090205460ff1661087a57604051637999b8d160e01b815260040160405180910390fd5b6001600160a01b0381166000818152600860209081526040808320805460ff19169055519182527fa76edbbd439cab73baed08320eede7980d3894c8bc741d7a50801efcf024552e9101610832565b3360009081526008602052604090205460ff166108f957604051637999b8d160e01b815260040160405180910390fd5b6001600160a01b03821660009081526005602052604090205461091c8282610f05565b6001600160a01b0384166000908152600560205260408120919091556002805484929061094a908490610f05565b90915550508181101561097057604051634240f8e160e11b815260040160405180910390fd5b6040518281526000906001600160a01b0385169060008051602061107a8339815191529060200160405180910390a3505050565b336000908152600560205260408120546109be8382610f05565b33600090815260056020526040808220929092556001600160a01b038616815290812080548592906109f1908490610f18565b909155505082811015610a1757604051634240f8e160e11b815260040160405180910390fd5b6001600160a01b038416610a3e576040516327fabe0560e01b815260040160405180910390fd5b6040518381526001600160a01b03851690339060008051602061107a8339815191529060200160405180910390a35060019392505050565b83421115610a9757604051630fc24c3160e31b815260040160405180910390fd5b6001600160a01b038716600090815260076020526040812080547f0000000000000000000000000000000000000000000000000000000000000000917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9187610b0583611060565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001610b7e92919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015610be9573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580610c1e5750886001600160a01b0316816001600160a01b031614155b15610c3c57604051630fc24c3160e31b815260040160405180910390fd5b6001600160a01b038981166000818152600660209081526040808320948d16808452948252918290208b905590518a81527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050505050505050565b602081526000825180602084015260005b81811015610cd15760208186018101516040868401015201610cb4565b506000604082850101526040601f19601f83011684010191505092915050565b80356001600160a01b0381168114610d0857600080fd5b919050565b60008060408385031215610d2057600080fd5b610d2983610cf1565b946020939093013593505050565b600080600060608486031215610d4c57600080fd5b610d5584610cf1565b9250610d6360208501610cf1565b929592945050506040919091013590565b600080600060408486031215610d8957600080fd5b833567ffffffffffffffff811115610da057600080fd5b8401601f81018613610db157600080fd5b803567ffffffffffffffff811115610dc857600080fd5b866020828401011115610dda57600080fd5b6020918201979096509401359392505050565b600060208284031215610dff57600080fd5b610e0882610cf1565b9392505050565b600080600080600080600060e0888a031215610e2a57600080fd5b610e3388610cf1565b9650610e4160208901610cf1565b95506040880135945060608801359350608088013560ff81168114610e6557600080fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215610e9557600080fd5b610e9e83610cf1565b9150610eac60208401610cf1565b90509250929050565b600181811c90821680610ec957607f821691505b602082108103610ee957634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156104e0576104e0610eef565b808201808211156104e0576104e0610eef565b634e487b7160e01b600052604160045260246000fd5b601f821115610f8b57806000526020600020601f840160051c81016020851015610f685750805b601f840160051c820191505b81811015610f885760008155600101610f74565b50505b505050565b67ffffffffffffffff831115610fa857610fa8610f2b565b610fbc83610fb68354610eb5565b83610f41565b6000601f841160018114610ff05760008515610fd85750838201355b600019600387901b1c1916600186901b178355610f88565b600083815260209020601f19861690835b828110156110215786850135825560209485019460019092019101611001565b508682101561103e5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b8183823760009101908152919050565b60006001820161107257611072610eef565b506001019056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220c543742ca3f2ad14ad7b20a04b6bf875915baa1dbc3caf06c509e7c755d633a464736f6c634300081c0033a26469706673582212205eec11df4ae86f396390b90d6246886cab040271d398d32753a30e1a8d47b1b864736f6c634300081c0033