false
true
0

Contract Address Details

0x2722064897CA3ba34854eD01430Dfb97d147d3A9

Contract Name
Bank
Creator
0xc07f6b–2a8e1a at 0x9e092d–ded2ec
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
723 Transactions
Transfers
462 Transfers
Gas Used
119,295,985
Last Balance Update
26120036
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:
Bank




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




Optimization runs
100
EVM Version
paris




Verified at
2026-03-24T22:27:10.250638Z

Constructor Arguments

16e9c051056ea742d289d2cb753372cf432f332213ecd495b26ea8f72e3cf2e00000000000000000000000004526e1f56a48f67c139cf9d37a34eaa5cd96d566000000000000000000000000db8925962aebcefd33f2985836402458125949970000000000000000000000000000000000000000033b2e3c9fd0803ce80000000000000000000000000000000000000000000000033b2e3cab86fdc4266e00000000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000000000000000000003648a260e3486a65a000000000000000000000000000000000000000000000003648a260e3486a65a000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000cecb8f27f4200f3a0000000fffffffffffffffffffffffffffffffffffffffff64e754a208e7f494800000000000000000000000000000000000000000000000000000012ffaa3f2982800000000000000000000000000000000000000000000000000000000000000001710000000000000000000000000000000000000000019d971e4fe8401e740000000000000000000000000000000000000000000000033adcebf14bd76ef80000000000000000000000000000000000000000000000033b2e22b63b5cca5b48000000000000000000000000000000000000000000000000000007b3c18f3a5780000000000000000000000000000000000000000000033b2e3c9fd0cfce3a94df6e0000000000000000000000000000000000000000033b2e3dd0b59ed5fb5500000000000000000000000000000000000000000000033b2e3c9fd0803ce80000000000000000000000000000000000000000000000000000000000000000000258
              

contracts/rich/bank.sol

// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024 Free Software Foundation, in memoriam of Nikolai Mushegian

// Copyright (C) 2026 PulseChain Rico Credit System 1.

// This file is a modified version of the original Bank contract.
// Original source: ['https://github.com/ricobank/ricobank/blob/master/src/bank.sol']
/*
- Major new feature: Epoch-based RISK mining system with competitive burn-to-lead mechanics,
time-weighted leader rewards, and a 33% final leader bonus.
- Introduced `startEpoch()` function that properly finalizes the previous epoch before
setting up the new one, following strict effects-before-interactions ordering.
- Replaced the original inflation-only `mine()` with a new `mine(uint256 riskToBurn)`
that allows users to burn RISK to compete for leadership within each epoch.
- Added comprehensive epoch state management: `epochDuration`, `currentEpoch`,
`epochPool`, lead period tracking, burned amounts, and related mappings.
- Bug fix & improvement in `safe()`: collateral valuation now correctly incorporates `par`
for more accurate safety calculations.
- Enhanced `keep()` with a `meaningfulFlap` guard to reduce unnecessary calls and spam.
- Added deployment block tracking (`dep`) for safety checks (e.g., minimum blocks before first epoch).
- Added multiple view functions for better UI and off-chain integration:
    `currentEpochId()`, `getCurrentEpochInfo()`, `timeLeftInEpoch()`, etc.
- New events: `MiningBurn`, `MiningLeadChange`, `MiningBurnLeader`
- New custom errors for clearer failure modes in the mining system.
- Minor gas optimizations, code cleanups while preserving core logic.

        The core mechanisms of `frob`, `bail`, `drip`, `heal`, and `poke` remain functionally
        equivalent to the original design unless explicitly noted above.

All modifications are released under the same AGPL-3.0-or-later license.
We are grateful for the open foundation provided by Nikolai Mushegian and the Free Software Foundation.
*/
pragma solidity ^0.8.25;

import { Math } from "./math.sol";
import { Flog } from "./flog.sol";
import { Palm } from "./palm.sol";
import { Gem }  from "./gem.sol";
contract Bank is Math, Flog, Palm {
    struct Urn {
        uint256 ink;   // [wad] Locked Collateral
        uint256 art;   // [wad] Normalised Debt
    }

    struct BankParams {
        address tokenA;
        address tokenB;
        uint256 par;
        uint256 fee;
        uint256 dust;
        uint256 chop;
        uint256 liqr;
        uint256 pep;
        uint256 pop;
        int256  pup;
        uint256 gif;
        uint256 pex;
        uint256 wel;
        uint256 dam;
        uint256 mop;
        uint256 lax;
        uint256 how;
        uint256 cap;
        uint256 way;
        uint256 epochDuration; // [sec] Epoch length for mining
    }

    Gem immutable public rico; // stability primitive
    Gem immutable public risk; // buy-and-burn token

    // vat
    mapping (address => Urn) public urns; // CDPs
    uint256 public joy;   // [wad] System revenue
    uint256 public sin;   // [rad] Unbacked debt
    uint256 public rest;  // [rad] System revenue remainder
    uint256 public par;   // [ray] System Price (rico/ref)
    uint256 public tart;  // [wad] Total Normalised Debt
    uint256 public rack;  // [ray] Accumulated Rate
    uint256 public rho;   // [sec] Time of last drip
    uint256 immutable public dep; // [Block] Deployment Block
    uint256 immutable public fee;   // [ray] per-second compounding rate
    uint256 immutable public dust;  // [ray] Urn Ink Floor, as a fraction of totalSupply
    uint256 immutable public chop;  // [ray] Liquidation Penalty
    uint256 immutable public liqr;  // [ray] Liquidation Ratio
    uint256 immutable public pep;   // [num] discount exponent
    uint256 immutable public pop;   // [ray] discount offset
    int256  immutable public pup;   // [ray] signed discount shift
    uint256 constant public FEE_MAX = 1000000072964521287979890107; // ~10x/yr

    // vow
    uint256 public bel;  // [sec] last flap timestamp
    uint256 public gif;  // [wad] RISK base mint rate
    uint256 public chi;  // [sec] last mine timestamp
    uint256 public wal;  // [wad] risk deposited + risk totalSupply
    uint256 immutable public pex; // [ray] start price
    uint256 immutable public wel; // [ray] fraction of joy/flap
    uint256 immutable public dam; // [ray] per-second flap discount
    uint256 immutable public mop; // [ray] per-second gif decay
    uint256 immutable public lax; // [ray] mint-rate shift up (fraction of totalSupply)
    uint256 constant public LAX_MAX = 145929047899781146998; // ~100x/yr
    uint256 constant SAFE = RAY;

    // vox
    uint256 public way; // [ray] Price Rate (system price growth rate)
    uint256 immutable public how; // [ray] Sensitivity Parameter (way growth rate)
    uint256 immutable public cap; // [ray] Price Rate Clamp (1/cap <= way <= cap)
    uint256 constant public CAP_MAX = 1000000072964521287979890107; // ~10x/yr

    // Mining epochs
    uint256 immutable public epochDuration;
    uint256 public currentEpoch;
    uint256 public epochPool; // [wad] RISK minted for current epoch
    uint256 public totalRico; // [wad] Total RICO balance for epoch
    struct LeadPeriod {
    address leader;
    uint256 startTime;
    uint256 endTime;
    }

    uint256 constant FINAL_LEADER_BONUS_PCT = 33; // 33% bonus for final leader

    mapping(uint256 => mapping(address => uint256)) public burnedThisEpoch; // epoch => user => total burned
    mapping(uint256 => LeadPeriod[]) public epochLeadPeriods; // epoch => array of lead periods
    mapping(uint256 => address) public epochBurnLeader; // Current leader (last in periods)
    mapping(uint256 => uint256) public epochBurnLeaderAmount; // Current leader's total burn

    event MiningBurn(address indexed burner, uint256 amount, uint256 newTotal, bool tookLead);
    event MiningLeadChange(address indexed newLeader, uint256 timestamp, uint256 epoch);
    event MiningBurnLeader(address indexed leader, uint256 inflate, uint256 epoch);

    error ErrNotSafe();
    error ErrSafeBail();
    error ErrUrnDust();
    error ErrWrongUrn();
    error ErrEpochNotStarted();
    error ErrZeroBurn();
    error ErrTooSoon();


    constructor(BankParams memory p) {
        (rico, risk) = (Gem(p.tokenA), Gem(p.tokenB));

        (wel, dam, pex, mop, lax) = (p.wel, p.dam, p.pex, p.mop, p.lax);
        must(wel, 0, RAY);
        must(dam, 0, RAY);
        must(pex, 0, BLN); 
        must(mop, 0, RAY);
        must(lax, 0, LAX_MAX);

        (how, cap) = (p.how, p.cap);
        must(how, RAY, type(uint).max);
        must(cap, RAY, CAP_MAX);

        (par, dust) = (p.par, p.dust);
        must(dust, 0, RAY);

        (pep, pop, pup) = (p.pep, p.pop, p.pup);

        (liqr, chop, fee) = (p.liqr, p.chop, p.fee);
        must(liqr, RAY, type(uint).max);
        must(chop, RAY, 10 * RAY);
        must(fee, RAY, FEE_MAX);

        (rack, rho, bel) = (RAY, block.timestamp, block.timestamp);

        (gif, chi, wal) = (p.gif, block.timestamp, risk.totalSupply());
        must(wal, 0, RAD);

        way = p.way;
        must(way, rinv(cap), cap);

        epochDuration = p.epochDuration;
        currentEpoch = block.timestamp / epochDuration;
        dep = block.number; // Store deployment block

        emit NewPalm0("par", bytes32(par));
        emit NewPalm0("rho", bytes32(rho));
        emit NewPalm0("bel", bytes32(bel));
        emit NewPalm0("gif", bytes32(gif));
        emit NewPalm0("chi", bytes32(chi));
        emit NewPalm0("wal", bytes32(wal));
        emit NewPalm0("way", bytes32(way));
        emit NewPalm0("epochDuration", bytes32(epochDuration));
    }

    function safe(address u) public view returns (uint deal, uint tot) {
        Urn storage urn = urns[u];
        uint ink = urn.ink;
        uint tab = urn.art * rmul(par, rack);
        uint cut = rdiv(rmul(ink, par), liqr) * RAY;  // FIXED: Include par in cut for correct collateral valuation
        deal = tab > cut ? min(cut / (tab / RAY), SAFE - 1) : SAFE;
        tot  = ink * RAY;
    }

    function frob(int dink, int dart) external payable _flog_ {
        Urn storage urn = urns[msg.sender];
        uint _rack = drip();
        uint256 art = add(urn.art, dart);
        urn.art     = art;
        emit NewPalm1("art", bytes32(bytes20(msg.sender)), bytes32(art));
        tart = add(tart, dart);
        emit NewPalm0("tart", bytes32(tart));
        uint _rest;
        int dtab = mul(_rack, dart);
        if (dtab > 0) {
            uint wad = uint(dtab) / RAY;
            _rest = rest += uint(dtab) % RAY;
            emit NewPalm0("rest", bytes32(_rest));
            rico.mint(msg.sender, wad);
        } else if (dtab < 0) {
            uint wad = (uint(-dtab) / RAY) + 1;
            _rest = rest += add(wad * RAY, dtab);
            emit NewPalm0("rest", bytes32(_rest));
            rico.burn(msg.sender, wad);
        }
        uint ink = add(urn.ink, dink);
        urn.ink  = ink;
        emit NewPalm1("ink", bytes32(bytes20(msg.sender)), bytes32(ink));
        if (dink > 0) {
            risk.burn(msg.sender, uint(dink));
        } else if (dink < 0) {
            risk.mint(msg.sender, uint(-dink));
        }
        if (dink < 0 || dart > 0) {
            (uint deal,) = safe(msg.sender);
            if (deal < SAFE) revert ErrNotSafe();
        }
        if (art != 0 && urn.ink < rmul(wal, dust)) revert ErrUrnDust();
    }

    function bail(address u) external payable _flog_ returns (uint sell) {
        uint _rack = drip();
        (uint deal, uint tot) = safe(u);
        if (deal == SAFE) revert ErrSafeBail();
        Urn storage urn = urns[u];
        uint art = urn.art;
        urn.art  = 0;
        emit NewPalm1("art", bytes32(bytes20(u)), 0);
        uint dtab  = art * _rack;
        tart      -= art;
        emit NewPalm0("tart", bytes32(tart));
        sin += dtab;
        emit NewPalm0("sin", bytes32(sin));
        uint mash = rmash(deal, pep, pop, pup);
        uint earn = rmul(tot / RAY, mash);
        uint bill = rmul(chop, dtab / RAY);
        if (earn > bill) {
            sell = (urn.ink * bill) / earn;
            earn = bill;
        } else {
            sell = urn.ink;
        }
        uint _joy = joy += earn;
        emit NewPalm0("joy", bytes32(_joy));
        unchecked {
            uint _ink = urn.ink -= sell;
            emit NewPalm1("ink", bytes32(bytes20(u)), bytes32(_ink));
        }
        rico.burn(msg.sender, earn);
        risk.mint(msg.sender, sell);
    }

    function drip() internal returns (uint _rack) {
        if (block.timestamp == rho) return rack;
        uint prev = rack;
        _rack = grow(prev, fee, block.timestamp - rho);
        uint256 delt = _rack - prev;
        uint256 rad  = tart * delt;
        uint256 all  = rest + rad;
        rho  = block.timestamp;
        emit NewPalm0("rho", bytes32(block.timestamp));
        rack = _rack;
        emit NewPalm0("rack", bytes32(_rack));
        rest = all % RAY;
        emit NewPalm0("rest", bytes32(rest));
        joy  = joy + (all / RAY);
        emit NewPalm0("joy", bytes32(joy));
    }

      // balance system revenue with bad debt, auction off surplus
    function keep() external payable _flog_ {
        drip();
        // use equal scales for sin and joy
        uint _joy = joy;
        uint _sin = sin / RAY;
        // in case of deficit max price should always lead to decrease in way
        uint price = type(uint256).max;
        uint dt = block.timestamp - bel;
        bool meaningfulFlap = false;
        if (_joy > _sin) {
            // pay down sin, then auction off surplus RICO for RISK
            if (_sin > 1) {
                // gas - don't zero sin
                _joy = heal(_sin - 1);
            }
            // price decreases with time
            price = rmul(par * pex, rpow(dam, dt));
            if (price < par / pex) price = 0;
            // buy-and-burn risk with remaining (`flap`) rico
            uint flap = rmul(_joy - 1, wel);
            if (flap > 0) {  // Gate on non-zero flap to prevent spam
                meaningfulFlap = true;
                uint earn = rmul(flap, price);
                _joy -= flap;
                joy = _joy;
                emit NewPalm0("joy", bytes32(_joy));
                // swap rico for RISK, pay protocol fee
                rico.mint(msg.sender, flap);
                risk.burn(msg.sender, earn);
                // burning RISK without putting it in a CDP - update wal
                wal -= earn;
                emit NewPalm0("wal", bytes32(wal));
            }
        }
        // price is max uint in deficit, so poke always ticks down in deficit
        bel = block.timestamp;
        emit NewPalm0("bel", bytes32(block.timestamp));
        if (meaningfulFlap || _joy <= _sin) {  // Only poke on actual surplus auction or deficit
            poke(price, dt);
        }
    }

    function heal(uint wad) internal returns (uint _joy) {
        sin  = sin - (wad * RAY);
        emit NewPalm0("sin", bytes32(sin));
        joy  = (_joy = joy - wad);
        emit NewPalm0("joy", bytes32(_joy));
    }

   function startEpoch() external _flog_ {
    uint256 newEpoch = block.timestamp / epochDuration;
    if (newEpoch <= currentEpoch) revert ErrEpochNotStarted();
    if (block.number < (dep + 8640)) revert ErrTooSoon();

    // ——— FINALIZE PREVIOUS EPOCH (ALL EFFECTS FIRST) ———
    address finalLeader = address(0);
    uint256 bonusToTransfer = 0;
    uint256 undistributedToBurn = 0;
    uint256 poolToBurnIfNoActivity = 0;

    // Temporary arrays to accumulate transfers (avoid multiple external calls interleaved)
    address[] memory rewardRecipients;
    uint256[] memory rewardAmounts;

    if (currentEpoch > 0) {
        LeadPeriod[] storage periods = epochLeadPeriods[currentEpoch];
        uint256 totalTime = epochDuration;
        uint256 pool = epochPool;
        uint256 timePool = (pool * (100 - FINAL_LEADER_BONUS_PCT)) / 100;
        uint256 bonus = pool - timePool;
        uint256 distributed = 0;

        if (periods.length > 0) {
            // Effect: close final period
            uint256 expectedEnd = (currentEpoch + 1) * epochDuration;
            periods[periods.length - 1].endTime = expectedEnd;
            finalLeader = periods[periods.length - 1].leader;

            // Calculate all time-based rewards (no external calls yet)
            rewardRecipients = new address[](periods.length);
            rewardAmounts = new uint256[](periods.length);

            for (uint256 i = 0; i < periods.length; i++) {
                LeadPeriod memory period = periods[i];
                uint256 duration = period.endTime - period.startTime;
                uint256 share = (timePool * duration) / totalTime;
                if (share > 0) {
                    rewardRecipients[i] = period.leader;
                    rewardAmounts[i] = share;
                    distributed += share;
                    emit MiningBurnLeader(period.leader, share, currentEpoch);
                }
            }

            undistributedToBurn = timePool - distributed;

            // Bonus calculation
            if (bonus > 0 && finalLeader != address(0)) {
                bonusToTransfer = bonus;
                emit MiningBurnLeader(finalLeader, bonus, currentEpoch);
            } else if (bonus > 0) {
                undistributedToBurn += bonus; // burn bonus if no leader
            }
        } else {
            // No activity → burn entire pool
            poolToBurnIfNoActivity = pool;
        }

        // All effects for previous epoch: update wal for everything that will be burned
        uint256 totalBurn = undistributedToBurn + poolToBurnIfNoActivity;
        if (totalBurn > 0) {
            wal -= totalBurn;
        }
    }

    // ——— NEW EPOCH SETUP (ALL EFFECTS FIRST) ———
    uint256 elapsed = block.timestamp - chi;
    gif = grow(gif, mop, elapsed);
    emit NewPalm0("gif", bytes32(gif));
    chi = block.timestamp;
    emit NewPalm0("chi", bytes32(chi));

    epochPool = (gif + rmul(wal, lax)) * epochDuration;

    // Effect: update wal BEFORE minting
    wal += epochPool;
    emit NewPalm0("wal", bytes32(wal));

    totalRico = rico.totalSupply();
    currentEpoch = newEpoch;

    // Reset mappings
    delete epochLeadPeriods[newEpoch];
    epochBurnLeader[newEpoch] = address(0);
    epochBurnLeaderAmount[newEpoch] = 0;

    emit NewPalm0("currentEpoch", bytes32(currentEpoch));

    // ——— ALL INTERACTIONS LAST (after every effect) ———
    // Mint new epoch pool
    if (epochPool > 0) {
        risk.mint(address(this), epochPool);
    }

    // Previous epoch burns (undistributed + no-activity)
    uint256 totalPreviousBurn = undistributedToBurn + poolToBurnIfNoActivity;
    if (totalPreviousBurn > 0) {
        risk.burn(address(this), totalPreviousBurn);
    }

    // Time-based leader rewards
    for (uint256 i = 0; i < rewardRecipients.length; i++) {
        if (rewardAmounts[i] > 0) {
            risk.transfer(rewardRecipients[i], rewardAmounts[i]);
        }
    }

    // Final leader bonus
    if (bonusToTransfer > 0) {
        risk.transfer(finalLeader, bonusToTransfer);
    }
}

function mine(uint256 riskToBurn) external _flog_ {
    drip();

    uint256 epoch = block.timestamp / epochDuration;
    if (epoch != currentEpoch) revert ErrEpochNotStarted();
    if (riskToBurn == 0) revert ErrZeroBurn();

    wal -= riskToBurn;

    uint256 previous = burnedThisEpoch[epoch][msg.sender];
    uint256 newTotal = previous + riskToBurn;
    burnedThisEpoch[epoch][msg.sender] = newTotal;

    bool tookLead = false;
    if (newTotal > epochBurnLeaderAmount[epoch]) {
        LeadPeriod[] storage periods = epochLeadPeriods[epoch];
        if (periods.length > 0) {
            periods[periods.length - 1].endTime = block.timestamp;
        }

        periods.push(LeadPeriod({
            leader: msg.sender,
            startTime: block.timestamp,
            endTime: 0 // Ongoing until next lead change or epoch end
        }));

        epochBurnLeader[epoch] = msg.sender;
        epochBurnLeaderAmount[epoch] = newTotal;
        tookLead = true;
        emit MiningLeadChange(msg.sender, block.timestamp, epoch);
    }
    risk.burn(msg.sender, riskToBurn);

    emit MiningBurn(msg.sender, riskToBurn, newTotal, tookLead);
}

    function poke(uint mar, uint dt) internal {
        if (dt == 0) return;
        uint _par = par;
        uint _way = way;
        _par      = grow(_par, _way, dt);
        par       = _par;
        emit NewPalm0("par", bytes32(_par));
        if (mar < _par) {
            _way = min(cap, grow(_way, how, dt));
        } else if (mar > _par) {
            _way = max(rinv(cap), grow(_way, rinv(how), dt));
        }
        way = _way;
        emit NewPalm0("way", bytes32(_way));
    }

    // ————————————————————————————————
// MINING & EPOCH GETTERS (FINAL CONSOLIDATED VERSION)
// ————————————————————————————————

/// @notice Returns the true on-chain current epoch ID (fixes all clock drift bugs)
function currentEpochId() external view returns (uint256) {
    return block.timestamp / epochDuration;
}

/// @notice Returns seconds remaining in the current epoch
function timeLeftInEpoch() external view returns (uint256) {
    uint256 epochEnd = ((block.timestamp / epochDuration) + 1) * epochDuration;
    return epochEnd > block.timestamp ? epochEnd - block.timestamp : 0;
}

/// @notice Returns whether mining is currently active in the current epoch
function isMiningActive() external view returns (bool) {
    return block.timestamp / epochDuration == currentEpoch;
}

/// @notice All-in-one current epoch info — the single source of truth for UI
function getCurrentEpochInfo() external view returns (
    uint256 epochId,          // True on-chain epoch
    uint256 startTime,        // epochId * epochDuration
    uint256 endTime,          // startTime + epochDuration
    uint256 timeLeft,         // endTime - block.timestamp
    uint256 pool,             // Current epoch's total RISK inflation
    address leader,           // Current burn leader
    uint256 leaderAmount,     // Leader's total burned RISK
    bool    isActive          // Is this epoch fully started and mining allowed?
) {
    epochId = block.timestamp / epochDuration;
    startTime = epochId * epochDuration;
    endTime = startTime + epochDuration;
    timeLeft = endTime > block.timestamp ? endTime - block.timestamp : 0;
    pool = epochPool;

    // Use true epoch ID for leader lookup (critical!)
    leader = epochBurnLeader[epochId];
    leaderAmount = epochBurnLeaderAmount[epochId];

    isActive = (epochId == currentEpoch);
}

/// @notice Current leader (uses true epoch ID — safer than old version)
function getCurrentLeader() external view returns (address leader, uint256 amount) {
    uint256 epoch = block.timestamp / epochDuration;
    leader = epochBurnLeader[epoch];
    amount = epochBurnLeaderAmount[epoch];
}

/// @notice User's burned RISK in current epoch
function getMyCurrentBurn() external view returns (uint256) {
    return burnedThisEpoch[currentEpoch][msg.sender];
}

/// @notice Any address's burned RISK in current epoch
function getCurrentBurnOf(address user) external view returns (uint256) {
    return burnedThisEpoch[currentEpoch][user];
}

/// @notice Current epoch inflation pool (RISK to be distributed)
function getCurrentInflate() external view returns (uint256) {
    return epochPool;
}
}
        

/palm.sol

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

// Copyright (C) 2024 Free Software Foundation, in memoriam of Nikolai Mushegian

pragma solidity ^0.8.25;

abstract contract Palm {
    event NewPalm0(
        bytes32 indexed key
      , bytes32 val
    );
    event NewPalm1(
        bytes32 indexed key
      , bytes32 indexed idx0
      , bytes32 val
    );
}
          

/math.sol

// SPDX-License-Identifier: AGPL-3.0-or-later

// Copyright (C) 2024 Free Software Foundation, in memoriam of Nikolai Mushegian
// Copyright (C) 2020 Maker Ecosystem Growth Holdings, INC.
// Copyright (C) 2018 Rain <rainbreak@riseup.net>
// Copyright (C) 2018 Lev Livnev <lev@liv.nev.org.uk>
// 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, either version 3 of the License, or
// (at your option) any later version.
//
// 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 Math {
    // when a (uint, int) arithmetic operation over/underflows
    // Err{returnty}{Over|Under}
    // need these because solidity has no native (uint, int) 
    // overflow checks
    error ErrUintOver();
    error ErrUintUnder();
    error ErrIntUnder();
    error ErrIntOver();
    error ErrBound();

    uint256 internal constant BLN = 10 **  9;
    uint256 internal constant WAD = 10 ** 18;
    uint256 internal constant RAY = 10 ** 27;
    uint256 internal constant RAD = 10 ** 45;

    uint256 internal constant BANKYEAR = ((365 * 24) + 6) * 3600;

    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x <= y ? x : y;
    }
    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x >= y ? x : y;
    }

    function add(uint x, int y) internal pure returns (uint z) {
        unchecked {
            z = x + uint(y);
            if (y > 0 && z <= x) revert ErrUintOver();
            if (y < 0 && z >= x) revert ErrUintUnder();
        }
    }

    function mul(uint x, int y) internal pure returns (int z) {
        unchecked {
            z = int(x) * y;
            if (int(x) < 0) revert ErrIntOver();
            if (y != 0 && z / y != int(x)) {
                if (y > 0) revert ErrIntOver();
                else revert ErrIntUnder();
            }
        }
    }

    function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
    z = (x * y + RAY / 2) / RAY; // ← ADD ROUNDING
}
    function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x * RAY / y;
    }
    function rinv(uint256 x) internal pure returns (uint256) {
        return rdiv(RAY, x);
    }

    function grow(uint256 amt, uint256 ray, uint256 dt) internal pure returns (uint256 z) {
        z = amt * rpow(ray, dt) / RAY;
    }

    // from dss src/abaci.sol:136
    function rpow(uint256 x, uint256 n) internal pure returns (uint256 z) {
        assembly {
            switch n case 0 { z := RAY }
            default {
                switch x case 0 { z := 0 }
                default {
                    switch mod(n, 2) case 0 { z := RAY } default { z := x }
                    let half := div(RAY, 2)  // for rounding.
                    for { n := div(n, 2) } n { n := div(n,2) } {
                        let xx := mul(x, x)
                        if shr(128, x) { revert(0,0) }
                        let xxRound := add(xx, half)
                        if lt(xxRound, xx) { revert(0,0) }
                        x := div(xxRound, RAY)
                        if mod(n,2) {
                            let zx := mul(z, x)
                            if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
                            let zxRound := add(zx, half)
                            if lt(zxRound, zx) { revert(0,0) }
                            z := div(zxRound, RAY)
                        }
                    }
                }
            }
        }
    }

    function rmash(uint deal, uint pep, uint pop, int pup)
      internal pure returns (uint res) {
        res = rmul(pop, rpow(deal, pep));
        if (pup < 0 && uint(-pup) > res) return 0;
        res = add(res, pup);
    }

    function must(uint actual, uint lo, uint hi) internal pure {
        if (actual < lo || actual > hi) revert ErrBound();
    }

}
          

/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));
    }
}
          

/flog.sol

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

// Copyright (C) 2024 Free Software Foundation, in memoriam of Nikolai Mushegian

pragma solidity ^0.8.25;

abstract contract Flog {
    event NewFlog(
        address indexed caller
      , bytes4 indexed sig
      , bytes data
    );

    // similar to ds-note - emits function call data
    // use at beginning of external state modifying functions
    modifier _flog_ {
        emit NewFlog(msg.sender, msg.sig, msg.data);
        _;
    }
}
          

Compiler Settings

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

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"tuple","name":"p","internalType":"struct Bank.BankParams","components":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"uint256","name":"par","internalType":"uint256"},{"type":"uint256","name":"fee","internalType":"uint256"},{"type":"uint256","name":"dust","internalType":"uint256"},{"type":"uint256","name":"chop","internalType":"uint256"},{"type":"uint256","name":"liqr","internalType":"uint256"},{"type":"uint256","name":"pep","internalType":"uint256"},{"type":"uint256","name":"pop","internalType":"uint256"},{"type":"int256","name":"pup","internalType":"int256"},{"type":"uint256","name":"gif","internalType":"uint256"},{"type":"uint256","name":"pex","internalType":"uint256"},{"type":"uint256","name":"wel","internalType":"uint256"},{"type":"uint256","name":"dam","internalType":"uint256"},{"type":"uint256","name":"mop","internalType":"uint256"},{"type":"uint256","name":"lax","internalType":"uint256"},{"type":"uint256","name":"how","internalType":"uint256"},{"type":"uint256","name":"cap","internalType":"uint256"},{"type":"uint256","name":"way","internalType":"uint256"},{"type":"uint256","name":"epochDuration","internalType":"uint256"}]}]},{"type":"error","name":"ErrBound","inputs":[]},{"type":"error","name":"ErrEpochNotStarted","inputs":[]},{"type":"error","name":"ErrIntOver","inputs":[]},{"type":"error","name":"ErrIntUnder","inputs":[]},{"type":"error","name":"ErrNotSafe","inputs":[]},{"type":"error","name":"ErrSafeBail","inputs":[]},{"type":"error","name":"ErrTooSoon","inputs":[]},{"type":"error","name":"ErrUintOver","inputs":[]},{"type":"error","name":"ErrUintUnder","inputs":[]},{"type":"error","name":"ErrUrnDust","inputs":[]},{"type":"error","name":"ErrWrongUrn","inputs":[]},{"type":"error","name":"ErrZeroBurn","inputs":[]},{"type":"event","name":"MiningBurn","inputs":[{"type":"address","name":"burner","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"newTotal","internalType":"uint256","indexed":false},{"type":"bool","name":"tookLead","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"MiningBurnLeader","inputs":[{"type":"address","name":"leader","internalType":"address","indexed":true},{"type":"uint256","name":"inflate","internalType":"uint256","indexed":false},{"type":"uint256","name":"epoch","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MiningLeadChange","inputs":[{"type":"address","name":"newLeader","internalType":"address","indexed":true},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false},{"type":"uint256","name":"epoch","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NewFlog","inputs":[{"type":"address","name":"caller","internalType":"address","indexed":true},{"type":"bytes4","name":"sig","internalType":"bytes4","indexed":true},{"type":"bytes","name":"data","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"NewPalm0","inputs":[{"type":"bytes32","name":"key","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"val","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"NewPalm1","inputs":[{"type":"bytes32","name":"key","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"idx0","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"val","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"CAP_MAX","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"FEE_MAX","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"LAX_MAX","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"sell","internalType":"uint256"}],"name":"bail","inputs":[{"type":"address","name":"u","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"bel","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"burnedThisEpoch","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"cap","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"chi","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"chop","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentEpoch","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentEpochId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dam","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dep","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"dust","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"epochBurnLeader","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"epochBurnLeaderAmount","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"epochDuration","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"leader","internalType":"address"},{"type":"uint256","name":"startTime","internalType":"uint256"},{"type":"uint256","name":"endTime","internalType":"uint256"}],"name":"epochLeadPeriods","inputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"epochPool","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"fee","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"frob","inputs":[{"type":"int256","name":"dink","internalType":"int256"},{"type":"int256","name":"dart","internalType":"int256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentBurnOf","inputs":[{"type":"address","name":"user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"epochId","internalType":"uint256"},{"type":"uint256","name":"startTime","internalType":"uint256"},{"type":"uint256","name":"endTime","internalType":"uint256"},{"type":"uint256","name":"timeLeft","internalType":"uint256"},{"type":"uint256","name":"pool","internalType":"uint256"},{"type":"address","name":"leader","internalType":"address"},{"type":"uint256","name":"leaderAmount","internalType":"uint256"},{"type":"bool","name":"isActive","internalType":"bool"}],"name":"getCurrentEpochInfo","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentInflate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"leader","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"getCurrentLeader","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getMyCurrentBurn","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"gif","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"how","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isMiningActive","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"joy","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"keep","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lax","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"liqr","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"mine","inputs":[{"type":"uint256","name":"riskToBurn","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"mop","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"par","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pep","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pex","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pop","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"int256","name":"","internalType":"int256"}],"name":"pup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rack","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rest","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rho","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract Gem"}],"name":"rico","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract Gem"}],"name":"risk","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"deal","internalType":"uint256"},{"type":"uint256","name":"tot","internalType":"uint256"}],"name":"safe","inputs":[{"type":"address","name":"u","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sin","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"startEpoch","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tart","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeLeftInEpoch","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalRico","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"ink","internalType":"uint256"},{"type":"uint256","name":"art","internalType":"uint256"}],"name":"urns","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"wal","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"way","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"wel","inputs":[]}]
              

Contract Creation Code

0x6102c060405234801561001157600080fd5b50604051613a4d380380613a4d83398101604081905261003091610567565b805160208201516001600160a01b0390811660a052166080526101808101516101a08201516101608301516101c0808501516101e0808701516102405261022091909152919052610200919091528190526100999060006b033b2e3c9fd0803ce800000061049c565b610200516100b59060006b033b2e3c9fd0803ce800000061049c565b6101c0516100c9906000633b9aca0061049c565b610220516100e59060006b033b2e3c9fd0803ce800000061049c565b610240516100fe9060006807e92c1fe64d6b297661049c565b6102008101516102208201516102805261026081905261012d906b033b2e3c9fd0803ce800000060001961049c565b61028051610154906b033b2e3c9fd0803ce80000006b033b2e4094668dc44877f5bb61049c565b604081015160808201516101008190526004919091556101829060006b033b2e3c9fd0803ce800000061049c565b60e080820151610100830151610120808501516101a052610180919091526101609190915260c083015160a084015160608501519093529190526101408190526101db906b033b2e3c9fd0803ce800000060001961049c565b61012051610200906b033b2e3c9fd0803ce80000006101fb81600a61066d565b61049c565b60e051610226906b033b2e3c9fd0803ce80000006b033b2e4094668dc44877f5bb61049c565b42600881905560078190556b033b2e3c9fd0803ce800000060065561014082015160a051604080516318160ddd60e01b815290519293926001600160a01b03909216916318160ddd916004808201926020929091908290030181865afa158015610294573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b89190610692565b600b819055600a919091556009919091556102e8906000722cd76fe086b93ce2f768a00b22a0000000000061049c565b610240810151600c8190556102805161030e9190610305906104cc565b6102805161049c565b6102608101516102a081905261032490426106ab565b600d554360c052600454604051908152623830b960e91b90600080516020613a2d8339815191529060200160405180910390a26007546040519081526272686f60e81b90600080516020613a2d8339815191529060200160405180910390a26008546040519081526218995b60ea1b90600080516020613a2d8339815191529060200160405180910390a26009546040519081526233b4b360e91b90600080516020613a2d8339815191529060200160405180910390a2600a546040519081526263686960e81b90600080516020613a2d8339815191529060200160405180910390a2600b54604051908152621dd85b60ea1b90600080516020613a2d8339815191529060200160405180910390a2600c546040519081526277617960e81b90600080516020613a2d8339815191529060200160405180910390a26102a0516040519081526c32b837b1b4223ab930ba34b7b760991b90600080516020613a2d8339815191529060200160405180910390a2506106cd565b818310806104a957508083115b156104c75760405163dcc76e0b60e01b815260040160405180910390fd5b505050565b60006104e46b033b2e3c9fd0803ce8000000836104ea565b92915050565b6000816105036b033b2e3c9fd0803ce80000008561066d565b61050d91906106ab565b9392505050565b60405161028081016001600160401b038111828210171561054557634e487b7160e01b600052604160045260246000fd5b60405290565b80516001600160a01b038116811461056257600080fd5b919050565b600061028082840312801561057b57600080fd5b506000610586610514565b61058f8461054b565b815261059d6020850161054b565b602082015260408481015190820152606080850151908201526080808501519082015260a0808501519082015260c0808501519082015260e08085015190820152610100808501519082015261012080850151908201526101408085015190820152610160808501519082015261018080850151908201526101a080850151908201526101c080850151908201526101e080850151908201526102008085015190820152610220808501519082015261024080850151908201526102609384015193810193909352509092915050565b80820281158282048414176104e457634e487b7160e01b600052601160045260246000fd5b6000602082840312156106a457600080fd5b5051919050565b6000826106c857634e487b7160e01b600052601260045260246000fd5b500490565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161026051610280516102a0516131596108d46000396000818161057901528181610b9b015281816117e1015281816118a20152818161190301528181611cf801528181612169015281816121a2015281816121ce015281816121fa015281816126f901528181612754015261278301526000818161041201528181612d590152612dba01526000818161044601528181612d7e0152612de70152600081816108cf0152611d1f01526000818161047a0152611c740152600081816106ab015261246c01526000818161073001526124df015260008181610a520152818161243b015261249501526000818161096701526110050152600081816107a40152610fe40152600081816108130152610fc30152600081816105c301526122dc015260008181610a1e0152611054015260008181610adb01526117410152600081816109ea015261284d0152600081816106fc015261182f0152600081816104ae01528181610d95015281816111dc015281816115df0152818161166001528181611ec101528181611f5401528181611fee015281816120d701526125ed0152600081816102f70152818161115e015281816113e70152818161150601528181611da4015261256f01526131596000f3fe6080604052600436106102e05760003560e01c8063855a0fe311610186578063c92aecc4116100d7578063e1fac83011610085578063e1fac83014610a40578063e4d06d8214610a74578063e868ba7014610a7c578063eacdc5ff14610a9f578063f2c2e66114610ab4578063fad9aba314610ac9578063fd14461e14610afd57600080fd5b8063c92aecc414610907578063ca945e911461091d578063cb92c56514610955578063d09f406514610989578063d7010999146109a9578063ddca3f43146109d8578063def8f41b14610a0c57600080fd5b8063a89ec7f311610134578063a89ec7f3146107dc578063ace237f514610801578063b44e5f0b14610835578063babc394f14610862578063bccddfe4146108bd578063c0ea09d7146108f1578063c2624e1e1461037057600080fd5b8063855a0fe3146106ea578063866d8bbe1461071e5780638eeab577146107525780639df43d7914610767578063a2c8b1771461077d578063a4ece52c14610792578063a62cd358146107c657600080fd5b8063495d32cb116102405780635d7320e3116101ee5780635d7320e3146105fb57806366c1773d146106445780636c0285081461065a5780636f2007a514610670578063766718081461068357806378386ede14610699578063815fd96c146106cd57600080fd5b8063495d32cb1461051c5780634d474898146105325780634dc639ea146105545780634ff0876a146105675780635b88ecd71461059b5780635ce67089146105b15780635d6542af146105e557600080fd5b8063331b278a1161029d578063331b278a146103bc578063355274ea146104005780633a4a4233146104345780634196fad914610468578063426a0c881461049c578063465b43d0146104d0578063470915fb146104e657600080fd5b806306029ec2146102e55780630695563f14610336578063071bafb51461035a57806317f997bd1461037057806320aba08b146103905780632cd30556146103a6575b600080fd5b3480156102f157600080fd5b506103197f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561034257600080fd5b5061034c600e5481565b60405190815260200161032d565b34801561036657600080fd5b5061034c60025481565b34801561037c57600080fd5b5061034c6b033b2e4094668dc44877f5bb81565b34801561039c57600080fd5b5061034c60075481565b3480156103b257600080fd5b5061034c60055481565b3480156103c857600080fd5b5061034c6103d7366004612ee5565b600d5460009081526010602090815260408083206001600160a01b039094168352929052205490565b34801561040c57600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b34801561044057600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b34801561047457600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104a857600080fd5b506103197f000000000000000000000000000000000000000000000000000000000000000081565b3480156104dc57600080fd5b5061034c60015481565b3480156104f257600080fd5b50610319610501366004612f00565b6012602052600090815260409020546001600160a01b031681565b34801561052857600080fd5b5061034c60045481565b34801561053e57600080fd5b5061055261054d366004612f00565b610b42565b005b61034c610562366004612ee5565b610e49565b34801561057357600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105a757600080fd5b5061034c60095481565b3480156105bd57600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105f157600080fd5b5061034c600c5481565b34801561060757600080fd5b5061062f610616366004612ee5565b6000602081905290815260409020805460019091015482565b6040805192835260208301919091520161032d565b34801561065057600080fd5b5061034c600f5481565b34801561066657600080fd5b5061034c60085481565b61055261067e366004612f19565b611256565b34801561068f57600080fd5b5061034c600d5481565b3480156106a557600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106d957600080fd5b5061034c6807e92c1fe64d6b297681565b3480156106f657600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b34801561072a57600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b34801561075e57600080fd5b50600e5461034c565b34801561077357600080fd5b5061034c60065481565b34801561078957600080fd5b50610552611791565b34801561079e57600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107d257600080fd5b5061034c600b5481565b3480156107e857600080fd5b506107f161215e565b604051901515815260200161032d565b34801561080d57600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b34801561084157600080fd5b5061034c610850366004612f00565b60136020526000908152604090205481565b34801561086e57600080fd5b50610877612194565b60408051988952602089019790975295870194909452606086019290925260808501526001600160a01b031660a084015260c0830152151560e08201526101000161032d565b3480156108c957600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b3480156108fd57600080fd5b5061034c60035481565b34801561091357600080fd5b5061034c600a5481565b34801561092957600080fd5b5061034c610938366004612f3b565b601060209081526000928352604080842090915290825290205481565b34801561096157600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b34801561099557600080fd5b5061062f6109a4366004612ee5565b61227c565b3480156109b557600080fd5b50600d54600090815260106020908152604080832033845290915290205461034c565b3480156109e457600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b348015610a1857600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b348015610a4c57600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b610552612383565b348015610a8857600080fd5b50610a916126f0565b60405161032d929190612f67565b348015610aab57600080fd5b5061034c61274d565b348015610ac057600080fd5b5061034c61277e565b348015610ad557600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000081565b348015610b0957600080fd5b50610b1d610b18366004612f19565b6127e1565b604080516001600160a01b03909416845260208401929092529082015260600161032d565b6000356001600160e01b0319166001600160e01b031916336001600160a01b03166000805160206130e4833981519152600036604051610b83929190612f80565b60405180910390a3610b9361282d565b506000610bc07f000000000000000000000000000000000000000000000000000000000000000042612fdb565b9050600d548114610be457604051630314cff360e51b815260040160405180910390fd5b81600003610c05576040516367bacd3760e11b815260040160405180910390fd5b81600b6000828254610c179190612fef565b9091555050600081815260106020908152604080832033845290915281205490610c418483613002565b60008481526010602090815260408083203384528252808320849055868352601390915281205491925090821115610d7e576000848152601160205260409020805415610cc057805442908290610c9a90600190612fef565b81548110610caa57610caa613015565b9060005260206000209060030201600201819055505b60408051606081018252338082524260208084018281526000858701818152885460018082018b558a84528584209851600390920290980180546001600160a01b039092166001600160a01b031992831617815593518489015590516002909301929092558b815260128352868120805490921685179091556013825285902088905584519182528101899052919450917f681fd45e542405d668f482f501e9ffc9d9dbad87101b41550a2aec74584b677b910160405180910390a2505b604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90610dcc9033908990600401612f67565b600060405180830381600087803b158015610de657600080fd5b505af1158015610dfa573d6000803e3d6000fd5b505060408051888152602081018690528415158183015290513393507ff83f760a1941218e401dbf956a03dd7472d1e599e6a09e3e6886b3810f1f398392509081900360600190a25050505050565b6040516000906001600160e01b03198235169033906000805160206130e483398151915290610e7b9085903690612f80565b60405180910390a36000610e8d61282d565b9050600080610e9b8561227c565b91509150676765c793fa10079d601b1b8203610eca5760405163a1455f9f60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320600181018054908590559151938452929091606089901b6001600160601b0319169162185c9d60ea1b91600080516020613104833981519152910160405180910390a36000610f32868361302b565b90508160056000828254610f469190612fef565b9091555050600554604051908152631d185c9d60e21b906000805160206130c48339815191529060200160405180910390a28060026000828254610f8a9190613002565b90915550506002546040519081526239b4b760e91b906000805160206130c48339815191529060200160405180910390a26000611029867f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006129aa565b9050600061104b611045676765c793fa10079d601b1b88612fdb565b836129f5565b9050600061108d7f0000000000000000000000000000000000000000000000000000000000000000611088676765c793fa10079d601b1b87612fdb565b6129f5565b9050808211156110ba57855482906110a690839061302b565b6110b09190612fdb565b99508091506110bf565b855499505b600082600160008282546110d39190613002565b9182905550604051818152909250626a6f7960e81b91506000805160206130c48339815191529060200160405180910390a286548b900380885560405181815260608e901b6001600160601b0319169062696e6b60e81b906000805160206131048339815191529060200160405180910390a350604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906111959033908790600401612f67565b600060405180830381600087803b1580156111af57600080fd5b505af11580156111c3573d6000803e3d6000fd5b50506040516340c10f1960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692506340c10f1991506112159033908f90600401612f67565b600060405180830381600087803b15801561122f57600080fd5b505af1158015611243573d6000803e3d6000fd5b5050505050505050505050505050919050565b6000356001600160e01b0319166001600160e01b031916336001600160a01b03166000805160206130e4833981519152600036604051611297929190612f80565b60405180910390a3336000908152602081905260408120906112b761282d565b905060006112c9836001015485612a33565b600184018190556040518181529091503360601b6001600160601b0319169062185c9d60ea1b906000805160206131048339815191529060200160405180910390a361131760055485612a33565b6005819055604051908152631d185c9d60e21b906000805160206130c48339815191529060200160405180910390a26000806113538487612a98565b90506000811315611456576000611375676765c793fa10079d601b1b83612fdb565b905061138c676765c793fa10079d601b1b83613042565b6003600082825461139d9190613002565b9182905550604051818152909450631c995cdd60e21b91506000805160206130c48339815191529060200160405180910390a26040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f199061141e9033908590600401612f67565b600060405180830381600087803b15801561143857600080fd5b505af115801561144c573d6000803e3d6000fd5b5050505050611571565b6000811215611571576000676765c793fa10079d601b1b61147683613056565b6114809190612fdb565b61148b906001613002565b90506114ab6114a5676765c793fa10079d601b1b8361302b565b83612a33565b600360008282546114bc9190613002565b9182905550604051818152909450631c995cdd60e21b91506000805160206130c48339815191529060200160405180910390a2604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac9061153d9033908590600401612f67565b600060405180830381600087803b15801561155757600080fd5b505af115801561156b573d6000803e3d6000fd5b50505050505b6000611581866000015489612a33565b8087556040518181529091503360601b6001600160601b0319169062696e6b60e81b906000805160206131048339815191529060200160405180910390a3600088131561164d57604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac906116169033908c90600401612f67565b600060405180830381600087803b15801561163057600080fd5b505af1158015611644573d6000803e3d6000fd5b505050506116df565b60008812156116df576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166340c10f193361168f8b613056565b6040518363ffffffff1660e01b81526004016116ac929190612f67565b600060405180830381600087803b1580156116c657600080fd5b505af11580156116da573d6000803e3d6000fd5b505050505b60008812806116ee5750600087135b1561172f5760006116fe3361227c565b509050676765c793fa10079d601b1b81101561172d57604051637cae106b60e11b815260040160405180910390fd5b505b83158015906117695750611765600b547f00000000000000000000000000000000000000000000000000000000000000006129f5565b8654105b156117875760405163a51f35b160e01b815260040160405180910390fd5b5050505050505050565b6000356001600160e01b0319166001600160e01b031916336001600160a01b03166000805160206130e48339815191526000366040516117d2929190612f80565b60405180910390a360006118067f000000000000000000000000000000000000000000000000000000000000000042612fdb565b9050600d54811161182a57604051630314cff360e51b815260040160405180910390fd5b6118567f00000000000000000000000000000000000000000000000000000000000000006121c0613002565b43101561187657604051634045a93560e11b815260040160405180910390fd5b6000806000806060806000600d541115611c5a57600d546000908152601160205260408120600e5490917f0000000000000000000000000000000000000000000000000000000000000000919060646118d0602182612fef565b6118da908461302b565b6118e49190612fdb565b905060006118f28284612fef565b855490915060009015611c225760007f0000000000000000000000000000000000000000000000000000000000000000600d5460016119319190613002565b61193b919061302b565b90508087600189805490506119509190612fef565b8154811061196057611960613015565b60009182526020909120600260039092020101558654879061198490600190612fef565b8154811061199457611994613015565b600091825260209091206003909102015487546001600160a01b039091169d5067ffffffffffffffff8111156119cc576119cc613072565b6040519080825280602002602001820160405280156119f5578160200160208202803683370190505b50875490995067ffffffffffffffff811115611a1357611a13613072565b604051908082528060200260200182016040528015611a3c578160200160208202803683370190505b50975060005b8754811015611b89576000888281548110611a5f57611a5f613015565b6000918252602080832060408051606081018252600390940290910180546001600160a01b03168452600181015492840183905260020154908301819052919350611aa991612fef565b9050600089611ab8838a61302b565b611ac29190612fdb565b90508015611b7e5782600001518d8581518110611ae157611ae1613015565b60200260200101906001600160a01b031690816001600160a01b031681525050808c8581518110611b1457611b14613015565b6020908102919091010152611b298187613002565b955082600001516001600160a01b03167fb1ac1931f981158c0ae87d8afae53e019589f7599ee85330037f8697fa3dff0182600d54604051611b75929190918252602082015260400190565b60405180910390a25b505050600101611a42565b50611b948285612fef565b9a50600083118015611bae57506001600160a01b038d1615155b15611c0957829b508c6001600160a01b03167fb1ac1931f981158c0ae87d8afae53e019589f7599ee85330037f8697fa3dff0184600d54604051611bfc929190918252602082015260400190565b60405180910390a2611c1c565b8215611c1c57611c19838c613002565b9a505b50611c26565b8398505b6000611c328a8c613002565b90508015611c525780600b6000828254611c4c9190612fef565b90915550505b505050505050505b6000600a5442611c6a9190612fef565b9050611c996009547f000000000000000000000000000000000000000000000000000000000000000083612b1b565b60098190556040519081526233b4b360e91b906000805160206130c48339815191529060200160405180910390a242600a8190556040519081526263686960e81b906000805160206130c48339815191529060200160405180910390a27f0000000000000000000000000000000000000000000000000000000000000000611d43600b547f00000000000000000000000000000000000000000000000000000000000000006129f5565b600954611d509190613002565b611d5a919061302b565b600e819055600b8054600090611d71908490613002565b9091555050600b54604051908152621dd85b60ea1b906000805160206130c48339815191529060200160405180910390a27f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e249190613088565b600f55600d8890556000888152601160205260408120611e4391612e74565b600088815260126020908152604080832080546001600160a01b03191690556013825280832092909255600d5491519182526b0c6eae4e4cadce88ae0dec6d60a31b916000805160206130c4833981519152910160405180910390a2600e5415611f2957600e546040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916340c10f1991611ef6913091600401612f67565b600060405180830381600087803b158015611f1057600080fd5b505af1158015611f24573d6000803e3d6000fd5b505050505b6000611f358587613002565b90508015611fbe57604051632770a7eb60e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690639dc29fac90611f8b9030908590600401612f67565b600060405180830381600087803b158015611fa557600080fd5b505af1158015611fb9573d6000803e3d6000fd5b505050505b60005b84518110156120b9576000848281518110611fde57611fde613015565b602002602001015111156120b1577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb86838151811061202d5761202d613015565b602002602001015186848151811061204757612047613015565b60200260200101516040518363ffffffff1660e01b815260040161206c929190612f67565b6020604051808303816000875af115801561208b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120af91906130a1565b505b600101611fc1565b5086156121535760405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb9061210e908b908b90600401612f67565b6020604051808303816000875af115801561212d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215191906130a1565b505b505050505050505050565b600d5460009061218e7f000000000000000000000000000000000000000000000000000000000000000042612fdb565b14905090565b6000808080808080806121c77f000000000000000000000000000000000000000000000000000000000000000042612fdb565b97506121f37f00000000000000000000000000000000000000000000000000000000000000008961302b565b965061221f7f000000000000000000000000000000000000000000000000000000000000000088613002565b955042861161222f576000612239565b6122394287612fef565b600e5460008a815260126020908152604080832054601390925290912054600d549b9c9a9b999a93999298506001600160a01b03909116965094508a1492509050565b6001600160a01b038116600090815260208190526040812080546004546006548493929184916122ac91906129f5565b83600101546122bb919061302b565b90506000676765c793fa10079d601b1b6123006122da856004546129f5565b7f0000000000000000000000000000000000000000000000000000000000000000612b47565b61230a919061302b565b905080821161232457676765c793fa10079d601b1b612361565b61236161233c676765c793fa10079d601b1b84612fdb565b6123469083612fdb565b61235c6001676765c793fa10079d601b1b612fef565b612b5f565b9550612378676765c793fa10079d601b1b8461302b565b945050505050915091565b6000356001600160e01b0319166001600160e01b031916336001600160a01b03166000805160206130e48339815191526000366040516123c4929190612f80565b60405180910390a36123d461282d565b506001546002546000906123f490676765c793fa10079d601b1b90612fdb565b6008549091506000199060009061240b9042612fef565b905060008385111561269f5760018411156124365761243361242e600186612fef565b612b76565b94505b6124917f0000000000000000000000000000000000000000000000000000000000000000600454612467919061302b565b6110887f000000000000000000000000000000000000000000000000000000000000000085612c0c565b92507f00000000000000000000000000000000000000000000000000000000000000006004546124c19190612fdb565b8310156124cd57600092505b60006125036124dd600188612fef565b7f00000000000000000000000000000000000000000000000000000000000000006129f5565b9050801561269d5760019150600061251b82866129f5565b90506125278288612fef565b6001819055604051818152909750626a6f7960e81b906000805160206130c48339815191529060200160405180910390a26040516340c10f1960e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906340c10f19906125a69033908690600401612f67565b600060405180830381600087803b1580156125c057600080fd5b505af11580156125d4573d6000803e3d6000fd5b5050604051632770a7eb60e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250639dc29fac91506126269033908590600401612f67565b600060405180830381600087803b15801561264057600080fd5b505af1158015612654573d6000803e3d6000fd5b5050505080600b600082825461266a9190612fef565b9091555050600b54604051908152621dd85b60ea1b906000805160206130c48339815191529060200160405180910390a2505b505b4260088190556040519081526218995b60ea1b906000805160206130c48339815191529060200160405180910390a280806126da5750838511155b156126e9576126e98383612cfe565b5050505050565b6000808061271e7f000000000000000000000000000000000000000000000000000000000000000042612fdb565b6000908152601260209081526040808320546013909252909120546001600160a01b0390911694909350915050565b60006127797f000000000000000000000000000000000000000000000000000000000000000042612fdb565b905090565b6000807f00000000000000000000000000000000000000000000000000000000000000006127ac8142612fdb565b6127b7906001613002565b6127c1919061302b565b90504281116127d15760006127db565b6127db4282612fef565b91505090565b601160205281600052604060002081815481106127fd57600080fd5b60009182526020909120600390910201805460018201546002909201546001600160a01b03909116935090915083565b6000600754420361283f575060065490565b60065460075461287c9082907f0000000000000000000000000000000000000000000000000000000000000000906128779042612fef565b612b1b565b9150600061288a8284612fef565b905060008160055461289c919061302b565b90506000816003546128ae9190613002565b4260078190556040519081529091506272686f60e81b906000805160206130c48339815191529060200160405180910390a26006859055604051858152637261636b60e01b906000805160206130c48339815191529060200160405180910390a2612924676765c793fa10079d601b1b82613042565b6003819055604051908152631c995cdd60e21b906000805160206130c48339815191529060200160405180910390a2612968676765c793fa10079d601b1b82612fdb565b6001546129759190613002565b6001819055604051908152626a6f7960e81b906000805160206130c48339815191529060200160405180910390a25050505090565b60006129ba836110888787612c0c565b90506000821280156129d35750806129d183613056565b115b156129e0575060006129ed565b6129ea8183612a33565b90505b949350505050565b6000676765c793fa10079d601b1b612a0e600282612fdb565b612a18848661302b565b612a229190613002565b612a2c9190612fdb565b9392505050565b818101600082138015612a465750828111155b15612a645760405163cdc2bcd760e01b815260040160405180910390fd5b600082128015612a745750828110155b15612a925760405163259981cf60e21b815260040160405180910390fd5b92915050565b8181026000831215612abd57604051638f71065f60e01b815260040160405180910390fd5b8115801590612adb575082828281612ad757612ad7612faf565b0514155b15612a92576000821315612b0257604051638f71065f60e01b815260040160405180910390fd5b60405163b80fa08560e01b815260040160405180910390fd5b6000676765c793fa10079d601b1b612b338484612c0c565b612b3d908661302b565b6129ed9190612fdb565b600081612a22676765c793fa10079d601b1b8561302b565b600081831115612b6f5781612a2c565b5090919050565b6000612b8d676765c793fa10079d601b1b8361302b565b600254612b9a9190612fef565b60028190556040519081526239b4b760e91b906000805160206130c48339815191529060200160405180910390a281600154612bd69190612fef565b6001819055604051818152909150626a6f7960e81b906000805160206130c48339815191529060200160405180910390a2919050565b6000818015612ce857838015612cdd57600184168015612c2e57859350612c3d565b676765c793fa10079d601b1b93505b506002909304926b019d971e4fe8401e740000005b8415612cd7578586028660801c15612c6957600080fd5b81810181811015612c7957600080fd5b676765c793fa10079d601b1b90049650506001851615612ccc578584028487820414158715151615612caa57600080fd5b81810181811015612cba57600080fd5b676765c793fa10079d601b1b90049450505b600285049450612c52565b50612ce2565b600092505b50612cf7565b676765c793fa10079d601b1b91505b5092915050565b80600003612d0a575050565b600454600c54612d1b828285612b1b565b6004819055604051818152909250623830b960e91b906000805160206130c48339815191529060200160405180910390a281841015612daa57612da37f000000000000000000000000000000000000000000000000000000000000000061235c837f000000000000000000000000000000000000000000000000000000000000000087612b1b565b9050612e19565b81841115612e1957612e16612dde7f0000000000000000000000000000000000000000000000000000000000000000612e4d565b612e1183612e0b7f0000000000000000000000000000000000000000000000000000000000000000612e4d565b87612b1b565b612e64565b90505b600c8190556040518181526277617960e81b906000805160206130c48339815191529060200160405180910390a250505050565b6000612a92676765c793fa10079d601b1b83612b47565b600081831015612b6f5781612a2c565b5080546000825560030290600052602060002090810190612e959190612e98565b50565b5b80821115612ec55780546001600160a01b03191681556000600182018190556002820155600301612e99565b5090565b80356001600160a01b0381168114612ee057600080fd5b919050565b600060208284031215612ef757600080fd5b612a2c82612ec9565b600060208284031215612f1257600080fd5b5035919050565b60008060408385031215612f2c57600080fd5b50508035926020909101359150565b60008060408385031215612f4e57600080fd5b82359150612f5e60208401612ec9565b90509250929050565b6001600160a01b03929092168252602082015260400190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082612fea57612fea612faf565b500490565b81810381811115612a9257612a92612fc5565b80820180821115612a9257612a92612fc5565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417612a9257612a92612fc5565b60008261305157613051612faf565b500690565b6000600160ff1b820161306b5761306b612fc5565b5060000390565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561309a57600080fd5b5051919050565b6000602082840312156130b357600080fd5b81518015158114612a2c57600080fdfe16e9c051056ea742d289d2cb753372cf432f332213ecd495b26ea8f72e3cf2e0c8b2a2dbd2bddf4ecc3e665d9828132a78820abf89df014d2ce4510f27a16061a6a62c84c48e7b9441c54da7ead6df8213afddbc24649e1f6b88294160ef069fa2646970667358221220cde81c166f3d191855f21a8dc72c5ec028c8970b7c1ae66f060beb735a25c37b64736f6c634300081c003316e9c051056ea742d289d2cb753372cf432f332213ecd495b26ea8f72e3cf2e00000000000000000000000004526e1f56a48f67c139cf9d37a34eaa5cd96d566000000000000000000000000db8925962aebcefd33f2985836402458125949970000000000000000000000000000000000000000033b2e3c9fd0803ce80000000000000000000000000000000000000000000000033b2e3cab86fdc4266e00000000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000000000000000000003648a260e3486a65a000000000000000000000000000000000000000000000003648a260e3486a65a000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000cecb8f27f4200f3a0000000fffffffffffffffffffffffffffffffffffffffff64e754a208e7f494800000000000000000000000000000000000000000000000000000012ffaa3f2982800000000000000000000000000000000000000000000000000000000000000001710000000000000000000000000000000000000000019d971e4fe8401e740000000000000000000000000000000000000000000000033adcebf14bd76ef80000000000000000000000000000000000000000000000033b2e22b63b5cca5b48000000000000000000000000000000000000000000000000000007b3c18f3a5780000000000000000000000000000000000000000000033b2e3c9fd0cfce3a94df6e0000000000000000000000000000000000000000033b2e3dd0b59ed5fb5500000000000000000000000000000000000000000000033b2e3c9fd0803ce80000000000000000000000000000000000000000000000000000000000000000000258

Deployed ByteCode

0x6080604052600436106102e05760003560e01c8063855a0fe311610186578063c92aecc4116100d7578063e1fac83011610085578063e1fac83014610a40578063e4d06d8214610a74578063e868ba7014610a7c578063eacdc5ff14610a9f578063f2c2e66114610ab4578063fad9aba314610ac9578063fd14461e14610afd57600080fd5b8063c92aecc414610907578063ca945e911461091d578063cb92c56514610955578063d09f406514610989578063d7010999146109a9578063ddca3f43146109d8578063def8f41b14610a0c57600080fd5b8063a89ec7f311610134578063a89ec7f3146107dc578063ace237f514610801578063b44e5f0b14610835578063babc394f14610862578063bccddfe4146108bd578063c0ea09d7146108f1578063c2624e1e1461037057600080fd5b8063855a0fe3146106ea578063866d8bbe1461071e5780638eeab577146107525780639df43d7914610767578063a2c8b1771461077d578063a4ece52c14610792578063a62cd358146107c657600080fd5b8063495d32cb116102405780635d7320e3116101ee5780635d7320e3146105fb57806366c1773d146106445780636c0285081461065a5780636f2007a514610670578063766718081461068357806378386ede14610699578063815fd96c146106cd57600080fd5b8063495d32cb1461051c5780634d474898146105325780634dc639ea146105545780634ff0876a146105675780635b88ecd71461059b5780635ce67089146105b15780635d6542af146105e557600080fd5b8063331b278a1161029d578063331b278a146103bc578063355274ea146104005780633a4a4233146104345780634196fad914610468578063426a0c881461049c578063465b43d0146104d0578063470915fb146104e657600080fd5b806306029ec2146102e55780630695563f14610336578063071bafb51461035a57806317f997bd1461037057806320aba08b146103905780632cd30556146103a6575b600080fd5b3480156102f157600080fd5b506103197f0000000000000000000000004526e1f56a48f67c139cf9d37a34eaa5cd96d56681565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561034257600080fd5b5061034c600e5481565b60405190815260200161032d565b34801561036657600080fd5b5061034c60025481565b34801561037c57600080fd5b5061034c6b033b2e4094668dc44877f5bb81565b34801561039c57600080fd5b5061034c60075481565b3480156103b257600080fd5b5061034c60055481565b3480156103c857600080fd5b5061034c6103d7366004612ee5565b600d5460009081526010602090815260408083206001600160a01b039094168352929052205490565b34801561040c57600080fd5b5061034c7f0000000000000000000000000000000000000000033b2e3dd0b59ed5fb55000081565b34801561044057600080fd5b5061034c7f0000000000000000000000000000000000000000033b2e3c9fd0cfce3a94df6e81565b34801561047457600080fd5b5061034c7f0000000000000000000000000000000000000000033b2e22b63b5cca5b48000081565b3480156104a857600080fd5b506103197f000000000000000000000000db8925962aebcefd33f29858364024581259499781565b3480156104dc57600080fd5b5061034c60015481565b3480156104f257600080fd5b50610319610501366004612f00565b6012602052600090815260409020546001600160a01b031681565b34801561052857600080fd5b5061034c60045481565b34801561053e57600080fd5b5061055261054d366004612f00565b610b42565b005b61034c610562366004612ee5565b610e49565b34801561057357600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000025881565b3480156105a757600080fd5b5061034c60095481565b3480156105bd57600080fd5b5061034c7f000000000000000000000000000000000000000003648a260e3486a65a00000081565b3480156105f157600080fd5b5061034c600c5481565b34801561060757600080fd5b5061062f610616366004612ee5565b6000602081905290815260409020805460019091015482565b6040805192835260208301919091520161032d565b34801561065057600080fd5b5061034c600f5481565b34801561066657600080fd5b5061034c60085481565b61055261067e366004612f19565b611256565b34801561068f57600080fd5b5061034c600d5481565b3480156106a557600080fd5b5061034c7f0000000000000000000000000000000000000000033adcebf14bd76ef800000081565b3480156106d957600080fd5b5061034c6807e92c1fe64d6b297681565b3480156106f657600080fd5b5061034c7f00000000000000000000000000000000000000000000000000000000018e5f4381565b34801561072a57600080fd5b5061034c7f0000000000000000000000000000000000000000019d971e4fe8401e7400000081565b34801561075e57600080fd5b50600e5461034c565b34801561077357600080fd5b5061034c60065481565b34801561078957600080fd5b50610552611791565b34801561079e57600080fd5b5061034c7f00000000000000000000000000000000000000000cecb8f27f4200f3a000000081565b3480156107d257600080fd5b5061034c600b5481565b3480156107e857600080fd5b506107f161215e565b604051901515815260200161032d565b34801561080d57600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000000181565b34801561084157600080fd5b5061034c610850366004612f00565b60136020526000908152604090205481565b34801561086e57600080fd5b50610877612194565b60408051988952602089019790975295870194909452606086019290925260808501526001600160a01b031660a084015260c0830152151560e08201526101000161032d565b3480156108c957600080fd5b5061034c7f00000000000000000000000000000000000000000000000007b3c18f3a57800081565b3480156108fd57600080fd5b5061034c60035481565b34801561091357600080fd5b5061034c600a5481565b34801561092957600080fd5b5061034c610938366004612f3b565b601060209081526000928352604080842090915290825290205481565b34801561096157600080fd5b5061034c7ffffffffffffffffffffffffffffffffffffffffff64e754a208e7f494800000081565b34801561099557600080fd5b5061062f6109a4366004612ee5565b61227c565b3480156109b557600080fd5b50600d54600090815260106020908152604080832033845290915290205461034c565b3480156109e457600080fd5b5061034c7f0000000000000000000000000000000000000000033b2e3cab86fdc4266e000081565b348015610a1857600080fd5b5061034c7f000000000000000000000000000000000000000003648a260e3486a65a00000081565b348015610a4c57600080fd5b5061034c7f000000000000000000000000000000000000000000000000000000000000017181565b610552612383565b348015610a8857600080fd5b50610a916126f0565b60405161032d929190612f67565b348015610aab57600080fd5b5061034c61274d565b348015610ac057600080fd5b5061034c61277e565b348015610ad557600080fd5b5061034c7f0000000000000000000000000000000000000000000000056bc75e2d6310000081565b348015610b0957600080fd5b50610b1d610b18366004612f19565b6127e1565b604080516001600160a01b03909416845260208401929092529082015260600161032d565b6000356001600160e01b0319166001600160e01b031916336001600160a01b03166000805160206130e4833981519152600036604051610b83929190612f80565b60405180910390a3610b9361282d565b506000610bc07f000000000000000000000000000000000000000000000000000000000000025842612fdb565b9050600d548114610be457604051630314cff360e51b815260040160405180910390fd5b81600003610c05576040516367bacd3760e11b815260040160405180910390fd5b81600b6000828254610c179190612fef565b9091555050600081815260106020908152604080832033845290915281205490610c418483613002565b60008481526010602090815260408083203384528252808320849055868352601390915281205491925090821115610d7e576000848152601160205260409020805415610cc057805442908290610c9a90600190612fef565b81548110610caa57610caa613015565b9060005260206000209060030201600201819055505b60408051606081018252338082524260208084018281526000858701818152885460018082018b558a84528584209851600390920290980180546001600160a01b039092166001600160a01b031992831617815593518489015590516002909301929092558b815260128352868120805490921685179091556013825285902088905584519182528101899052919450917f681fd45e542405d668f482f501e9ffc9d9dbad87101b41550a2aec74584b677b910160405180910390a2505b604051632770a7eb60e21b81526001600160a01b037f000000000000000000000000db8925962aebcefd33f2985836402458125949971690639dc29fac90610dcc9033908990600401612f67565b600060405180830381600087803b158015610de657600080fd5b505af1158015610dfa573d6000803e3d6000fd5b505060408051888152602081018690528415158183015290513393507ff83f760a1941218e401dbf956a03dd7472d1e599e6a09e3e6886b3810f1f398392509081900360600190a25050505050565b6040516000906001600160e01b03198235169033906000805160206130e483398151915290610e7b9085903690612f80565b60405180910390a36000610e8d61282d565b9050600080610e9b8561227c565b91509150676765c793fa10079d601b1b8203610eca5760405163a1455f9f60e01b815260040160405180910390fd5b6001600160a01b038516600090815260208181526040808320600181018054908590559151938452929091606089901b6001600160601b0319169162185c9d60ea1b91600080516020613104833981519152910160405180910390a36000610f32868361302b565b90508160056000828254610f469190612fef565b9091555050600554604051908152631d185c9d60e21b906000805160206130c48339815191529060200160405180910390a28060026000828254610f8a9190613002565b90915550506002546040519081526239b4b760e91b906000805160206130c48339815191529060200160405180910390a26000611029867f00000000000000000000000000000000000000000000000000000000000000017f00000000000000000000000000000000000000000cecb8f27f4200f3a00000007ffffffffffffffffffffffffffffffffffffffffff64e754a208e7f49480000006129aa565b9050600061104b611045676765c793fa10079d601b1b88612fdb565b836129f5565b9050600061108d7f000000000000000000000000000000000000000003648a260e3486a65a000000611088676765c793fa10079d601b1b87612fdb565b6129f5565b9050808211156110ba57855482906110a690839061302b565b6110b09190612fdb565b99508091506110bf565b855499505b600082600160008282546110d39190613002565b9182905550604051818152909250626a6f7960e81b91506000805160206130c48339815191529060200160405180910390a286548b900380885560405181815260608e901b6001600160601b0319169062696e6b60e81b906000805160206131048339815191529060200160405180910390a350604051632770a7eb60e21b81526001600160a01b037f0000000000000000000000004526e1f56a48f67c139cf9d37a34eaa5cd96d5661690639dc29fac906111959033908790600401612f67565b600060405180830381600087803b1580156111af57600080fd5b505af11580156111c3573d6000803e3d6000fd5b50506040516340c10f1960e01b81526001600160a01b037f000000000000000000000000db8925962aebcefd33f2985836402458125949971692506340c10f1991506112159033908f90600401612f67565b600060405180830381600087803b15801561122f57600080fd5b505af1158015611243573d6000803e3d6000fd5b5050505050505050505050505050919050565b6000356001600160e01b0319166001600160e01b031916336001600160a01b03166000805160206130e4833981519152600036604051611297929190612f80565b60405180910390a3336000908152602081905260408120906112b761282d565b905060006112c9836001015485612a33565b600184018190556040518181529091503360601b6001600160601b0319169062185c9d60ea1b906000805160206131048339815191529060200160405180910390a361131760055485612a33565b6005819055604051908152631d185c9d60e21b906000805160206130c48339815191529060200160405180910390a26000806113538487612a98565b90506000811315611456576000611375676765c793fa10079d601b1b83612fdb565b905061138c676765c793fa10079d601b1b83613042565b6003600082825461139d9190613002565b9182905550604051818152909450631c995cdd60e21b91506000805160206130c48339815191529060200160405180910390a26040516340c10f1960e01b81526001600160a01b037f0000000000000000000000004526e1f56a48f67c139cf9d37a34eaa5cd96d56616906340c10f199061141e9033908590600401612f67565b600060405180830381600087803b15801561143857600080fd5b505af115801561144c573d6000803e3d6000fd5b5050505050611571565b6000811215611571576000676765c793fa10079d601b1b61147683613056565b6114809190612fdb565b61148b906001613002565b90506114ab6114a5676765c793fa10079d601b1b8361302b565b83612a33565b600360008282546114bc9190613002565b9182905550604051818152909450631c995cdd60e21b91506000805160206130c48339815191529060200160405180910390a2604051632770a7eb60e21b81526001600160a01b037f0000000000000000000000004526e1f56a48f67c139cf9d37a34eaa5cd96d5661690639dc29fac9061153d9033908590600401612f67565b600060405180830381600087803b15801561155757600080fd5b505af115801561156b573d6000803e3d6000fd5b50505050505b6000611581866000015489612a33565b8087556040518181529091503360601b6001600160601b0319169062696e6b60e81b906000805160206131048339815191529060200160405180910390a3600088131561164d57604051632770a7eb60e21b81526001600160a01b037f000000000000000000000000db8925962aebcefd33f2985836402458125949971690639dc29fac906116169033908c90600401612f67565b600060405180830381600087803b15801561163057600080fd5b505af1158015611644573d6000803e3d6000fd5b505050506116df565b60008812156116df576001600160a01b037f000000000000000000000000db8925962aebcefd33f298583640245812594997166340c10f193361168f8b613056565b6040518363ffffffff1660e01b81526004016116ac929190612f67565b600060405180830381600087803b1580156116c657600080fd5b505af11580156116da573d6000803e3d6000fd5b505050505b60008812806116ee5750600087135b1561172f5760006116fe3361227c565b509050676765c793fa10079d601b1b81101561172d57604051637cae106b60e11b815260040160405180910390fd5b505b83158015906117695750611765600b547f0000000000000000000000000000000000000000000000056bc75e2d631000006129f5565b8654105b156117875760405163a51f35b160e01b815260040160405180910390fd5b5050505050505050565b6000356001600160e01b0319166001600160e01b031916336001600160a01b03166000805160206130e48339815191526000366040516117d2929190612f80565b60405180910390a360006118067f000000000000000000000000000000000000000000000000000000000000025842612fdb565b9050600d54811161182a57604051630314cff360e51b815260040160405180910390fd5b6118567f00000000000000000000000000000000000000000000000000000000018e5f436121c0613002565b43101561187657604051634045a93560e11b815260040160405180910390fd5b6000806000806060806000600d541115611c5a57600d546000908152601160205260408120600e5490917f0000000000000000000000000000000000000000000000000000000000000258919060646118d0602182612fef565b6118da908461302b565b6118e49190612fdb565b905060006118f28284612fef565b855490915060009015611c225760007f0000000000000000000000000000000000000000000000000000000000000258600d5460016119319190613002565b61193b919061302b565b90508087600189805490506119509190612fef565b8154811061196057611960613015565b60009182526020909120600260039092020101558654879061198490600190612fef565b8154811061199457611994613015565b600091825260209091206003909102015487546001600160a01b039091169d5067ffffffffffffffff8111156119cc576119cc613072565b6040519080825280602002602001820160405280156119f5578160200160208202803683370190505b50875490995067ffffffffffffffff811115611a1357611a13613072565b604051908082528060200260200182016040528015611a3c578160200160208202803683370190505b50975060005b8754811015611b89576000888281548110611a5f57611a5f613015565b6000918252602080832060408051606081018252600390940290910180546001600160a01b03168452600181015492840183905260020154908301819052919350611aa991612fef565b9050600089611ab8838a61302b565b611ac29190612fdb565b90508015611b7e5782600001518d8581518110611ae157611ae1613015565b60200260200101906001600160a01b031690816001600160a01b031681525050808c8581518110611b1457611b14613015565b6020908102919091010152611b298187613002565b955082600001516001600160a01b03167fb1ac1931f981158c0ae87d8afae53e019589f7599ee85330037f8697fa3dff0182600d54604051611b75929190918252602082015260400190565b60405180910390a25b505050600101611a42565b50611b948285612fef565b9a50600083118015611bae57506001600160a01b038d1615155b15611c0957829b508c6001600160a01b03167fb1ac1931f981158c0ae87d8afae53e019589f7599ee85330037f8697fa3dff0184600d54604051611bfc929190918252602082015260400190565b60405180910390a2611c1c565b8215611c1c57611c19838c613002565b9a505b50611c26565b8398505b6000611c328a8c613002565b90508015611c525780600b6000828254611c4c9190612fef565b90915550505b505050505050505b6000600a5442611c6a9190612fef565b9050611c996009547f0000000000000000000000000000000000000000033b2e22b63b5cca5b48000083612b1b565b60098190556040519081526233b4b360e91b906000805160206130c48339815191529060200160405180910390a242600a8190556040519081526263686960e81b906000805160206130c48339815191529060200160405180910390a27f0000000000000000000000000000000000000000000000000000000000000258611d43600b547f00000000000000000000000000000000000000000000000007b3c18f3a5780006129f5565b600954611d509190613002565b611d5a919061302b565b600e819055600b8054600090611d71908490613002565b9091555050600b54604051908152621dd85b60ea1b906000805160206130c48339815191529060200160405180910390a27f0000000000000000000000004526e1f56a48f67c139cf9d37a34eaa5cd96d5666001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e249190613088565b600f55600d8890556000888152601160205260408120611e4391612e74565b600088815260126020908152604080832080546001600160a01b03191690556013825280832092909255600d5491519182526b0c6eae4e4cadce88ae0dec6d60a31b916000805160206130c4833981519152910160405180910390a2600e5415611f2957600e546040516340c10f1960e01b81526001600160a01b037f000000000000000000000000db8925962aebcefd33f29858364024581259499716916340c10f1991611ef6913091600401612f67565b600060405180830381600087803b158015611f1057600080fd5b505af1158015611f24573d6000803e3d6000fd5b505050505b6000611f358587613002565b90508015611fbe57604051632770a7eb60e21b81526001600160a01b037f000000000000000000000000db8925962aebcefd33f2985836402458125949971690639dc29fac90611f8b9030908590600401612f67565b600060405180830381600087803b158015611fa557600080fd5b505af1158015611fb9573d6000803e3d6000fd5b505050505b60005b84518110156120b9576000848281518110611fde57611fde613015565b602002602001015111156120b1577f000000000000000000000000db8925962aebcefd33f2985836402458125949976001600160a01b031663a9059cbb86838151811061202d5761202d613015565b602002602001015186848151811061204757612047613015565b60200260200101516040518363ffffffff1660e01b815260040161206c929190612f67565b6020604051808303816000875af115801561208b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120af91906130a1565b505b600101611fc1565b5086156121535760405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000db8925962aebcefd33f298583640245812594997169063a9059cbb9061210e908b908b90600401612f67565b6020604051808303816000875af115801561212d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061215191906130a1565b505b505050505050505050565b600d5460009061218e7f000000000000000000000000000000000000000000000000000000000000025842612fdb565b14905090565b6000808080808080806121c77f000000000000000000000000000000000000000000000000000000000000025842612fdb565b97506121f37f00000000000000000000000000000000000000000000000000000000000002588961302b565b965061221f7f000000000000000000000000000000000000000000000000000000000000025888613002565b955042861161222f576000612239565b6122394287612fef565b600e5460008a815260126020908152604080832054601390925290912054600d549b9c9a9b999a93999298506001600160a01b03909116965094508a1492509050565b6001600160a01b038116600090815260208190526040812080546004546006548493929184916122ac91906129f5565b83600101546122bb919061302b565b90506000676765c793fa10079d601b1b6123006122da856004546129f5565b7f000000000000000000000000000000000000000003648a260e3486a65a000000612b47565b61230a919061302b565b905080821161232457676765c793fa10079d601b1b612361565b61236161233c676765c793fa10079d601b1b84612fdb565b6123469083612fdb565b61235c6001676765c793fa10079d601b1b612fef565b612b5f565b9550612378676765c793fa10079d601b1b8461302b565b945050505050915091565b6000356001600160e01b0319166001600160e01b031916336001600160a01b03166000805160206130e48339815191526000366040516123c4929190612f80565b60405180910390a36123d461282d565b506001546002546000906123f490676765c793fa10079d601b1b90612fdb565b6008549091506000199060009061240b9042612fef565b905060008385111561269f5760018411156124365761243361242e600186612fef565b612b76565b94505b6124917f0000000000000000000000000000000000000000000000000000000000000171600454612467919061302b565b6110887f0000000000000000000000000000000000000000033adcebf14bd76ef800000085612c0c565b92507f00000000000000000000000000000000000000000000000000000000000001716004546124c19190612fdb565b8310156124cd57600092505b60006125036124dd600188612fef565b7f0000000000000000000000000000000000000000019d971e4fe8401e740000006129f5565b9050801561269d5760019150600061251b82866129f5565b90506125278288612fef565b6001819055604051818152909750626a6f7960e81b906000805160206130c48339815191529060200160405180910390a26040516340c10f1960e01b81526001600160a01b037f0000000000000000000000004526e1f56a48f67c139cf9d37a34eaa5cd96d56616906340c10f19906125a69033908690600401612f67565b600060405180830381600087803b1580156125c057600080fd5b505af11580156125d4573d6000803e3d6000fd5b5050604051632770a7eb60e21b81526001600160a01b037f000000000000000000000000db8925962aebcefd33f298583640245812594997169250639dc29fac91506126269033908590600401612f67565b600060405180830381600087803b15801561264057600080fd5b505af1158015612654573d6000803e3d6000fd5b5050505080600b600082825461266a9190612fef565b9091555050600b54604051908152621dd85b60ea1b906000805160206130c48339815191529060200160405180910390a2505b505b4260088190556040519081526218995b60ea1b906000805160206130c48339815191529060200160405180910390a280806126da5750838511155b156126e9576126e98383612cfe565b5050505050565b6000808061271e7f000000000000000000000000000000000000000000000000000000000000025842612fdb565b6000908152601260209081526040808320546013909252909120546001600160a01b0390911694909350915050565b60006127797f000000000000000000000000000000000000000000000000000000000000025842612fdb565b905090565b6000807f00000000000000000000000000000000000000000000000000000000000002586127ac8142612fdb565b6127b7906001613002565b6127c1919061302b565b90504281116127d15760006127db565b6127db4282612fef565b91505090565b601160205281600052604060002081815481106127fd57600080fd5b60009182526020909120600390910201805460018201546002909201546001600160a01b03909116935090915083565b6000600754420361283f575060065490565b60065460075461287c9082907f0000000000000000000000000000000000000000033b2e3cab86fdc4266e0000906128779042612fef565b612b1b565b9150600061288a8284612fef565b905060008160055461289c919061302b565b90506000816003546128ae9190613002565b4260078190556040519081529091506272686f60e81b906000805160206130c48339815191529060200160405180910390a26006859055604051858152637261636b60e01b906000805160206130c48339815191529060200160405180910390a2612924676765c793fa10079d601b1b82613042565b6003819055604051908152631c995cdd60e21b906000805160206130c48339815191529060200160405180910390a2612968676765c793fa10079d601b1b82612fdb565b6001546129759190613002565b6001819055604051908152626a6f7960e81b906000805160206130c48339815191529060200160405180910390a25050505090565b60006129ba836110888787612c0c565b90506000821280156129d35750806129d183613056565b115b156129e0575060006129ed565b6129ea8183612a33565b90505b949350505050565b6000676765c793fa10079d601b1b612a0e600282612fdb565b612a18848661302b565b612a229190613002565b612a2c9190612fdb565b9392505050565b818101600082138015612a465750828111155b15612a645760405163cdc2bcd760e01b815260040160405180910390fd5b600082128015612a745750828110155b15612a925760405163259981cf60e21b815260040160405180910390fd5b92915050565b8181026000831215612abd57604051638f71065f60e01b815260040160405180910390fd5b8115801590612adb575082828281612ad757612ad7612faf565b0514155b15612a92576000821315612b0257604051638f71065f60e01b815260040160405180910390fd5b60405163b80fa08560e01b815260040160405180910390fd5b6000676765c793fa10079d601b1b612b338484612c0c565b612b3d908661302b565b6129ed9190612fdb565b600081612a22676765c793fa10079d601b1b8561302b565b600081831115612b6f5781612a2c565b5090919050565b6000612b8d676765c793fa10079d601b1b8361302b565b600254612b9a9190612fef565b60028190556040519081526239b4b760e91b906000805160206130c48339815191529060200160405180910390a281600154612bd69190612fef565b6001819055604051818152909150626a6f7960e81b906000805160206130c48339815191529060200160405180910390a2919050565b6000818015612ce857838015612cdd57600184168015612c2e57859350612c3d565b676765c793fa10079d601b1b93505b506002909304926b019d971e4fe8401e740000005b8415612cd7578586028660801c15612c6957600080fd5b81810181811015612c7957600080fd5b676765c793fa10079d601b1b90049650506001851615612ccc578584028487820414158715151615612caa57600080fd5b81810181811015612cba57600080fd5b676765c793fa10079d601b1b90049450505b600285049450612c52565b50612ce2565b600092505b50612cf7565b676765c793fa10079d601b1b91505b5092915050565b80600003612d0a575050565b600454600c54612d1b828285612b1b565b6004819055604051818152909250623830b960e91b906000805160206130c48339815191529060200160405180910390a281841015612daa57612da37f0000000000000000000000000000000000000000033b2e3dd0b59ed5fb55000061235c837f0000000000000000000000000000000000000000033b2e3c9fd0cfce3a94df6e87612b1b565b9050612e19565b81841115612e1957612e16612dde7f0000000000000000000000000000000000000000033b2e3dd0b59ed5fb550000612e4d565b612e1183612e0b7f0000000000000000000000000000000000000000033b2e3c9fd0cfce3a94df6e612e4d565b87612b1b565b612e64565b90505b600c8190556040518181526277617960e81b906000805160206130c48339815191529060200160405180910390a250505050565b6000612a92676765c793fa10079d601b1b83612b47565b600081831015612b6f5781612a2c565b5080546000825560030290600052602060002090810190612e959190612e98565b50565b5b80821115612ec55780546001600160a01b03191681556000600182018190556002820155600301612e99565b5090565b80356001600160a01b0381168114612ee057600080fd5b919050565b600060208284031215612ef757600080fd5b612a2c82612ec9565b600060208284031215612f1257600080fd5b5035919050565b60008060408385031215612f2c57600080fd5b50508035926020909101359150565b60008060408385031215612f4e57600080fd5b82359150612f5e60208401612ec9565b90509250929050565b6001600160a01b03929092168252602082015260400190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082612fea57612fea612faf565b500490565b81810381811115612a9257612a92612fc5565b80820180821115612a9257612a92612fc5565b634e487b7160e01b600052603260045260246000fd5b8082028115828204841417612a9257612a92612fc5565b60008261305157613051612faf565b500690565b6000600160ff1b820161306b5761306b612fc5565b5060000390565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561309a57600080fd5b5051919050565b6000602082840312156130b357600080fd5b81518015158114612a2c57600080fdfe16e9c051056ea742d289d2cb753372cf432f332213ecd495b26ea8f72e3cf2e0c8b2a2dbd2bddf4ecc3e665d9828132a78820abf89df014d2ce4510f27a16061a6a62c84c48e7b9441c54da7ead6df8213afddbc24649e1f6b88294160ef069fa2646970667358221220cde81c166f3d191855f21a8dc72c5ec028c8970b7c1ae66f060beb735a25c37b64736f6c634300081c0033