Contract 0x16e25cf364cecc305590128335b8f327975d0560 13

 

Contract Overview

Balance:
0 ETH

ETH Value:
$0.00

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x53707a18a5a1954be986bc6ab29162b5a3932905f5f2a285b6d0d853fcf0a5a1Batch1953705052024-03-29 8:02:269 mins ago0xaa5d93e233674aae3ac25d289f32af8e49c1aed7 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000629 0.01
0x44c1274b21f5b9157c982657c6aae9f3ed1c1c1b27aa7b89376bd5042cbfad38Batch1953668132024-03-29 7:47:0425 mins ago0x0756ef58d1125e82eaa823364fa0b3862caccabe IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000552 0.01
0x6d1e3bac918d0f69155d53f5babeb23a56701d4adaf38169ce07b5bbfb2064d6Batch1953662642024-03-29 7:44:4727 mins ago0x134eca36dfbe3d480d822d18e33c300924136710 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000567 0.010894
0x8e8fb0d4cc618f192ef4da491336ec965f1fdfe2206d2f6a7da4051bc8ca478fBatch1953366022024-03-29 5:40:462 hrs 31 mins ago0xff824db1c87c2653db979e4bac62d50f9e802e4d IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000547 0.01
0xa8a4eae2a9610714c3ff4db5dacdc39885c47adae3c86a128d019d6b8e5f402eBatch1953363792024-03-29 5:39:492 hrs 32 mins ago0x334a46a6a166f3fa743058f6e7f9a5a3f953ce6e IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000544 0.01
0x35d064ec7fa728d27bdfead595113825538d7cbf7309e2769c359d244d84f618Batch1953127882024-03-29 4:00:434 hrs 11 mins ago0xd0bad26b5cd2b1aa8baf6f283109153e72c53e53 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000933 0.01
0x1cca9c1f8342b444645cd0a791fdfebfea69a103d77bde68edbbda8901c4fde9Batch1953111682024-03-29 3:53:574 hrs 18 mins ago0x3255df9d5706784bdbb3bbb1f02452909b10d5eb IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00001476 0.01
0xa269fbe7aa4c6a439d65500a67ac5f7c0277a3e3bc078734e56814563f722313Batch1953106832024-03-29 3:51:564 hrs 20 mins ago0x5631117f55ac3866ca22173d57f6db40b2fe96b2 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00002254 0.01
0x4f28e09d4776f62c70b6094c000a9c590fb3c229a4791bb793d6fb3ee8cc13c2Batch1953103722024-03-29 3:50:384 hrs 21 mins ago0x402e316405c7a43e424bf3126eed65949f4acf2a IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00002264 0.01
0xa554c4de3a304f899104a1a8df15cd65fe7a354e225771e82099747539350e43Batch1953099992024-03-29 3:49:054 hrs 23 mins ago0xf78c85d0bde9af8ff52584eebf75655e3e784168 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00002294 0.01
0x55df95ade6b342f8682d4df9a514e9a813cceafa90443bc001c34868ad10fd8cBatch1953089952024-03-29 3:44:554 hrs 27 mins ago0x78cff23567b518c274280f9767b8bfe358cdd9d0 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00002862 0.01
0x4f18b1af9dc94f7d408ba39b06abd885ac87b7d1641ebc47cc16e6fa442c8426Batch1953047722024-03-29 3:27:184 hrs 45 mins ago0x8f663d59ce781b8d13757a28d5282d7309790b7e IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00001807 0.01
0x7dc8939e338d54f35146002cba08935b9e6fb41a5cc77be58af7600a51f4d23dBatch1952187062024-03-28 21:25:3710 hrs 46 mins ago0xcd5f282fcec89eda841cc007acaf0c8973e8e0e0 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.000003990.01
0xc84b44093cd2d8f37e95a5fa2cad211cb244d8b3dddf5a118c794a5678c79eacBatch1951350182024-03-28 15:33:0516 hrs 39 mins ago0xd859beadaefe26857b9102430a831d6ef309ed15 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.000013530.01
0x7459099228cd5f2a70debf25062bfe7192d38c8418e4480192a544daf564b444Batch1951205532024-03-28 14:31:5317 hrs 40 mins ago0xe62bcf78a4b157b10969720a44d6438c7ad99f5c IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00001151 0.01
0xee014db917787a7300c854a3d8a247ad3328cfbaab780ad71677144bd3621918Batch1951203842024-03-28 14:31:1117 hrs 41 mins ago0xe62bcf78a4b157b10969720a44d6438c7ad99f5c IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.0000147 0.01
0x83540030531200d92244f7a6fbcf315af29bf899590004f667644c5710b615bcBatch1950776132024-03-28 11:32:3020 hrs 39 mins ago0x76ac46b712a6c0bbe52e3dcf17aae495284b994c IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.000009160.01
0x2859ae0d302a0160f00ce480bf48b9900bdead8d255546dac52837dfabaebbd9Batch1950220132024-03-28 7:40:241 day 32 mins ago0xd7e124a5fabaeeaf0712bc18274dfee1d9cf4263 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00001015 0.01
0x063cf5ec3b2edbc32022fbe2c7df4fb28c752ee81412fb68a5a67d6aaae880d0Batch1950214062024-03-28 7:37:521 day 34 mins ago0xd7e124a5fabaeeaf0712bc18274dfee1d9cf4263 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00001321 0.01
0x7830bb57762c986f27b172864725f4742b78ad212d78185a88aa79f7444bf1caBatch1949746342024-03-28 4:22:431 day 3 hrs ago0x9cc2eb8801f102df5a28a56a3701e3d5dbf22a7c IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000476 0.01
0xa46ba642ca125eb2a3135b41c6809350ae18d367db158dbb8bca5c8fa4721df9Batch1948775292024-03-27 21:36:001 day 10 hrs ago0x84323c7139af855de059dc08eb4a9a1c94f2b42b IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00002023 0.01
0x4e1ff58465667df6516c0b585704b69fc2c06d86be8ceabbd7628cbd68a29ad3Batch1947503812024-03-27 12:43:251 day 19 hrs ago0x000006eee6e39015cb523aebdd4d0b1855aba682 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000365 0.01
0x98de32cf41aa7493afe42967b4305cfb94529d3538ff19d1bd3db04214255a65Batch1947500982024-03-27 12:42:151 day 19 hrs ago0x000006eee6e39015cb523aebdd4d0b1855aba682 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000569 0.01
0xc50057bb93d4519e9ab22f3b5f2f11564223834188ce6a7e794546ebc105bf81Batch1946908752024-03-27 8:34:561 day 23 hrs ago0x01dba2e22135d01022a22ce975f3e9705485e395 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000582 0.01
0xc02cc88504f57aa908681937fa8ef4b284297c8740e0420d8d1a497f41791cd0Batch1945561352024-03-26 23:11:272 days 9 hrs ago0xe9894efe9ff0d3eb166042bc6eeaf11f7f992843 IN  0x16e25cf364cecc305590128335b8f327975d05600 ETH0.00000472 0.01
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x83540030531200d92244f7a6fbcf315af29bf899590004f667644c5710b615bc1950776132024-03-28 11:32:3020 hrs 39 mins ago 0x16e25cf364cecc305590128335b8f327975d05600x76ac46b712a6c0bbe52e3dcf17aae495284b994c0.001999413184013053 ETH
0x83540030531200d92244f7a6fbcf315af29bf899590004f667644c5710b615bc1950776132024-03-28 11:32:3020 hrs 39 mins ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.001999413184013053 ETH
0xc50057bb93d4519e9ab22f3b5f2f11564223834188ce6a7e794546ebc105bf811946908752024-03-27 8:34:561 day 23 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600x01dba2e22135d01022a22ce975f3e9705485e3950.033110918271805881 ETH
0xc50057bb93d4519e9ab22f3b5f2f11564223834188ce6a7e794546ebc105bf811946908752024-03-27 8:34:561 day 23 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.033110918271805881 ETH
0xc02cc88504f57aa908681937fa8ef4b284297c8740e0420d8d1a497f41791cd01945561352024-03-26 23:11:272 days 9 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600xe9894efe9ff0d3eb166042bc6eeaf11f7f9928430.000765735060472551 ETH
0xc02cc88504f57aa908681937fa8ef4b284297c8740e0420d8d1a497f41791cd01945561352024-03-26 23:11:272 days 9 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.000765735060472551 ETH
0x051cac16cfcab5211e95fb44d4a5b7f5398154124c4d8e6bbb5c2e73b221e5bc1941217442024-03-25 17:00:203 days 15 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600xfe01c1a253443b13ab76b4f591b53f2c2d4c0ad40.001000030905056429 ETH
0x051cac16cfcab5211e95fb44d4a5b7f5398154124c4d8e6bbb5c2e73b221e5bc1941217442024-03-25 17:00:203 days 15 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.001000030905056429 ETH
0x3a60e1199a5ba24784f71b506a2a1abf5cef370f3e0a400db9d0e3d5820ccbe11938200682024-03-24 20:00:444 days 12 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600x133532e13cfc015afa1da59b349f7d92420ca3db0.015010654669841171 ETH
0x3a60e1199a5ba24784f71b506a2a1abf5cef370f3e0a400db9d0e3d5820ccbe11938200682024-03-24 20:00:444 days 12 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.015010654669841171 ETH
0x48af84c3ee258a737da8625cac11bdef5b4d41a5f570be4f4a93d67e5ae43e211937716292024-03-24 16:38:154 days 15 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600xe9b8eab75b5f26db708a93e2a174cb2820d16dfa0.073377560108510778 ETH
0x48af84c3ee258a737da8625cac11bdef5b4d41a5f570be4f4a93d67e5ae43e211937716292024-03-24 16:38:154 days 15 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.073377560108510778 ETH
0xe6bbe7121c54414e6a0de61866865fff845782cee0dea4a7f2a0fc1b870046811937680872024-03-24 16:23:274 days 15 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600xe9b8eab75b5f26db708a93e2a174cb2820d16dfa0.219204944256076929 ETH
0xe6bbe7121c54414e6a0de61866865fff845782cee0dea4a7f2a0fc1b870046811937680872024-03-24 16:23:274 days 15 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.219204944256076929 ETH
0x4915bd2588b1d5b8773e00a3c4bb20f99f6f2af33fc3155620eb1c8a8931f1a41935281222024-03-23 23:42:265 days 8 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600x89f42ccb1b90103a4b886cc8ee019794928080790.128417868944389809 ETH
0x4915bd2588b1d5b8773e00a3c4bb20f99f6f2af33fc3155620eb1c8a8931f1a41935281222024-03-23 23:42:265 days 8 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.128417868944389809 ETH
0x7cf7247f000fa1a6cac288503609878a29d7b8744d4513a450845544e9b8ea351933920752024-03-23 14:12:025 days 18 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600xef8dfc3a17debbea4f7ed5d512043fb9afbca8b90.03002466121798018 ETH
0x7cf7247f000fa1a6cac288503609878a29d7b8744d4513a450845544e9b8ea351933920752024-03-23 14:12:025 days 18 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.03002466121798018 ETH
0xf9e4872599771c310080ce31b81ac746dc10bc0fcdd35ae0a8725fb3521a846d1930084892024-03-22 11:30:226 days 20 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600xdf9de12f207c38df3ed166d9931b44a4ba9f36b90.010000253708200534 ETH
0xf9e4872599771c310080ce31b81ac746dc10bc0fcdd35ae0a8725fb3521a846d1930084892024-03-22 11:30:226 days 20 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.010000253708200534 ETH
0x95b4f8694ff03f31f8ff0f077e54ff20e9f0e1e17a2513716e7de942ec589bfa1929776392024-03-22 9:21:416 days 22 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600xb02c5eb954b95aae35cc32337cae4a6924c727da0.048963520506237172 ETH
0x95b4f8694ff03f31f8ff0f077e54ff20e9f0e1e17a2513716e7de942ec589bfa1929776392024-03-22 9:21:416 days 22 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.048963520506237172 ETH
0x341b3b22d2026c7af3fc95752ca899c56909a98703cc9136ac8c1c9bb6e83a221929764562024-03-22 9:16:456 days 22 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600xb02c5eb954b95aae35cc32337cae4a6924c727da0.151036479493762828 ETH
0x341b3b22d2026c7af3fc95752ca899c56909a98703cc9136ac8c1c9bb6e83a221929764562024-03-22 9:16:456 days 22 hrs ago Wrapped Ether 0x16e25cf364cecc305590128335b8f327975d05600.151036479493762828 ETH
0x99cb6801f4e2324b79f77cc18757c3c929a7568edd43667669c61444045153d61927895242024-03-21 20:13:217 days 11 hrs ago 0x16e25cf364cecc305590128335b8f327975d05600xc2e83a2a14092388920b133a53b9ff2b53dd6bf10.001000168148458884 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Ladle

Compiler Version
v0.8.6+commit.11564f7e

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion
File 1 of 21 : Ladle.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.6;
import "@yield-protocol/vault-interfaces/IFYToken.sol";
import "@yield-protocol/vault-interfaces/IJoin.sol";
import "@yield-protocol/vault-interfaces/ICauldron.sol";
import "@yield-protocol/vault-interfaces/IOracle.sol";
import "@yield-protocol/vault-interfaces/DataTypes.sol";
import "@yield-protocol/yieldspace-interfaces/IPool.sol";
import "@yield-protocol/utils-v2/contracts/token/IERC20.sol";
import "@yield-protocol/utils-v2/contracts/token/IERC2612.sol";
import "dss-interfaces/src/dss/DaiAbstract.sol";
import "@yield-protocol/utils-v2/contracts/access/AccessControl.sol";
import "@yield-protocol/utils-v2/contracts/token/TransferHelper.sol";
import "@yield-protocol/utils-v2/contracts/math/WMul.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU256U128.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU256I128.sol";
import "@yield-protocol/utils-v2/contracts/cast/CastU128I128.sol";
import "./LadleStorage.sol";


/// @dev Ladle orchestrates contract calls throughout the Yield Protocol v2 into useful and efficient user oriented features.
contract Ladle is LadleStorage, AccessControl() {
    using WMul for uint256;
    using CastU256U128 for uint256;
    using CastU256I128 for uint256;
    using CastU128I128 for uint128;
    using TransferHelper for IERC20;
    using TransferHelper for address payable;

    constructor (ICauldron cauldron, IWETH9 weth) LadleStorage(cauldron, weth) { }

    // ---- Data sourcing ----
    /// @dev Obtains a vault by vaultId from the Cauldron, and verifies that msg.sender is the owner
    /// If bytes(0) is passed as the vaultId it tries to load a vault from the cache
    function getVault(bytes12 vaultId_)
        internal view
        returns (bytes12 vaultId, DataTypes.Vault memory vault)
    {
        if (vaultId_ == bytes12(0)) { // We use the cache
            require (cachedVaultId != bytes12(0), "Vault not cached");
            vaultId = cachedVaultId;
        } else {
            vaultId = vaultId_;
        }
        vault = cauldron.vaults(vaultId);
        require (vault.owner == msg.sender, "Only vault owner");
    } 
    /// @dev Obtains a series by seriesId from the Cauldron, and verifies that it exists
    function getSeries(bytes6 seriesId)
        internal view returns(DataTypes.Series memory series)
    {
        series = cauldron.series(seriesId);
        require (series.fyToken != IFYToken(address(0)), "Series not found");
    }

    /// @dev Obtains a join by assetId, and verifies that it exists
    function getJoin(bytes6 assetId)
        internal view returns(IJoin join)
    {
        join = joins[assetId];
        require (join != IJoin(address(0)), "Join not found");
    }

    /// @dev Obtains a pool by seriesId, and verifies that it exists
    function getPool(bytes6 seriesId)
        internal view returns(IPool pool)
    {
        pool = pools[seriesId];
        require (pool != IPool(address(0)), "Pool not found");
    }

    // ---- Administration ----

    /// @dev Add or remove an integration.
    function addIntegration(address integration, bool set)
        external
        auth
    {
        _addIntegration(integration, set);
    }

    /// @dev Add or remove an integration.
    function _addIntegration(address integration, bool set)
        private
    {
        integrations[integration] = set;
        emit IntegrationAdded(integration, set);
    }

    /// @dev Add or remove a token that the Ladle can call `transfer` or `permit` on.
    function addToken(address token, bool set)
        external
        auth
    {
        _addToken(token, set);
    }
    

    /// @dev Add or remove a token that the Ladle can call `transfer` or `permit` on.
    function _addToken(address token, bool set)
        private
    {
        tokens[token] = set;
        emit TokenAdded(token, set);
    }


    /// @dev Add a new Join for an Asset, or replace an existing one for a new one.
    /// There can be only one Join per Asset. Until a Join is added, no tokens of that Asset can be posted or withdrawn.
    function addJoin(bytes6 assetId, IJoin join)
        external
        auth
    {
        address asset = cauldron.assets(assetId);
        require (asset != address(0), "Asset not found");
        require (join.asset() == asset, "Mismatched asset and join");
        joins[assetId] = join;

        bool set = (join != IJoin(address(0))) ? true : false;
        _addToken(asset, set);                  // address(0) disables the token
        emit JoinAdded(assetId, address(join));
    }

    /// @dev Add a new Pool for a Series, or replace an existing one for a new one.
    /// There can be only one Pool per Series. Until a Pool is added, it is not possible to borrow Base.
    function addPool(bytes6 seriesId, IPool pool)
        external
        auth
    {
        IFYToken fyToken = getSeries(seriesId).fyToken;
        require (fyToken == pool.fyToken(), "Mismatched pool fyToken and series");
        require (fyToken.underlying() == address(pool.base()), "Mismatched pool base and series");
        pools[seriesId] = pool;

        bool set = (pool != IPool(address(0))) ? true : false;
        _addToken(address(fyToken), set);       // address(0) disables the token
        _addToken(address(pool), set);          // address(0) disables the token
        _addIntegration(address(pool), set);    // address(0) disables the integration

        emit PoolAdded(seriesId, address(pool));
    }

    /// @dev Add or remove a module.
    /// @notice Treat modules as you would Ladle upgrades. Modules have unrestricted access to the Ladle
    /// storage, and can wreak havoc easily.
    /// Modules must not do any changes to any vault (owner, seriesId, ilkId) because of vault caching.
    /// Modules must not be contracts that can self-destruct because of `moduleCall`.
    /// Modules can't use `msg.value` because of `batch`.
    function addModule(address module, bool set)
        external
        auth
    {
        modules[module] = set;
        emit ModuleAdded(module, set);
    }

    /// @dev Set the fee parameter
    function setFee(uint256 fee)
        external
        auth
    {
        borrowingFee = fee;
        emit FeeSet(fee);
    }

    // ---- Call management ----

    /// @dev Allows batched call to self (this contract).
    /// @param calls An array of inputs for each call.
    function batch(bytes[] calldata calls) external payable returns(bytes[] memory results) {
        results = new bytes[](calls.length);
        for (uint256 i; i < calls.length; i++) {
            (bool success, bytes memory result) = address(this).delegatecall(calls[i]);
            if (!success) revert(RevertMsgExtractor.getRevertMsg(result));
            results[i] = result;
        }

        // build would have populated the cache, this deletes it
        cachedVaultId = bytes12(0);
    }

    /// @dev Allow users to route calls to a contract, to be used with batch
    function route(address integration, bytes calldata data)
        external payable
        returns (bytes memory result)
    {
        require(integrations[integration], "Unknown integration");
        return router.route(integration, data);
    }

    /// @dev Allow users to use functionality coded in a module, to be used with batch
    function moduleCall(address module, bytes calldata data)
        external payable
        returns (bytes memory result)
    {
        require (modules[module], "Unregistered module");
        bool success;
        (success, result) = module.delegatecall(data);
        if (!success) revert(RevertMsgExtractor.getRevertMsg(result));
    }

    // ---- Token management ----

    /// @dev Execute an ERC2612 permit for the selected token
    function forwardPermit(IERC2612 token, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
        external payable
    {
        require(tokens[address(token)], "Unknown token");
        token.permit(msg.sender, spender, amount, deadline, v, r, s);
    }

    /// @dev Execute a Dai-style permit for the selected token
    function forwardDaiPermit(DaiAbstract token, address spender, uint256 nonce, uint256 deadline, bool allowed, uint8 v, bytes32 r, bytes32 s)
        external payable
    {
        require(tokens[address(token)], "Unknown token");
        token.permit(msg.sender, spender, nonce, deadline, allowed, v, r, s);
    }

    /// @dev Allow users to trigger a token transfer from themselves to a receiver through the ladle, to be used with batch
    function transfer(IERC20 token, address receiver, uint128 wad)
        external payable
    {
        require(tokens[address(token)], "Unknown token");
        token.safeTransferFrom(msg.sender, receiver, wad);
    }

    /// @dev Retrieve any token in the Ladle
    function retrieve(IERC20 token, address to) 
        external payable
        returns (uint256 amount)
    {
        require(tokens[address(token)], "Unknown token");
        amount = token.balanceOf(address(this));
        token.safeTransfer(to, amount);
    }

    /// @dev The WETH9 contract will send ether to BorrowProxy on `weth.withdraw` using this function.
    receive() external payable { 
        require (msg.sender == address(weth), "Only receive from WETH");
    }

    /// @dev Accept Ether, wrap it and forward it to the WethJoin
    /// This function should be called first in a batch, and the Join should keep track of stored reserves
    /// Passing the id for a join that doesn't link to a contract implemnting IWETH9 will fail
    function joinEther(bytes6 etherId)
        external payable
        returns (uint256 ethTransferred)
    {
        ethTransferred = address(this).balance;
        IJoin wethJoin = getJoin(etherId);
        weth.deposit{ value: ethTransferred }();
        IERC20(address(weth)).safeTransfer(address(wethJoin), ethTransferred);
    }

    /// @dev Unwrap Wrapped Ether held by this Ladle, and send the Ether
    /// This function should be called last in a batch, and the Ladle should have no reason to keep an WETH balance
    function exitEther(address payable to)
        external payable
        returns (uint256 ethTransferred)
    {
        ethTransferred = weth.balanceOf(address(this));
        weth.withdraw(ethTransferred);
        to.safeTransferETH(ethTransferred);
    }

    // ---- Vault management ----

    /// @dev Generate a vaultId. A keccak256 is cheaper than using a counter with a SSTORE, even accounting for eventual collision retries.
    function _generateVaultId(uint8 salt) private view returns (bytes12) {
        return bytes12(keccak256(abi.encodePacked(msg.sender, block.timestamp, salt)));
    }

    /// @dev Create a new vault, linked to a series (and therefore underlying) and a collateral
    function build(bytes6 seriesId, bytes6 ilkId, uint8 salt)
        external payable
        returns(bytes12, DataTypes.Vault memory)
    {
        return _build(seriesId, ilkId, salt);
    }

    /// @dev Create a new vault, linked to a series (and therefore underlying) and a collateral
    function _build(bytes6 seriesId, bytes6 ilkId, uint8 salt)
        private
        returns(bytes12 vaultId, DataTypes.Vault memory vault)
    {
        vaultId = _generateVaultId(salt);
        while (cauldron.vaults(vaultId).seriesId != bytes6(0)) vaultId = _generateVaultId(++salt); // If the vault exists, generate other random vaultId
        vault = cauldron.build(msg.sender, vaultId, seriesId, ilkId);
        // Store the vault data in the cache
        cachedVaultId = vaultId;
    }

    /// @dev Change a vault series or collateral.
    function tweak(bytes12 vaultId_, bytes6 seriesId, bytes6 ilkId)
        external payable
        returns(DataTypes.Vault memory vault)
    {
        (bytes12 vaultId, ) = getVault(vaultId_); // getVault verifies the ownership as well
        // tweak checks that the series and the collateral both exist and that the collateral is approved for the series
        vault = cauldron.tweak(vaultId, seriesId, ilkId);
    }

    /// @dev Give a vault to another user.
    function give(bytes12 vaultId_, address receiver)
        external payable
        returns(DataTypes.Vault memory vault)
    {
        (bytes12 vaultId, ) = getVault(vaultId_);
        vault = cauldron.give(vaultId, receiver);
    }

    /// @dev Destroy an empty vault. Used to recover gas costs.
    function destroy(bytes12 vaultId_)
        external payable
    {
        (bytes12 vaultId, ) = getVault(vaultId_);
        cauldron.destroy(vaultId);
    }

    // ---- Asset and debt management ----

    /// @dev Move collateral and debt between vaults.
    function stir(bytes12 from, bytes12 to, uint128 ink, uint128 art)
        external payable
    {
        if (ink > 0) require (cauldron.vaults(from).owner == msg.sender, "Only origin vault owner");
        if (art > 0) require (cauldron.vaults(to).owner == msg.sender, "Only destination vault owner");
        cauldron.stir(from, to, ink, art);
    }

    /// @dev Add collateral and borrow from vault, pull assets from and push borrowed asset to user
    /// Or, repay to vault and remove collateral, pull borrowed asset from and push assets to user
    /// Borrow only before maturity.
    function _pour(bytes12 vaultId, DataTypes.Vault memory vault, address to, int128 ink, int128 art)
        private
    {
        DataTypes.Series memory series;
        if (art != 0) series = getSeries(vault.seriesId);

        int128 fee;
        if (art > 0 && vault.ilkId != series.baseId && borrowingFee != 0)
            fee = ((series.maturity - block.timestamp) * uint256(int256(art)).wmul(borrowingFee)).i128();

        // Update accounting
        cauldron.pour(vaultId, ink, art + fee);

        // Manage collateral
        if (ink != 0) {
            IJoin ilkJoin = getJoin(vault.ilkId);
            if (ink > 0) ilkJoin.join(vault.owner, uint128(ink));
            if (ink < 0) ilkJoin.exit(to, uint128(-ink));
        }

        // Manage debt tokens
        if (art != 0) {
            if (art > 0) series.fyToken.mint(to, uint128(art));
            else series.fyToken.burn(msg.sender, uint128(-art));
        }
    }

    /// @dev Add collateral and borrow from vault, pull assets from and push borrowed asset to user
    /// Or, repay to vault and remove collateral, pull borrowed asset from and push assets to user
    /// Borrow only before maturity.
    function pour(bytes12 vaultId_, address to, int128 ink, int128 art)
        external payable
    {
        (bytes12 vaultId, DataTypes.Vault memory vault) = getVault(vaultId_);
        _pour(vaultId, vault, to, ink, art);
    }

    /// @dev Add collateral and borrow from vault, so that a precise amount of base is obtained by the user.
    /// The base is obtained by borrowing fyToken and buying base with it in a pool.
    /// Only before maturity.
    function serve(bytes12 vaultId_, address to, uint128 ink, uint128 base, uint128 max)
        external payable
        returns (uint128 art)
    {
        (bytes12 vaultId, DataTypes.Vault memory vault) = getVault(vaultId_);
        IPool pool = getPool(vault.seriesId);
        
        art = pool.buyBasePreview(base);
        _pour(vaultId, vault, address(pool), ink.i128(), art.i128());
        pool.buyBase(to, base, max);
    }

    /// @dev Repay vault debt using underlying token at a 1:1 exchange rate, without trading in a pool.
    /// It can add or remove collateral at the same time.
    /// The debt to repay is denominated in fyToken, even if the tokens pulled from the user are underlying.
    /// The debt to repay must be entered as a negative number, as with `pour`.
    /// Debt cannot be acquired with this function.
    function close(bytes12 vaultId_, address to, int128 ink, int128 art)
        external payable
        returns (uint128 base)
    {
        require (art < 0, "Only repay debt");                                          // When repaying debt in `frob`, art is a negative value. Here is the same for consistency.

        // Calculate debt in fyToken terms
        (bytes12 vaultId, DataTypes.Vault memory vault) = getVault(vaultId_);
        DataTypes.Series memory series = getSeries(vault.seriesId);
        base = cauldron.debtToBase(vault.seriesId, uint128(-art));

        // Update accounting
        cauldron.pour(vaultId, ink, art);

        // Manage collateral
        if (ink != 0) {
            IJoin ilkJoin = getJoin(vault.ilkId);
            if (ink > 0) ilkJoin.join(vault.owner, uint128(ink));
            if (ink < 0) ilkJoin.exit(to, uint128(-ink));
        }

        // Manage underlying
        IJoin baseJoin = getJoin(series.baseId);
        baseJoin.join(msg.sender, base);
    }

    /// @dev Repay debt by selling base in a pool and using the resulting fyToken
    /// The base tokens need to be already in the pool, unaccounted for.
    /// Only before maturity. After maturity use close.
    function repay(bytes12 vaultId_, address to, int128 ink, uint128 min)
        external payable
        returns (uint128 art)
    {
        (bytes12 vaultId, DataTypes.Vault memory vault) = getVault(vaultId_);
        DataTypes.Series memory series = getSeries(vault.seriesId);
        IPool pool = getPool(vault.seriesId);

        art = pool.sellBase(address(series.fyToken), min);
        _pour(vaultId, vault, to, ink, -(art.i128()));
    }

    /// @dev Repay all debt in a vault by buying fyToken from a pool with base.
    /// The base tokens need to be already in the pool, unaccounted for. The surplus base will be returned to msg.sender.
    /// Only before maturity. After maturity use close.
    function repayVault(bytes12 vaultId_, address to, int128 ink, uint128 max)
        external payable
        returns (uint128 base)
    {
        (bytes12 vaultId, DataTypes.Vault memory vault) = getVault(vaultId_);
        DataTypes.Series memory series = getSeries(vault.seriesId);
        IPool pool = getPool(vault.seriesId);

        DataTypes.Balances memory balances = cauldron.balances(vaultId);
        base = pool.buyFYToken(address(series.fyToken), balances.art, max);
        _pour(vaultId, vault, to, ink, -(balances.art.i128()));
        pool.retrieveBase(msg.sender);
    }

    /// @dev Change series and debt of a vault.
    function roll(bytes12 vaultId_, bytes6 newSeriesId, uint8 loan, uint128 max)
        external payable
        returns (DataTypes.Vault memory vault, uint128 newDebt)
    {
        bytes12 vaultId;
        (vaultId, vault) = getVault(vaultId_);
        DataTypes.Balances memory balances = cauldron.balances(vaultId);
        DataTypes.Series memory series = getSeries(vault.seriesId);
        DataTypes.Series memory newSeries = getSeries(newSeriesId);
        
        
        {
            IPool pool = getPool(newSeriesId);
            IFYToken fyToken = IFYToken(newSeries.fyToken);
            IJoin baseJoin = getJoin(series.baseId);

            // Calculate debt in fyToken terms
            uint128 base = cauldron.debtToBase(vault.seriesId, balances.art);

            // Mint fyToken to the pool, as a kind of flash loan
            fyToken.mint(address(pool), base * loan);                // Loan is the size of the flash loan relative to the debt amount, 2 should be safe most of the time

            // Buy the base required to pay off the debt in series 1, and find out the debt in series 2
            newDebt = pool.buyBase(address(baseJoin), base, max);
            baseJoin.join(address(baseJoin), base);                  // Repay the old series debt

            pool.retrieveFYToken(address(fyToken));                 // Get the surplus fyToken
            fyToken.burn(address(fyToken), (base * loan) - newDebt);    // Burn the surplus
        }

        if (vault.ilkId != newSeries.baseId && borrowingFee != 0)
            newDebt += ((newSeries.maturity - block.timestamp) * uint256(newDebt).wmul(borrowingFee)).u128();  // Add borrowing fee, also stops users form rolling to a mature series

        (vault,) = cauldron.roll(vaultId, newSeriesId, newDebt.i128() - balances.art.i128()); // Change the series and debt for the vault

        return (vault, newDebt);
    }

    // ---- Ladle as a token holder ----

    /// @dev Use fyToken in the Ladle to repay debt. Return unused fyToken to `to`.
    /// Return as much collateral as debt was repaid, as well. This function is only used when
    /// removing liquidity added with "Borrow and Pool", so it's safe to assume the exchange rate
    /// is 1:1. If used in other contexts, it might revert, which is fine.
    function repayFromLadle(bytes12 vaultId_, address to)
        external payable
        returns (uint256 repaid)
    {
        (bytes12 vaultId, DataTypes.Vault memory vault) = getVault(vaultId_);
        DataTypes.Series memory series = getSeries(vault.seriesId);
        DataTypes.Balances memory balances = cauldron.balances(vaultId);
        
        uint256 amount = series.fyToken.balanceOf(address(this));
        repaid = amount <= balances.art ? amount : balances.art;

        // Update accounting, burn fyToken and return collateral
        if (repaid > 0) {
            cauldron.pour(vaultId, -(repaid.i128()), -(repaid.i128()));
            series.fyToken.burn(address(this), repaid);
            IJoin ilkJoin = getJoin(vault.ilkId);
            ilkJoin.exit(to, repaid.u128());
        }

        // Return remainder
        if (amount - repaid > 0) IERC20(address(series.fyToken)).safeTransfer(to, amount - repaid);
    }

    /// @dev Use base in the Ladle to repay debt. Return unused base to `to`.
    /// Return as much collateral as debt was repaid, as well. This function is only used when
    /// removing liquidity added with "Borrow and Pool", so it's safe to assume the exchange rate
    /// is 1:1. If used in other contexts, it might revert, which is fine.
    function closeFromLadle(bytes12 vaultId_, address to)
        external payable
        returns (uint256 repaid)
    {
        (bytes12 vaultId, DataTypes.Vault memory vault) = getVault(vaultId_);
        DataTypes.Series memory series = getSeries(vault.seriesId);
        DataTypes.Balances memory balances = cauldron.balances(vaultId);
        
        IERC20 base = IERC20(cauldron.assets(series.baseId));
        uint256 amount = base.balanceOf(address(this));
        uint256 debtInBase = cauldron.debtToBase(vault.seriesId, balances.art);
        uint128 repaidInBase = ((amount <= debtInBase) ? amount : debtInBase).u128();
        repaid = (repaidInBase == debtInBase) ? balances.art : cauldron.debtFromBase(vault.seriesId, repaidInBase);

        // Update accounting, join base and return collateral
        if (repaidInBase > 0) {
            cauldron.pour(vaultId, -(repaid.i128()), -(repaid.i128()));
            IJoin baseJoin = getJoin(series.baseId);
            base.safeTransfer(address(baseJoin), repaidInBase);
            baseJoin.join(address(this), repaidInBase);
            IJoin ilkJoin = getJoin(vault.ilkId);
            ilkJoin.exit(to, repaid.u128()); // repaid is the ink collateral released, and equal to the fyToken debt. repaidInBase is the value of the fyToken debt in base terms
        }

        // Return remainder
        if (amount - repaidInBase > 0) base.safeTransfer(to, amount - repaidInBase);
    }

    /// @dev Allow users to redeem fyToken, to be used with batch.
    /// If 0 is passed as the amount to redeem, it redeems the fyToken balance of the Ladle instead.
    function redeem(bytes6 seriesId, address to, uint256 wad)
        external payable
        returns (uint256)
    {
        IFYToken fyToken = getSeries(seriesId).fyToken;
        return fyToken.redeem(to, wad != 0 ? wad : fyToken.balanceOf(address(this)));
    }

}

File 2 of 21 : IFYToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@yield-protocol/utils-v2/contracts/token/IERC20.sol";


interface IFYToken is IERC20 {
    /// @dev Asset that is returned on redemption.
    function underlying() external view returns (address);

    /// @dev Unix time at which redemption of fyToken for underlying are possible
    function maturity() external view returns (uint256);
    
    /// @dev Record price data at maturity
    function mature() external;

    /// @dev Mint fyToken providing an equal amount of underlying to the protocol
    function mintWithUnderlying(address to, uint256 amount) external;

    /// @dev Burn fyToken after maturity for an amount of underlying.
    function redeem(address to, uint256 amount) external returns (uint256);

    /// @dev Mint fyToken.
    /// This function can only be called by other Yield contracts, not users directly.
    /// @param to Wallet to mint the fyToken in.
    /// @param fyTokenAmount Amount of fyToken to mint.
    function mint(address to, uint256 fyTokenAmount) external;

    /// @dev Burn fyToken.
    /// This function can only be called by other Yield contracts, not users directly.
    /// @param from Wallet to burn the fyToken from.
    /// @param fyTokenAmount Amount of fyToken to burn.
    function burn(address from, uint256 fyTokenAmount) external;
}

File 3 of 21 : IJoin.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@yield-protocol/utils-v2/contracts/token/IERC20.sol";


interface IJoin {
    /// @dev asset managed by this contract
    function asset() external view returns (address);

    /// @dev Add tokens to this contract.
    function join(address user, uint128 wad) external returns (uint128);

    /// @dev Remove tokens to this contract.
    function exit(address user, uint128 wad) external returns (uint128);
}

File 4 of 21 : ICauldron.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IFYToken.sol";
import "./IOracle.sol";
import "./DataTypes.sol";


interface ICauldron {

    /// @dev Variable rate lending oracle for an underlying
    function lendingOracles(bytes6 baseId) external view returns (IOracle);

    /// @dev An user can own one or more Vaults, with each vault being able to borrow from a single series.
    function vaults(bytes12 vault) external view returns (DataTypes.Vault memory);

    /// @dev Series available in Cauldron.
    function series(bytes6 seriesId) external view returns (DataTypes.Series memory);

    /// @dev Assets available in Cauldron.
    function assets(bytes6 assetsId) external view returns (address);

    /// @dev Each vault records debt and collateral balances_.
    function balances(bytes12 vault) external view returns (DataTypes.Balances memory);

    /// @dev Max, min and sum of debt per underlying and collateral.
    function debt(bytes6 baseId, bytes6 ilkId) external view returns (DataTypes.Debt memory);

    // @dev Spot price oracle addresses and collateralization ratios
    function spotOracles(bytes6 baseId, bytes6 ilkId) external returns (DataTypes.SpotOracle memory);

    /// @dev Create a new vault, linked to a series (and therefore underlying) and up to 5 collateral types
    function build(address owner, bytes12 vaultId, bytes6 seriesId, bytes6 ilkId) external returns (DataTypes.Vault memory);

    /// @dev Destroy an empty vault. Used to recover gas costs.
    function destroy(bytes12 vault) external;

    /// @dev Change a vault series and/or collateral types.
    function tweak(bytes12 vaultId, bytes6 seriesId, bytes6 ilkId) external returns (DataTypes.Vault memory);

    /// @dev Give a vault to another user.
    function give(bytes12 vaultId, address receiver) external returns (DataTypes.Vault memory);

    /// @dev Move collateral and debt between vaults.
    function stir(bytes12 from, bytes12 to, uint128 ink, uint128 art) external returns (DataTypes.Balances memory, DataTypes.Balances memory);

    /// @dev Manipulate a vault debt and collateral.
    function pour(bytes12 vaultId, int128 ink, int128 art) external returns (DataTypes.Balances memory);

    /// @dev Change series and debt of a vault.
    /// The module calling this function also needs to buy underlying in the pool for the new series, and sell it in pool for the old series.
    function roll(bytes12 vaultId, bytes6 seriesId, int128 art) external returns (DataTypes.Vault memory, DataTypes.Balances memory);

    /// @dev Reduce debt and collateral from a vault, ignoring collateralization checks.
    function slurp(bytes12 vaultId, uint128 ink, uint128 art) external returns (DataTypes.Balances memory);

    // ==== Helpers ====

    /// @dev Convert a debt amount for a series from base to fyToken terms.
    /// @notice Think about rounding if using, since we are dividing.
    function debtFromBase(bytes6 seriesId, uint128 base) external returns (uint128 art);

    /// @dev Convert a debt amount for a series from fyToken to base terms
    function debtToBase(bytes6 seriesId, uint128 art) external returns (uint128 base);

    // ==== Accounting ====

    /// @dev Record the borrowing rate at maturity for a series
    function mature(bytes6 seriesId) external;
    
    /// @dev Retrieve the rate accrual since maturity, maturing if necessary.
    function accrual(bytes6 seriesId) external returns (uint256);

    /// @dev Return the collateralization level of a vault. It will be negative if undercollateralized.
    function level(bytes12 vaultId) external returns (int256);
}

File 5 of 21 : IOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IOracle {
    /**
     * @notice Doesn't refresh the price, but returns the latest value available without doing any transactional operations:
     * @return value in wei
     */
    function peek(bytes32 base, bytes32 quote, uint256 amount) external view returns (uint256 value, uint256 updateTime);

    /**
     * @notice Does whatever work or queries will yield the most up-to-date price, and returns it.
     * @return value in wei
     */
    function get(bytes32 base, bytes32 quote, uint256 amount) external returns (uint256 value, uint256 updateTime);
}

File 6 of 21 : DataTypes.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IFYToken.sol";
import "./IOracle.sol";


library DataTypes {
    struct Series {
        IFYToken fyToken;                                               // Redeemable token for the series.
        bytes6  baseId;                                                 // Asset received on redemption.
        uint32  maturity;                                               // Unix time at which redemption becomes possible.
        // bytes2 free
    }

    struct Debt {
        uint96 max;                                                     // Maximum debt accepted for a given underlying, across all series
        uint24 min;                                                     // Minimum debt accepted for a given underlying, across all series
        uint8 dec;                                                      // Multiplying factor (10**dec) for max and min 
        uint128 sum;                                                    // Current debt for a given underlying, across all series
    }

    struct SpotOracle {
        IOracle oracle;                                                 // Address for the spot price oracle
        uint32  ratio;                                                  // Collateralization ratio to multiply the price for
        // bytes8 free
    }

    struct Vault {
        address owner;
        bytes6  seriesId;                                                // Each vault is related to only one series, which also determines the underlying.
        bytes6  ilkId;                                                   // Asset accepted as collateral
    }

    struct Balances {
        uint128 art;                                                     // Debt amount
        uint128 ink;                                                     // Collateral amount
    }
}

File 7 of 21 : IPool.sol
// SPDX-License-Identifier: MIT
pragma solidity >= 0.8.0;
import "@yield-protocol/utils-v2/contracts/token/IERC20.sol";
import "@yield-protocol/utils-v2/contracts/token/IERC2612.sol";
import "@yield-protocol/vault-interfaces/IFYToken.sol";


interface IPool is IERC20, IERC2612 {
    function ts() external view returns(int128);
    function g1() external view returns(int128);
    function g2() external view returns(int128);
    function maturity() external view returns(uint32);
    function scaleFactor() external view returns(uint96);
    function getCache() external view returns (uint112, uint112, uint32);
    function base() external view returns(IERC20);
    function fyToken() external view returns(IFYToken);
    function getBaseBalance() external view returns(uint112);
    function getFYTokenBalance() external view returns(uint112);
    function retrieveBase(address to) external returns(uint128 retrieved);
    function retrieveFYToken(address to) external returns(uint128 retrieved);
    function sellBase(address to, uint128 min) external returns(uint128);
    function buyBase(address to, uint128 baseOut, uint128 max) external returns(uint128);
    function sellFYToken(address to, uint128 min) external returns(uint128);
    function buyFYToken(address to, uint128 fyTokenOut, uint128 max) external returns(uint128);
    function sellBasePreview(uint128 baseIn) external view returns(uint128);
    function buyBasePreview(uint128 baseOut) external view returns(uint128);
    function sellFYTokenPreview(uint128 fyTokenIn) external view returns(uint128);
    function buyFYTokenPreview(uint128 fyTokenOut) external view returns(uint128);
    function mint(address to, address remainder, uint256 minRatio, uint256 maxRatio) external returns (uint256, uint256, uint256);
    function mintWithBase(address to, address remainder, uint256 fyTokenToBuy, uint256 minRatio, uint256 maxRatio) external returns (uint256, uint256, uint256);
    function burn(address baseTo, address fyTokenTo, uint256 minRatio, uint256 maxRatio) external returns (uint256, uint256, uint256);
    function burnForBase(address to, uint256 minRatio, uint256 maxRatio) external returns (uint256, uint256);
}

File 8 of 21 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

File 9 of 21 : IERC2612.sol
// SPDX-License-Identifier: MIT
// Code adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/
pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC2612 standard as defined in the EIP.
 *
 * Adds the {permit} method, which can be used to change one's
 * {IERC20-allowance} without having to send a transaction, by signing a
 * message. This allows users to spend tokens without having to hold Ether.
 *
 * See https://eips.ethereum.org/EIPS/eip-2612.
 */
interface IERC2612 {
    /**
     * @dev Sets `amount` as the allowance of `spender` over `owner`'s tokens,
     * given `owner`'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;

    /**
     * @dev Returns the current ERC2612 nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);
}

File 10 of 21 : DaiAbstract.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.5.12;

// https://github.com/makerdao/dss/blob/master/src/dai.sol
interface DaiAbstract {
    function wards(address) external view returns (uint256);
    function rely(address) external;
    function deny(address) external;
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function version() external view returns (string memory);
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint256);
    function balanceOf(address) external view returns (uint256);
    function allowance(address, address) external view returns (uint256);
    function nonces(address) external view returns (uint256);
    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external view returns (bytes32);
    function transfer(address, uint256) external;
    function transferFrom(address, address, uint256) external returns (bool);
    function mint(address, uint256) external;
    function burn(address, uint256) external;
    function approve(address, uint256) external returns (bool);
    function push(address, uint256) external;
    function pull(address, uint256) external;
    function move(address, address, uint256) external;
    function permit(address, address, uint256, uint256, bool, uint8, bytes32, bytes32) external;
}

File 11 of 21 : AccessControl.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms.
 *
 * Roles are referred to by their `bytes4` identifier. These are expected to be the 
 * signatures for all the functions in the contract. Special roles should be exposed
 * in the external API and be unique:
 *
 * ```
 * bytes4 public constant ROOT = 0x00000000;
 * ```
 *
 * Roles represent restricted access to a function call. For that purpose, use {auth}:
 *
 * ```
 * function foo() public auth {
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `ROOT`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {setRoleAdmin}.
 *
 * WARNING: The `ROOT` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
contract AccessControl {
    struct RoleData {
        mapping (address => bool) members;
        bytes4 adminRole;
    }

    mapping (bytes4 => RoleData) private _roles;

    bytes4 public constant ROOT = 0x00000000;
    bytes4 public constant ROOT4146650865 = 0x00000000; // Collision protection for ROOT, test with ROOT12007226833()
    bytes4 public constant LOCK = 0xFFFFFFFF;           // Used to disable further permissioning of a function
    bytes4 public constant LOCK8605463013 = 0xFFFFFFFF; // Collision protection for LOCK, test with LOCK10462387368()

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role
     *
     * `ROOT` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes4 indexed role, bytes4 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call.
     */
    event RoleGranted(bytes4 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes4 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Give msg.sender the ROOT role and create a LOCK role with itself as the admin role and no members. 
     * Calling setRoleAdmin(msg.sig, LOCK) means no one can grant that msg.sig role anymore.
     */
    constructor () {
        _grantRole(ROOT, msg.sender);   // Grant ROOT to msg.sender
        _setRoleAdmin(LOCK, LOCK);      // Create the LOCK role by setting itself as its own admin, creating an independent role tree
    }

    /**
     * @dev Each function in the contract has its own role, identified by their msg.sig signature.
     * ROOT can give and remove access to each function, lock any further access being granted to
     * a specific action, or even create other roles to delegate admin control over a function.
     */
    modifier auth() {
        require (_hasRole(msg.sig, msg.sender), "Access denied");
        _;
    }

    /**
     * @dev Allow only if the caller has been granted the admin role of `role`.
     */
    modifier admin(bytes4 role) {
        require (_hasRole(_getRoleAdmin(role), msg.sender), "Only admin");
        _;
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes4 role, address account) external view returns (bool) {
        return _hasRole(role, account);
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes4 role) external view returns (bytes4) {
        return _getRoleAdmin(role);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.

     * If ``role``'s admin role is not `adminRole` emits a {RoleAdminChanged} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function setRoleAdmin(bytes4 role, bytes4 adminRole) external virtual admin(role) {
        _setRoleAdmin(role, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes4 role, address account) external virtual admin(role) {
        _grantRole(role, account);
    }

    
    /**
     * @dev Grants all of `role` in `roles` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - For each `role` in `roles`, the caller must have ``role``'s admin role.
     */
    function grantRoles(bytes4[] memory roles, address account) external virtual {
        for (uint256 i = 0; i < roles.length; i++) {
            require (_hasRole(_getRoleAdmin(roles[i]), msg.sender), "Only admin");
            _grantRole(roles[i], account);
        }
    }

    /**
     * @dev Sets LOCK as ``role``'s admin role. LOCK has no members, so this disables admin management of ``role``.

     * Emits a {RoleAdminChanged} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function lockRole(bytes4 role) external virtual admin(role) {
        _setRoleAdmin(role, LOCK);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes4 role, address account) external virtual admin(role) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes all of `role` in `roles` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - For each `role` in `roles`, the caller must have ``role``'s admin role.
     */
    function revokeRoles(bytes4[] memory roles, address account) external virtual {
        for (uint256 i = 0; i < roles.length; i++) {
            require (_hasRole(_getRoleAdmin(roles[i]), msg.sender), "Only admin");
            _revokeRole(roles[i], account);
        }
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes4 role, address account) external virtual {
        require(account == msg.sender, "Renounce only for self");

        _revokeRole(role, account);
    }

    function _hasRole(bytes4 role, address account) internal view returns (bool) {
        return _roles[role].members[account];
    }

    function _getRoleAdmin(bytes4 role) internal view returns (bytes4) {
        return _roles[role].adminRole;
    }

    function _setRoleAdmin(bytes4 role, bytes4 adminRole) internal virtual {
        if (_getRoleAdmin(role) != adminRole) {
            _roles[role].adminRole = adminRole;
            emit RoleAdminChanged(role, adminRole);
        }
    }

    function _grantRole(bytes4 role, address account) internal {
        if (!_hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, msg.sender);
        }
    }

    function _revokeRole(bytes4 role, address account) internal {
        if (_hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, msg.sender);
        }
    }
}

File 12 of 21 : TransferHelper.sol
// SPDX-License-Identifier: MIT
// Taken from https://github.com/Uniswap/uniswap-lib/blob/master/contracts/libraries/TransferHelper.sol

pragma solidity >=0.6.0;

import "./IERC20.sol";
import "../utils/RevertMsgExtractor.sol";


// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    /// @notice Transfers tokens from msg.sender to a recipient
    /// @dev Errors with the underlying revert message if transfer fails
    /// @param token The contract address of the token which will be transferred
    /// @param to The recipient of the transfer
    /// @param value The value of the transfer
    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
        if (!(success && (data.length == 0 || abi.decode(data, (bool))))) revert(RevertMsgExtractor.getRevertMsg(data));
    }

    /// @notice Transfers tokens from the targeted address to the given destination
    /// @dev Errors with the underlying revert message if transfer fails
    /// @param token The contract address of the token to be transferred
    /// @param from The originating address from which the tokens will be transferred
    /// @param to The destination address of the transfer
    /// @param value The amount to be transferred
    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
        if (!(success && (data.length == 0 || abi.decode(data, (bool))))) revert(RevertMsgExtractor.getRevertMsg(data));
    }

    /// @notice Transfers ETH to the recipient address
    /// @dev Errors with the underlying revert message if transfer fails
    /// @param to The destination of the transfer
    /// @param value The value to be transferred
    function safeTransferETH(address payable to, uint256 value) internal {
        (bool success, bytes memory data) = to.call{value: value}(new bytes(0));
        if (!success) revert(RevertMsgExtractor.getRevertMsg(data));
    }
}

File 13 of 21 : WMul.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;


library WMul {
    // Taken from https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol
    /// @dev Multiply an amount by a fixed point factor with 18 decimals, rounds down.
    function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x * y;
        unchecked { z /= 1e18; }
    }
}

File 14 of 21 : CastU256U128.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;


library CastU256U128 {
    /// @dev Safely cast an uint256 to an uint128
    function u128(uint256 x) internal pure returns (uint128 y) {
        require (x <= type(uint128).max, "Cast overflow");
        y = uint128(x);
    }
}

File 15 of 21 : CastU256I128.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;


library CastU256I128 {
    /// @dev Safe casting from uint256 to int256
    function i128(uint256 x) internal pure returns(int128) {
        require(x <= uint256(int256(type(int128).max)), "Cast overflow");
        return int128(int256(x));
    }
}

File 16 of 21 : CastU128I128.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;


library CastU128I128 {
    /// @dev Safely cast an uint128 to an int128
    function i128(uint128 x) internal pure returns (int128 y) {
        require (x <= uint128(type(int128).max), "Cast overflow");
        y = int128(x);
    }
}

File 17 of 21 : LadleStorage.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.6;
import "@yield-protocol/vault-interfaces/ICauldron.sol";
import "@yield-protocol/vault-interfaces/IJoin.sol";
import "@yield-protocol/yieldspace-interfaces/IPool.sol";
import "@yield-protocol/utils-v2/contracts/interfaces/IWETH9.sol";
import "./Router.sol";


/// @dev Ladle orchestrates contract calls throughout the Yield Protocol v2 into useful and efficient user oriented features.
contract LadleStorage {
    event JoinAdded(bytes6 indexed assetId, address indexed join);
    event PoolAdded(bytes6 indexed seriesId, address indexed pool);
    event ModuleAdded(address indexed module, bool indexed set);
    event IntegrationAdded(address indexed integration, bool indexed set);
    event TokenAdded(address indexed token, bool indexed set);
    event FeeSet(uint256 fee);

    ICauldron public immutable cauldron;
    Router public immutable router;
    IWETH9 public immutable weth;
    uint256 public borrowingFee;
    bytes12 cachedVaultId;

    mapping (bytes6 => IJoin)                   public joins;            // Join contracts available to manage assets. The same Join can serve multiple assets (ETH-A, ETH-B, etc...)
    mapping (bytes6 => IPool)                   public pools;            // Pool contracts available to manage series. 12 bytes still free.
    mapping (address => bool)                   public modules;          // Trusted contracts to delegatecall anything on.
    mapping (address => bool)                   public integrations;     // Trusted contracts to call anything on.
    mapping (address => bool)                   public tokens;           // Trusted contracts to call `transfer` or `permit` on.

    constructor (ICauldron cauldron_, IWETH9 weth_) {
        cauldron = cauldron_;
        router = new Router();
        weth = weth_;
    }
}

File 18 of 21 : RevertMsgExtractor.sol
// SPDX-License-Identifier: MIT
// Taken from https://github.com/sushiswap/BoringSolidity/blob/441e51c0544cf2451e6116fe00515e71d7c42e2c/contracts/BoringBatchable.sol

pragma solidity >=0.6.0;


library RevertMsgExtractor {
    /// @dev Helper function to extract a useful revert message from a failed call.
    /// If the returned data is malformed or not correctly abi encoded then this call can fail itself.
    function getRevertMsg(bytes memory returnData)
        internal pure
        returns (string memory)
    {
        // If the _res length is less than 68, then the transaction failed silently (without a revert message)
        if (returnData.length < 68) return "Transaction reverted silently";

        assembly {
            // Slice the sighash.
            returnData := add(returnData, 0x04)
        }
        return abi.decode(returnData, (string)); // All that remains is the revert string
    }
}

File 19 of 21 : IWETH9.sol
// SPDX-License-Identifier: MIT
import "../token/IERC20.sol";

pragma solidity ^0.8.0;


interface IWETH9 is IERC20 {
    event  Deposit(address indexed dst, uint wad);
    event  Withdrawal(address indexed src, uint wad);

    function deposit() external payable;
    function withdraw(uint wad) external;
}

File 20 of 21 : Router.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.6;
import "@yield-protocol/utils-v2/contracts/utils/RevertMsgExtractor.sol";
import "@yield-protocol/utils-v2/contracts/utils/IsContract.sol";


/// @dev Router forwards calls between two contracts, so that any permissions
/// given to the original caller are stripped from the call.
/// This is useful when implementing generic call routing functions on contracts
/// that might have ERC20 approvals or AccessControl authorizations.
contract Router {
    using IsContract for address;

    address immutable public owner;

    constructor () {
        owner = msg.sender;
    }

    /// @dev Allow users to route calls to a pool, to be used with batch
    function route(address target, bytes calldata data)
        external payable
        returns (bytes memory result)
    {
        require(msg.sender == owner, "Only owner");
        require(target.isContract(), "Target is not a contract");
        bool success;
        (success, result) = target.call(data);
        if (!success) revert(RevertMsgExtractor.getRevertMsg(result));
    }
}

File 21 of 21 : IsContract.sol
// SPDX-License-Identifier: MIT
// Taken from Address.sol from OpenZeppelin.
pragma solidity ^0.8.0;


library IsContract {
  /// @dev Returns true if `account` is a contract.
  function isContract(address account) internal view returns (bool) {
      // This method relies on extcodesize, which returns 0 for contracts in
      // construction, since the code is only stored at the end of the
      // constructor execution.
      return account.code.length > 0;
  }
}

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

Contract ABI

[{"inputs":[{"internalType":"contract ICauldron","name":"cauldron","type":"address"},{"internalType":"contract IWETH9","name":"weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"FeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"integration","type":"address"},{"indexed":true,"internalType":"bool","name":"set","type":"bool"}],"name":"IntegrationAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes6","name":"assetId","type":"bytes6"},{"indexed":true,"internalType":"address","name":"join","type":"address"}],"name":"JoinAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"module","type":"address"},{"indexed":true,"internalType":"bool","name":"set","type":"bool"}],"name":"ModuleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes6","name":"seriesId","type":"bytes6"},{"indexed":true,"internalType":"address","name":"pool","type":"address"}],"name":"PoolAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"role","type":"bytes4"},{"indexed":true,"internalType":"bytes4","name":"newAdminRole","type":"bytes4"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"role","type":"bytes4"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes4","name":"role","type":"bytes4"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bool","name":"set","type":"bool"}],"name":"TokenAdded","type":"event"},{"inputs":[],"name":"LOCK","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCK8605463013","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT4146650865","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"integration","type":"address"},{"internalType":"bool","name":"set","type":"bool"}],"name":"addIntegration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes6","name":"assetId","type":"bytes6"},{"internalType":"contract IJoin","name":"join","type":"address"}],"name":"addJoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bool","name":"set","type":"bool"}],"name":"addModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes6","name":"seriesId","type":"bytes6"},{"internalType":"contract IPool","name":"pool","type":"address"}],"name":"addPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"set","type":"bool"}],"name":"addToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"calls","type":"bytes[]"}],"name":"batch","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"borrowingFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes6","name":"seriesId","type":"bytes6"},{"internalType":"bytes6","name":"ilkId","type":"bytes6"},{"internalType":"uint8","name":"salt","type":"uint8"}],"name":"build","outputs":[{"internalType":"bytes12","name":"","type":"bytes12"},{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes6","name":"seriesId","type":"bytes6"},{"internalType":"bytes6","name":"ilkId","type":"bytes6"}],"internalType":"struct DataTypes.Vault","name":"","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"cauldron","outputs":[{"internalType":"contract ICauldron","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"address","name":"to","type":"address"},{"internalType":"int128","name":"ink","type":"int128"},{"internalType":"int128","name":"art","type":"int128"}],"name":"close","outputs":[{"internalType":"uint128","name":"base","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"address","name":"to","type":"address"}],"name":"closeFromLadle","outputs":[{"internalType":"uint256","name":"repaid","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"}],"name":"destroy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"}],"name":"exitEther","outputs":[{"internalType":"uint256","name":"ethTransferred","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract DaiAbstract","name":"token","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"forwardDaiPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC2612","name":"token","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"forwardPermit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"address","name":"receiver","type":"address"}],"name":"give","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes6","name":"seriesId","type":"bytes6"},{"internalType":"bytes6","name":"ilkId","type":"bytes6"}],"internalType":"struct DataTypes.Vault","name":"vault","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"roles","type":"bytes4[]"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRoles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"integrations","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes6","name":"etherId","type":"bytes6"}],"name":"joinEther","outputs":[{"internalType":"uint256","name":"ethTransferred","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes6","name":"","type":"bytes6"}],"name":"joins","outputs":[{"internalType":"contract IJoin","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"}],"name":"lockRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"module","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"moduleCall","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"modules","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes6","name":"","type":"bytes6"}],"name":"pools","outputs":[{"internalType":"contract IPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"address","name":"to","type":"address"},{"internalType":"int128","name":"ink","type":"int128"},{"internalType":"int128","name":"art","type":"int128"}],"name":"pour","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes6","name":"seriesId","type":"bytes6"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"address","name":"to","type":"address"},{"internalType":"int128","name":"ink","type":"int128"},{"internalType":"uint128","name":"min","type":"uint128"}],"name":"repay","outputs":[{"internalType":"uint128","name":"art","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"address","name":"to","type":"address"}],"name":"repayFromLadle","outputs":[{"internalType":"uint256","name":"repaid","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"address","name":"to","type":"address"},{"internalType":"int128","name":"ink","type":"int128"},{"internalType":"uint128","name":"max","type":"uint128"}],"name":"repayVault","outputs":[{"internalType":"uint128","name":"base","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"retrieve","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"roles","type":"bytes4[]"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRoles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"bytes6","name":"newSeriesId","type":"bytes6"},{"internalType":"uint8","name":"loan","type":"uint8"},{"internalType":"uint128","name":"max","type":"uint128"}],"name":"roll","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes6","name":"seriesId","type":"bytes6"},{"internalType":"bytes6","name":"ilkId","type":"bytes6"}],"internalType":"struct DataTypes.Vault","name":"vault","type":"tuple"},{"internalType":"uint128","name":"newDebt","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"integration","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"route","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract Router","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint128","name":"ink","type":"uint128"},{"internalType":"uint128","name":"base","type":"uint128"},{"internalType":"uint128","name":"max","type":"uint128"}],"name":"serve","outputs":[{"internalType":"uint128","name":"art","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"role","type":"bytes4"},{"internalType":"bytes4","name":"adminRole","type":"bytes4"}],"name":"setRoleAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes12","name":"from","type":"bytes12"},{"internalType":"bytes12","name":"to","type":"bytes12"},{"internalType":"uint128","name":"ink","type":"uint128"},{"internalType":"uint128","name":"art","type":"uint128"}],"name":"stir","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint128","name":"wad","type":"uint128"}],"name":"transfer","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes12","name":"vaultId_","type":"bytes12"},{"internalType":"bytes6","name":"seriesId","type":"bytes6"},{"internalType":"bytes6","name":"ilkId","type":"bytes6"}],"name":"tweak","outputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes6","name":"seriesId","type":"bytes6"},{"internalType":"bytes6","name":"ilkId","type":"bytes6"}],"internalType":"struct DataTypes.Vault","name":"vault","type":"tuple"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH9","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60e06040523480156200001157600080fd5b50604051620067c6380380620067c6833981016040819052620000349162000202565b6001600160601b0319606083901b16608052604051829082906200005890620001f4565b604051809103906000f08015801562000075573d6000803e3d6000fd5b506001600160601b0319606091821b811660a05291901b1660c052506200009e600033620000ba565b620000b26001600160e01b03198062000156565b50506200025a565b6001600160e01b0319821660009081526007602090815260408083206001600160a01b038516845290915290205460ff1662000152576001600160e01b0319821660008181526007602090815260408083206001600160a01b0386168085529252808320805460ff1916600117905551339391927fe6231789d19137da31d0550f4ba9ee379020a8cfb64cb79bf1790c996d2e616591a45b5050565b6001600160e01b0319811662000188836001600160e01b03191660009081526007602052604090206001015460e01b90565b6001600160e01b0319161462000152576001600160e01b0319828116600081815260076020526040808220600101805463ffffffff191660e087901c17905551928416927fd348e2220a50b4500ec353f6e802d2f14dd1b5d6786148fd1bbcc570bf92d4739190a35050565b6104cc80620062fa83390190565b600080604083850312156200021657600080fd5b8251620002238162000241565b6020840151909250620002368162000241565b809150509250929050565b6001600160a01b03811681146200025757600080fd5b50565b60805160601c60a05160601c60c05160601c615f8e6200036c6000396000818161034301528181610520015281816111840152818161123801528181611fac015261202a01526000818161099d0152613b2801526000818161073e01528181610c5701528181610d6001528181610e8801528181610f73015281816116820152818161179301528181611b4701528181612402015281816124d4015281816128a20152818161297401528181612a9e01528181612d3701528181612e35015281816132100152818161346c015281816135180152818161364a01528181613751015281816137f30152818161406f015281816141ab0152818161441501528181614cc40152614e350152615f8e6000f3fe6080604052600436106103335760003560e01c8063782006b6116101b0578063c13b1bd3116100ec578063e817b38511610095578063f6252c711161006f578063f6252c711461096b578063f887ea401461098b578063f888f220146109bf578063ffffffff1461077357600080fd5b8063e817b38514610925578063effae35314610938578063f06c2dfc1461095857600080fd5b8063c6f33412116100c6578063c6f33412146108b5578063de02cde7146108d5578063e4860339146108f557600080fd5b8063c13b1bd31461086e578063c4d61ff11461088f578063c5dd197b146108a257600080fd5b8063a8ee49fe11610159578063ae93c1b511610133578063ae93c1b5146107f2578063b9af392014610812578063bf1025f314610825578063c03981981461085b57600080fd5b8063a8ee49fe1461078f578063ad82110f146107bf578063adf8d478146107df57600080fd5b806397ff6a041161018a57806397ff6a041461072c57806399d4294014610760578063a4f0d7d01461077357600080fd5b8063782006b6146106e3578063798a828b146106f65780638377be501461071657600080fd5b806349c29d2b1161027f57806360e0b6361161022857806369fe0e2d1161020257806369fe0e2d1461067c5780636c208f101461069c5780636d4756d7146106af57806371e70168146106d057600080fd5b806360e0b6361461061357806366c5b31214610649578063687f0e4c1461065c57600080fd5b806356e596a81161025957806356e596a8146105e05780635909c12f146103bc5780635ba5e9f0146105f357600080fd5b806349c29d2b1461058d578063543645ae146105ad578063559742d9146105c057600080fd5b806324bd54b4116102e15780633fc8cef3116102bb5780633fc8cef31461050e578063441c70f71461055a57806344faded01461056d57600080fd5b806324bd54b4146104a25780632bcc69a0146104cd57806333e6035a146104ee57600080fd5b806310ab94321161031257806310ab94321461044f5780631e897afb1461046f5780632458028a1461048f57600080fd5b80156103bc57806305e64794146103ef5780630a28e95d1461042f57600080fd5b366103b757336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103b55760405162461bcd60e51b815260206004820152601660248201527f4f6e6c7920726563656976652066726f6d20574554480000000000000000000060448201526064015b60405180910390fd5b005b600080fd5b3480156103c857600080fd5b506103d1600081565b6040516001600160e01b031990911681526020015b60405180910390f35b3480156103fb57600080fd5b5061041f61040a3660046151bd565b60056020526000908152604090205460ff1681565b60405190151581526020016103e6565b34801561043b57600080fd5b506103b561044a3660046151f7565b6109df565b34801561045b57600080fd5b5061041f61046a36600461564f565b610a97565b61048261047d36600461537b565b610ad2565b6040516103e69190615ae8565b6103b561049d366004615571565b610c1f565b6104b56104b03660046154aa565b610f14565b6040516001600160801b0390911681526020016103e6565b6104e06104db3660046151bd565b61116c565b6040519081526020016103e6565b3480156104fa57600080fd5b506103b5610509366004615743565b6112b5565b34801561051a57600080fd5b506105427f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016103e6565b6104b5610568366004615454565b61160b565b34801561057957600080fd5b506103b561058836600461564f565b611a25565b34801561059957600080fd5b506103b56105a8366004615743565b611ac1565b6104b56105bb3660046154aa565b611d87565b3480156105cc57600080fd5b506103b56105db366004615634565b611e88565b6103b56105ee366004615849565b611f01565b3480156105ff57600080fd5b506103d161060e366004615634565b611f77565b34801561061f57600080fd5b5061054261062e36600461569e565b6002602052600090815260409020546001600160a01b031681565b6104e061065736600461569e565b611f9c565b34801561066857600080fd5b506103b561067736600461564f565b61205b565b34801561068857600080fd5b506103b5610697366004615a1f565b6120bd565b6104e06106aa3660046156bb565b61215c565b6106c26106bd3660046156fc565b612287565b6040516103e6929190615b4a565b6103b56106de366004615889565b6122ba565b6103b56106f136600461540d565b6123bb565b610709610704366004615428565b612462565b6040516103e69190615ba8565b34801561072257600080fd5b506104e060005481565b34801561073857600080fd5b506105427f000000000000000000000000000000000000000000000000000000000000000081565b6103b561076e366004615454565b61255a565b34801561077f57600080fd5b506103d16001600160e01b031981565b34801561079b57600080fd5b5061041f6107aa3660046151bd565b60046020526000908152604090205460ff1681565b3480156107cb57600080fd5b506103b56107da3660046152b5565b612577565b6104b56107ed366004615502565b612633565b3480156107fe57600080fd5b506103b561080d36600461566b565b6127bb565b6107096108203660046155ae565b612828565b34801561083157600080fd5b5061054261084036600461569e565b6003602052600090815260409020546001600160a01b031681565b6104e0610869366004615428565b612926565b61088161087c3660046155f7565b612ce8565b6040516103e6929190615be3565b6103b561089d3660046157aa565b613314565b6104e06108b0366004615428565b61341e565b6108c86108c3366004615230565b613a8d565b6040516103e69190615b95565b3480156108e157600080fd5b506103b56108f036600461564f565b613bb7565b34801561090157600080fd5b5061041f6109103660046151bd565b60066020526000908152604090205460ff1681565b6108c8610933366004615230565b613c24565b34801561094457600080fd5b506103b56109533660046152b5565b613d06565b6104e061096636600461582b565b613d98565b34801561097757600080fd5b506103b56109863660046151f7565b613e7d565b34801561099757600080fd5b506105427f000000000000000000000000000000000000000000000000000000000000000081565b3480156109cb57600080fd5b506103b56109da3660046151f7565b613eeb565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff16610a435760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b6001600160a01b038216600081815260046020526040808220805460ff191685151590811790915590519092917fb33b04e7f0b1c74e2a082ded974e43bb8434997412d2f8fc32e4224144dbd9fe91a35050565b6001600160e01b0319821660009081526007602090815260408083206001600160a01b038516845290915281205460ff165b90505b92915050565b60608167ffffffffffffffff811115610aed57610aed615ef1565b604051908082528060200260200182016040528015610b2057816020015b6060815260200190600190039081610b0b5790505b50905060005b82811015610c035760008030868685818110610b4457610b44615edb565b9050602002810190610b569190615c34565b604051610b64929190615a7d565b600060405180830381855af49150503d8060008114610b9f576040519150601f19603f3d011682016040523d82523d6000602084013e610ba4565b606091505b509150915081610bd057610bb781613f59565b60405162461bcd60e51b81526004016103ac9190615b95565b80848481518110610be357610be3615edb565b602002602001018190525050508080610bfb90615e5a565b915050610b26565b50600180546bffffffffffffffffffffffff1916905592915050565b6001600160801b03821615610d2857604051631e81f82960e01b81526001600160a01b03198516600482015233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631e81f8299060240160606040518083038186803b158015610c9957600080fd5b505afa158015610cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd191906159ba565b516001600160a01b031614610d285760405162461bcd60e51b815260206004820152601760248201527f4f6e6c79206f726967696e207661756c74206f776e657200000000000000000060448201526064016103ac565b6001600160801b03811615610e3157604051631e81f82960e01b81526001600160a01b03198416600482015233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690631e81f8299060240160606040518083038186803b158015610da257600080fd5b505afa158015610db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dda91906159ba565b516001600160a01b031614610e315760405162461bcd60e51b815260206004820152601c60248201527f4f6e6c792064657374696e6174696f6e207661756c74206f776e65720000000060448201526064016103ac565b6040517f2458028a0000000000000000000000000000000000000000000000000000000081526001600160a01b03198086166004830152841660248201526001600160801b038084166044830152821660648201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632458028a90608401608060405180830381600087803b158015610ed457600080fd5b505af1158015610ee8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0c9190615913565b505050505050565b6000806000610f2287613fb8565b915091506000610f358260200151614152565b90506000610f46836020015161427f565b604051631c8a4a0360e21b81526001600160a01b0319861660048201529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637229280c90602401604080518083038186803b158015610fb457600080fd5b505afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec91906158f7565b835181516040517ffe2846b10000000000000000000000000000000000000000000000000000000081526001600160a01b0392831660048201526001600160801b039182166024820152908a16604482015291925083169063fe2846b190606401602060405180830381600087803b15801561106757600080fd5b505af115801561107b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109f9190615a02565b95506110cc85858b8b6110be86600001516001600160801b03166142ef565b6110c790615e95565b61434e565b6040517ffa2968790000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0383169063fa29687990602401602060405180830381600087803b15801561112657600080fd5b505af115801561113a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115e9190615a02565b505050505050949350505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a082319060240160206040518083038186803b1580156111ce57600080fd5b505afa1580156111e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112069190615a38565b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561128457600080fd5b505af1158015611298573d6000803e3d6000fd5b506112b0925050506001600160a01b03831682614737565b919050565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff166113195760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b600061132483614152565b600001519050816001600160a01b031663dc3bfba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561136357600080fd5b505afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b91906151da565b6001600160a01b0316816001600160a01b0316146114215760405162461bcd60e51b815260206004820152602260248201527f4d69736d61746368656420706f6f6c206679546f6b656e20616e64207365726960448201527f657300000000000000000000000000000000000000000000000000000000000060648201526084016103ac565b816001600160a01b0316635001f3b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561145a57600080fd5b505afa15801561146e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149291906151da565b6001600160a01b0316816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156114d457600080fd5b505afa1580156114e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150c91906151da565b6001600160a01b0316146115625760405162461bcd60e51b815260206004820152601f60248201527f4d69736d61746368656420706f6f6c206261736520616e64207365726965730060448201526064016103ac565b6001600160d01b03198316600090815260036020526040812080546001600160a01b0319166001600160a01b0385169081179091556115a25760006115a5565b60015b90506115b182826147bc565b6115bb83826147bc565b6115c58382614810565b6040516001600160a01b038416906001600160d01b03198616907f9b2f85ba13740543525ad2d1fc97e976093cce223fd72bdd789866b884470b3890600090a350505050565b60008082600f0b1261165f5760405162461bcd60e51b815260206004820152600f60248201527f4f6e6c792072657061792064656274000000000000000000000000000000000060448201526064016103ac565b60008061166b87613fb8565b91509150600061167e8260200151614152565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663550b02538360200151876116be90615e95565b6040516001600160e01b031960e085901b1681526001600160d01b031990921660048301526001600160801b03166024820152604401602060405180830381600087803b15801561170e57600080fd5b505af1158015611722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117469190615a02565b6040517fae8ad4920000000000000000000000000000000000000000000000000000000081526001600160a01b031985166004820152600f88810b602483015287900b60448201529094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ae8ad492906064016040805180830381600087803b1580156117de57600080fd5b505af11580156117f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181691906158f7565b5085600f0b60001461197e5760006118318360400151614864565b9050600087600f0b13156118ce57825160405163ceae3abd60e01b81526001600160a01b0391821660048201526001600160801b03891660248201529082169063ceae3abd90604401602060405180830381600087803b15801561189457600080fd5b505af11580156118a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118cc9190615a02565b505b600087600f0b121561197c576001600160a01b0381166312e5ff77896118f38a615e95565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401602060405180830381600087803b15801561194257600080fd5b505af1158015611956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197a9190615a02565b505b505b600061198d8260200151614864565b60405163ceae3abd60e01b81523360048201526001600160801b03871660248201529091506001600160a01b0382169063ceae3abd90604401602060405180830381600087803b1580156119e057600080fd5b505af11580156119f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a189190615a02565b5050505050949350505050565b81611a79611a4f826001600160e01b03191660009081526007602052604090206001015460e01b90565b6001600160e01b031916600090815260076020908152604080832033845290915290205460ff1690565b611ab25760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b611abc83836148d4565b505050565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff16611b255760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b604051630cdf468960e11b81526001600160d01b0319831660048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906319be8d129060240160206040518083038186803b158015611b9157600080fd5b505afa158015611ba5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc991906151da565b90506001600160a01b038116611c215760405162461bcd60e51b815260206004820152600f60248201527f4173736574206e6f7420666f756e64000000000000000000000000000000000060448201526064016103ac565b806001600160a01b0316826001600160a01b03166338d52e0f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c6457600080fd5b505afa158015611c78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9c91906151da565b6001600160a01b031614611cf25760405162461bcd60e51b815260206004820152601960248201527f4d69736d61746368656420617373657420616e64206a6f696e0000000000000060448201526064016103ac565b6001600160d01b03198316600090815260026020526040812080546001600160a01b0319166001600160a01b038516908117909155611d32576000611d35565b60015b9050611d4182826147bc565b6040516001600160a01b038416906001600160d01b03198616907fa165be0a6237b515a1722eaa2ac0d02a97a7a04e0b31261556003a46c08cbf9f90600090a350505050565b6000806000611d9587613fb8565b915091506000611da88260200151614152565b90506000611db9836020015161427f565b82516040517fbcc1694f0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526001600160801b038916602482015291925082169063bcc1694f90604401602060405180830381600087803b158015611e2957600080fd5b505af1158015611e3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e619190615a02565b9450611e7c84848a8a6110be8a6001600160801b03166142ef565b50505050949350505050565b80611eb2611a4f826001600160e01b03191660009081526007602052604090206001015460e01b90565b611eeb5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b611efd826001600160e01b031961496c565b5050565b6001600160a01b03831660009081526006602052604090205460ff16611f595760405162461bcd60e51b815260206004820152600d60248201526c2ab735b737bbb7103a37b5b2b760991b60448201526064016103ac565b611abc6001600160a01b03841633846001600160801b038516614a08565b6001600160e01b0319811660009081526007602052604081206001015460e01b610acc565b476000611fa883614864565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561200557600080fd5b505af1158015612019573d6000803e3d6000fd5b506120559350506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915083905084614b13565b50919050565b6001600160a01b03811633146120b35760405162461bcd60e51b815260206004820152601660248201527f52656e6f756e6365206f6e6c7920666f722073656c660000000000000000000060448201526064016103ac565b611efd82826148d4565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff166121215760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b60008190556040518181527f20461e09b8e557b77e107939f9ce6544698123aad0fc964ac5cc59b7df2e608f9060200160405180910390a150565b60008061216885614152565b5190506001600160a01b038116631e9a695085856121fc576040516370a0823160e01b81523060048201526001600160a01b038516906370a082319060240160206040518083038186803b1580156121bf57600080fd5b505afa1580156121d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f79190615a38565b6121fe565b855b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b15801561224457600080fd5b505af1158015612258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227c9190615a38565b9150505b9392505050565b604080516060810182526000808252602082018190529181018290526122ae858585614c1d565b91509150935093915050565b6001600160a01b03871660009081526006602052604090205460ff166123125760405162461bcd60e51b815260206004820152600d60248201526c2ab735b737bbb7103a37b5b2b760991b60448201526064016103ac565b6040517fd505accf0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b038781166024830152604482018790526064820186905260ff8516608483015260a4820184905260c4820183905288169063d505accf9060e4015b600060405180830381600087803b15801561239a57600080fd5b505af11580156123ae573d6000803e3d6000fd5b5050505050505050505050565b60006123c682613fb8565b506040517f782006b60000000000000000000000000000000000000000000000000000000081526001600160a01b0319821660048201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063782006b690602401600060405180830381600087803b15801561244e57600080fd5b505af1158015610f0c573d6000803e3d6000fd5b604080516060810182526000808252602082018190529181018290529061248884613fb8565b506040517f798a828b0000000000000000000000000000000000000000000000000000000081526001600160a01b0319821660048201526001600160a01b0385811660248301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063798a828b90604401606060405180830381600087803b15801561251a57600080fd5b505af115801561252e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255291906159ba565b949350505050565b60008061256686613fb8565b91509150610f0c828287878761434e565b60005b8251811015611abc576125c5611a4f84838151811061259b5761259b615edb565b60200260200101516001600160e01b03191660009081526007602052604090206001015460e01b90565b6125fe5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b61262183828151811061261357612613615edb565b6020026020010151836148d4565b8061262b81615e5a565b91505061257a565b600080600061264188613fb8565b915091506000612654826020015161427f565b6040517fb0f289210000000000000000000000000000000000000000000000000000000081526001600160801b03881660048201529091506001600160a01b0382169063b0f289219060240160206040518083038186803b1580156126b857600080fd5b505afa1580156126cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f09190615a02565b935061271c83838361270a8b6001600160801b03166142ef565b6110c7896001600160801b03166142ef565b6040516327af726d60e21b81526001600160a01b0389811660048301526001600160801b03808916602484015287166044830152821690639ebdc9b490606401602060405180830381600087803b15801561277657600080fd5b505af115801561278a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ae9190615a02565b5050505095945050505050565b816127e5611a4f826001600160e01b03191660009081526007602052604090206001015460e01b90565b61281e5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b611abc838361496c565b604080516060810182526000808252602082018190529181018290529061284e85613fb8565b506040517fb9af39200000000000000000000000000000000000000000000000000000000081526001600160a01b0319821660048201526001600160d01b03198087166024830152851660448201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b9af392090606401606060405180830381600087803b1580156128ee57600080fd5b505af1158015612902573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227c91906159ba565b600080600061293485613fb8565b9150915060006129478260200151614152565b604051631c8a4a0360e21b81526001600160a01b0319851660048201529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637229280c90602401604080518083038186803b1580156129b557600080fd5b505afa1580156129c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ed91906158f7565b82516040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015612a3557600080fd5b505afa158015612a49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6d9190615a38565b82519091506001600160801b0316811115612a925781516001600160801b0316612a94565b805b95508515612cab577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ae8ad49286612ad589614ee0565b612ade90615e95565b612ae78a614ee0565b612af090615e95565b6040516001600160e01b031960e086901b1681526001600160a01b03199093166004840152600f91820b6024840152900b60448201526064016040805180830381600087803b158015612b4257600080fd5b505af1158015612b56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b7a91906158f7565b5082516040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018890526001600160a01b0390911690639dc29fac90604401600060405180830381600087803b158015612bdf57600080fd5b505af1158015612bf3573d6000803e3d6000fd5b505050506000612c068560400151614864565b9050806001600160a01b03166312e5ff7789612c218a614f32565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401602060405180830381600087803b158015612c7057600080fd5b505af1158015612c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca89190615a02565b50505b6000612cb78783615e17565b1115612cdd57612cdd87612ccb8884615e17565b85516001600160a01b03169190614b13565b505050505092915050565b604080516060810182526000808252602082018190529181018290529080612d0f87613fb8565b604051631c8a4a0360e21b81526001600160a01b0319831660048201529094509091506000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690637229280c90602401604080518083038186803b158015612d8057600080fd5b505afa158015612d94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612db891906158f7565b90506000612dc98560200151614152565b90506000612dd689614152565b90506000612de38a61427f565b8251602085015191925090600090612dfa90614864565b60208a0151875160405163550b025360e01b81526001600160d01b031990921660048301526001600160801b031660248201529091506000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063550b025390604401602060405180830381600087803b158015612e8157600080fd5b505af1158015612e95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb99190615a02565b9050826001600160a01b03166340c10f19858e60ff1684612eda9190615d3f565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401600060405180830381600087803b158015612f2957600080fd5b505af1158015612f3d573d6000803e3d6000fd5b50506040516327af726d60e21b81526001600160a01b0385811660048301526001600160801b0380861660248401528f16604483015287169250639ebdc9b49150606401602060405180830381600087803b158015612f9b57600080fd5b505af1158015612faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd39190615a02565b60405163ceae3abd60e01b81526001600160a01b038416600482018190526001600160801b0384166024830152919a5063ceae3abd90604401602060405180830381600087803b15801561302657600080fd5b505af115801561303a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061305e9190615a02565b506040517fd3d00f240000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015285169063d3d00f2490602401602060405180830381600087803b1580156130bb57600080fd5b505af11580156130cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f39190615a02565b50826001600160a01b0316639dc29fac848b8f60ff16856131149190615d3f565b61311e9190615def565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401600060405180830381600087803b15801561316d57600080fd5b505af1158015613181573d6000803e3d6000fd5b505050505050505080602001516001600160d01b03191686604001516001600160d01b031916141580156131b6575060005415155b1561320e576132016131dc600054876001600160801b0316614f7b90919063ffffffff16565b42836040015163ffffffff166131f29190615e17565b6131fc9190615d6e565b614f32565b61320b9086615d14565b94505b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636295afac858b61325587600001516001600160801b03166142ef565b6132678a6001600160801b03166142ef565b6132719190615d8d565b6040516001600160e01b031960e086901b1681526001600160a01b031990931660048401526001600160d01b03199091166024830152600f0b604482015260640160a060405180830381600087803b1580156132cc57600080fd5b505af11580156132e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330491906159d6565b5095505050505094509492505050565b6001600160a01b03881660009081526006602052604090205460ff1661336c5760405162461bcd60e51b815260206004820152600d60248201526c2ab735b737bbb7103a37b5b2b760991b60448201526064016103ac565b6040517f8fcbaf0c0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0388811660248301526044820188905260648201879052851515608483015260ff851660a483015260c4820184905260e48201839052891690638fcbaf0c9061010401600060405180830381600087803b1580156133fc57600080fd5b505af1158015613410573d6000803e3d6000fd5b505050505050505050505050565b600080600061342c85613fb8565b91509150600061343f8260200151614152565b604051631c8a4a0360e21b81526001600160a01b0319851660048201529091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690637229280c90602401604080518083038186803b1580156134ad57600080fd5b505afa1580156134c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e591906158f7565b6020830151604051630cdf468960e11b81526001600160d01b031990911660048201529091506000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906319be8d129060240160206040518083038186803b15801561355a57600080fd5b505afa15801561356e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061359291906151da565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b1580156135d757600080fd5b505afa1580156135eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061360f9190615a38565b6020860151845160405163550b025360e01b81526001600160d01b031990921660048301526001600160801b031660248201529091506000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063550b025390604401602060405180830381600087803b15801561369657600080fd5b505af11580156136aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ce9190615a02565b6001600160801b0316905060006136f2828411156136ec5782614f32565b83614f32565b905081816001600160801b0316146137da5760208701516040517f9dd6c00e0000000000000000000000000000000000000000000000000000000081526001600160d01b031990911660048201526001600160801b03821660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639dd6c00e90604401602060405180830381600087803b15801561379d57600080fd5b505af11580156137b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137d59190615a02565b6137dd565b84515b6001600160801b039081169950811615613a3c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ae8ad4928961382a8c614ee0565b61383390615e95565b61383c8d614ee0565b61384590615e95565b6040516001600160e01b031960e086901b1681526001600160a01b03199093166004840152600f91820b6024840152900b60448201526064016040805180830381600087803b15801561389757600080fd5b505af11580156138ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138cf91906158f7565b5060006138df8760200151614864565b90506138fe6001600160a01b038616826001600160801b038516614b13565b60405163ceae3abd60e01b81523060048201526001600160801b03831660248201526001600160a01b0382169063ceae3abd90604401602060405180830381600087803b15801561394e57600080fd5b505af1158015613962573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139869190615a02565b5060006139968960400151614864565b9050806001600160a01b03166312e5ff778d6139b18e614f32565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401602060405180830381600087803b158015613a0057600080fd5b505af1158015613a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a389190615a02565b5050505b6000613a516001600160801b03831685615e17565b1115613a7f57613a7f8a613a6e6001600160801b03841686615e17565b6001600160a01b0387169190614b13565b505050505050505092915050565b6001600160a01b03831660009081526005602052604090205460609060ff16613af85760405162461bcd60e51b815260206004820152601360248201527f556e6b6e6f776e20696e746567726174696f6e0000000000000000000000000060448201526064016103ac565b6040517fc6f334120000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c6f3341290613b6190879087908790600401615aa9565b600060405180830381600087803b158015613b7b57600080fd5b505af1158015613b8f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526125529190810190615761565b81613be1611a4f826001600160e01b03191660009081526007602052604090206001015460e01b90565b613c1a5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b611abc8383614f99565b6001600160a01b03831660009081526004602052604090205460609060ff16613c8f5760405162461bcd60e51b815260206004820152601360248201527f556e72656769737465726564206d6f64756c650000000000000000000000000060448201526064016103ac565b6000846001600160a01b03168484604051613cab929190615a7d565b600060405180830381855af49150503d8060008114613ce6576040519150601f19603f3d011682016040523d82523d6000602084013e613ceb565b606091505b509250905080613cfe57610bb782613f59565b509392505050565b60005b8251811015611abc57613d2a611a4f84838151811061259b5761259b615edb565b613d635760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b613d86838281518110613d7857613d78615edb565b602002602001015183614f99565b80613d9081615e5a565b915050613d09565b6001600160a01b03821660009081526006602052604081205460ff16613df05760405162461bcd60e51b815260206004820152600d60248201526c2ab735b737bbb7103a37b5b2b760991b60448201526064016103ac565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b158015613e2f57600080fd5b505afa158015613e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e679190615a38565b9050610acc6001600160a01b0384168383614b13565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff16613ee15760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b611efd82826147bc565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff16613f4f5760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b611efd8282614810565b6060604482511015613f9e57505060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c79000000602082015290565b60048201915081806020019051810190610acc9190615761565b604080516060810182526000808252602082018190529181018290526001600160a01b0319831661404c5760015460a01b6001600160a01b03191661403f5760405162461bcd60e51b815260206004820152601060248201527f5661756c74206e6f74206361636865640000000000000000000000000000000060448201526064016103ac565b60015460a01b9150614050565b8291505b604051631e81f82960e01b81526001600160a01b0319831660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631e81f8299060240160606040518083038186803b1580156140b957600080fd5b505afa1580156140cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140f191906159ba565b80519091506001600160a01b0316331461414d5760405162461bcd60e51b815260206004820152601060248201527f4f6e6c79207661756c74206f776e65720000000000000000000000000000000060448201526064016103ac565b915091565b604080516060810182526000808252602082018190528183015290517f55d03e340000000000000000000000000000000000000000000000000000000081526001600160d01b0319831660048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906355d03e349060240160606040518083038186803b1580156141ed57600080fd5b505afa158015614201573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614225919061593f565b80519091506001600160a01b03166112b05760405162461bcd60e51b815260206004820152601060248201527f536572696573206e6f7420666f756e640000000000000000000000000000000060448201526064016103ac565b6001600160d01b031981166000908152600360205260409020546001600160a01b0316806112b05760405162461bcd60e51b815260206004820152600e60248201527f506f6f6c206e6f7420666f756e6400000000000000000000000000000000000060448201526064016103ac565b60006f7fffffffffffffffffffffffffffffff6001600160801b038316111561434a5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b60448201526064016103ac565b5090565b604080516060810182526000808252602082018190529181019190915281600f0b600014614386576143838560200151614152565b90505b60008083600f0b1380156143b6575081602001516001600160d01b03191686604001516001600160d01b03191614155b80156143c3575060005415155b1561440b576144086143e360005485600f0b614f7b90919063ffffffff16565b42846040015163ffffffff166143f99190615e17565b6144039190615d6e565b614ee0565b90505b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663ae8ad49288866144468588615cb3565b6040516001600160e01b031960e086901b1681526001600160a01b03199093166004840152600f91820b6024840152900b60448201526064016040805180830381600087803b15801561449857600080fd5b505af11580156144ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144d091906158f7565b5083600f0b6000146146385760006144eb8760400151614864565b9050600085600f0b131561458857865160405163ceae3abd60e01b81526001600160a01b0391821660048201526001600160801b03871660248201529082169063ceae3abd90604401602060405180830381600087803b15801561454e57600080fd5b505af1158015614562573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145869190615a02565b505b600085600f0b1215614636576001600160a01b0381166312e5ff77876145ad88615e95565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401602060405180830381600087803b1580156145fc57600080fd5b505af1158015614610573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146349190615a02565b505b505b82600f0b60001461472e57600083600f0b13156146da5781516040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301526001600160801b0386166024830152909116906340c10f1990604401600060405180830381600087803b1580156146bd57600080fd5b505af11580156146d1573d6000803e3d6000fd5b5050505061472e565b81516001600160a01b0316639dc29fac336146f486615e95565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401612380565b50505050505050565b60408051600080825260208201928390529182916001600160a01b03861691859161476191615a8d565b60006040518083038185875af1925050503d806000811461479e576040519150601f19603f3d011682016040523d82523d6000602084013e6147a3565b606091505b5091509150816147b657610bb781613f59565b50505050565b6001600160a01b038216600081815260066020526040808220805460ff191685151590811790915590519092917f654ff2be0f58b1b437adcc6ff9868ab309fc9979c02811bca8f9a7bd95a217b691a35050565b6001600160a01b038216600081815260056020526040808220805460ff191685151590811790915590519092917f3f708a815f33c6ad64cc991b28ca6b465b31c3d0b7459b295fb3f095cd76c54291a35050565b6001600160d01b031981166000908152600260205260409020546001600160a01b0316806112b05760405162461bcd60e51b815260206004820152600e60248201527f4a6f696e206e6f7420666f756e6400000000000000000000000000000000000060448201526064016103ac565b6001600160e01b0319821660009081526007602090815260408083206001600160a01b038516845290915290205460ff1615611efd576001600160e01b0319821660008181526007602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339391927f4ddc7b757e7bdd7254a9cd39452d307a52761bc824625c6a33104a075d8099e691a45050565b6001600160e01b0319811661499d836001600160e01b03191660009081526007602052604090206001015460e01b90565b6001600160e01b03191614611efd576001600160e01b0319828116600081815260076020526040808220600101805463ffffffff191660e087901c17905551928416927fd348e2220a50b4500ec353f6e802d2f14dd1b5d6786148fd1bbcc570bf92d4739190a35050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691614a9a9190615a8d565b6000604051808303816000865af19150503d8060008114614ad7576040519150601f19603f3d011682016040523d82523d6000602084013e614adc565b606091505b5091509150818015614b06575080511580614b06575080806020019051810190614b0691906153f0565b610f0c57610bb781613f59565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691614b9d9190615a8d565b6000604051808303816000865af19150503d8060008114614bda576040519150601f19603f3d011682016040523d82523d6000602084013e614bdf565b606091505b5091509150818015614c09575080511580614c09575080806020019051810190614c0991906153f0565b614c1657610bb781613f59565b5050505050565b60408051606080820183526000808352602080840182905283850182905284513390931b6bffffffffffffffffffffffff19168382015242603484015260f886901b7fff000000000000000000000000000000000000000000000000000000000000001660548401528451603581850301815260559093019094528151919093012091505b604051631e81f82960e01b81526001600160a01b0319831660048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631e81f8299060240160606040518083038186803b158015614d0e57600080fd5b505afa158015614d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d4691906159ba565b602001516001600160d01b03191614614ddf57614dd8614d6584615e75565b9350836040516bffffffffffffffffffffffff193360601b1660208201524260348201527fff0000000000000000000000000000000000000000000000000000000000000060f883901b166054820152600090605501604051602081830303815290604052805190602001209050919050565b9150614ca2565b6040517f272c0a6e0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0319831660248201526001600160d01b03198087166044830152851660648201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063272c0a6e90608401606060405180830381600087803b158015614e8157600080fd5b505af1158015614e95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614eb991906159ba565b600180546bffffffffffffffffffffffff191660a085901c17905591959194509092505050565b60006f7fffffffffffffffffffffffffffffff82111561434a5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b60448201526064016103ac565b60006001600160801b0382111561434a5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b60448201526064016103ac565b6000614f878284615d6e565b670de0b6b3a764000090049392505050565b6001600160e01b0319821660009081526007602090815260408083206001600160a01b038516845290915290205460ff16611efd576001600160e01b0319821660008181526007602090815260408083206001600160a01b0386168085529252808320805460ff1916600117905551339391927fe6231789d19137da31d0550f4ba9ee379020a8cfb64cb79bf1790c996d2e616591a45050565b600067ffffffffffffffff83111561504d5761504d615ef1565b615060601f8401601f1916602001615c82565b905082815283838301111561507457600080fd5b612280836020830184615e2e565b80356112b081615f07565b80356001600160a01b0319811681146112b057600080fd5b80356001600160e01b0319811681146112b057600080fd5b8035600f81900b81146112b057600080fd5b6000604082840312156150e157600080fd5b6040516040810181811067ffffffffffffffff8211171561510457615104615ef1565b8060405250809150825161511781615f43565b8152602083015161512781615f43565b6020919091015292915050565b60006060828403121561514657600080fd5b6040516060810181811067ffffffffffffffff8211171561516957615169615ef1565b8060405250809150825161517c81615f07565b8152602083015161518c81615f2d565b6020820152604083015161519f81615f2d565b6040919091015292915050565b803560ff811681146112b057600080fd5b6000602082840312156151cf57600080fd5b813561228081615f07565b6000602082840312156151ec57600080fd5b815161228081615f07565b6000806040838503121561520a57600080fd5b823561521581615f07565b9150602083013561522581615f1f565b809150509250929050565b60008060006040848603121561524557600080fd5b833561525081615f07565b9250602084013567ffffffffffffffff8082111561526d57600080fd5b818601915086601f83011261528157600080fd5b81358181111561529057600080fd5b8760208285010111156152a257600080fd5b6020830194508093505050509250925092565b600080604083850312156152c857600080fd5b823567ffffffffffffffff808211156152e057600080fd5b818501915085601f8301126152f457600080fd5b813560208282111561530857615308615ef1565b8160051b9250615319818401615c82565b8281528181019085830185870184018b101561533457600080fd5b600096505b8487101561535e5761534a816150a5565b835260019690960195918301918301615339565b50965061536e9050878201615082565b9450505050509250929050565b6000806020838503121561538e57600080fd5b823567ffffffffffffffff808211156153a657600080fd5b818501915085601f8301126153ba57600080fd5b8135818111156153c957600080fd5b8660208260051b85010111156153de57600080fd5b60209290920196919550909350505050565b60006020828403121561540257600080fd5b815161228081615f1f565b60006020828403121561541f57600080fd5b610ac98261508d565b6000806040838503121561543b57600080fd5b6154448361508d565b9150602083013561522581615f07565b6000806000806080858703121561546a57600080fd5b6154738561508d565b9350602085013561548381615f07565b9250615491604086016150bd565b915061549f606086016150bd565b905092959194509250565b600080600080608085870312156154c057600080fd5b6154c98561508d565b935060208501356154d981615f07565b92506154e7604086016150bd565b915060608501356154f781615f43565b939692955090935050565b600080600080600060a0868803121561551a57600080fd5b6155238661508d565b9450602086013561553381615f07565b9350604086013561554381615f43565b9250606086013561555381615f43565b9150608086013561556381615f43565b809150509295509295909350565b6000806000806080858703121561558757600080fd5b6155908561508d565b935061559e6020860161508d565b925060408501356154e781615f43565b6000806000606084860312156155c357600080fd5b6155cc8461508d565b925060208401356155dc81615f2d565b915060408401356155ec81615f2d565b809150509250925092565b6000806000806080858703121561560d57600080fd5b6156168561508d565b9350602085013561562681615f2d565b92506154e7604086016151ac565b60006020828403121561564657600080fd5b610ac9826150a5565b6000806040838503121561566257600080fd5b615444836150a5565b6000806040838503121561567e57600080fd5b615687836150a5565b9150615695602084016150a5565b90509250929050565b6000602082840312156156b057600080fd5b813561228081615f2d565b6000806000606084860312156156d057600080fd5b83356156db81615f2d565b925060208401356156eb81615f07565b929592945050506040919091013590565b60008060006060848603121561571157600080fd5b833561571c81615f2d565b9250602084013561572c81615f2d565b915061573a604085016151ac565b90509250925092565b6000806040838503121561575657600080fd5b823561544481615f2d565b60006020828403121561577357600080fd5b815167ffffffffffffffff81111561578a57600080fd5b8201601f8101841361579b57600080fd5b61255284825160208401615033565b600080600080600080600080610100898b0312156157c757600080fd5b88356157d281615f07565b975060208901356157e281615f07565b96506040890135955060608901359450608089013561580081615f1f565b935061580e60a08a016151ac565b925060c0890135915060e089013590509295985092959890939650565b6000806040838503121561583e57600080fd5b823561544481615f07565b60008060006060848603121561585e57600080fd5b833561586981615f07565b9250602084013561587981615f07565b915060408401356155ec81615f43565b600080600080600080600060e0888a0312156158a457600080fd5b87356158af81615f07565b965060208801356158bf81615f07565b955060408801359450606088013593506158db608089016151ac565b925060a0880135915060c0880135905092959891949750929550565b60006040828403121561590957600080fd5b610ac983836150cf565b6000806080838503121561592657600080fd5b61593084846150cf565b915061569584604085016150cf565b60006060828403121561595157600080fd5b6040516060810181811067ffffffffffffffff8211171561597457615974615ef1565b604052825161598281615f07565b8152602083015161599281615f2d565b6020820152604083015163ffffffff811681146159ae57600080fd5b60408201529392505050565b6000606082840312156159cc57600080fd5b610ac98383615134565b60008060a083850312156159e957600080fd5b6159f38484615134565b915061569584606085016150cf565b600060208284031215615a1457600080fd5b815161228081615f43565b600060208284031215615a3157600080fd5b5035919050565b600060208284031215615a4a57600080fd5b5051919050565b60008151808452615a69816020860160208601615e2e565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b60008251615a9f818460208701615e2e565b9190910192915050565b6001600160a01b038416815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015615b3d57603f19888603018452615b2b858351615a51565b94509285019290850190600101615b0f565b5092979650505050505050565b6001600160a01b03198316815260808101612280602083018480516001600160a01b031682526020808201516001600160d01b03199081169184019190915260409182015116910152565b602081526000610ac96020830184615a51565b60608101610acc828480516001600160a01b031682526020808201516001600160d01b03199081169184019190915260409182015116910152565b60808101615c1e828580516001600160a01b031682526020808201516001600160d01b03199081169184019190915260409182015116910152565b6001600160801b03831660608301529392505050565b6000808335601e19843603018112615c4b57600080fd5b83018035915067ffffffffffffffff821115615c6657600080fd5b602001915036819003821315615c7b57600080fd5b9250929050565b604051601f8201601f1916810167ffffffffffffffff81118282101715615cab57615cab615ef1565b604052919050565b600081600f0b83600f0b60008212826f7fffffffffffffffffffffffffffffff03821381151615615ce657615ce6615ec5565b826f7fffffffffffffffffffffffffffffff19038212811615615d0b57615d0b615ec5565b50019392505050565b60006001600160801b03808316818516808303821115615d3657615d36615ec5565b01949350505050565b60006001600160801b0380831681851681830481118215151615615d6557615d65615ec5565b02949350505050565b6000816000190483118215151615615d8857615d88615ec5565b500290565b600081600f0b83600f0b60008112816f7fffffffffffffffffffffffffffffff1901831281151615615dc157615dc1615ec5565b816f7fffffffffffffffffffffffffffffff018313811615615de557615de5615ec5565b5090039392505050565b60006001600160801b0383811690831681811015615e0f57615e0f615ec5565b039392505050565b600082821015615e2957615e29615ec5565b500390565b60005b83811015615e49578181015183820152602001615e31565b838111156147b65750506000910152565b6000600019821415615e6e57615e6e615ec5565b5060010190565b600060ff821660ff811415615e8c57615e8c615ec5565b60010192915050565b600081600f0b6f7fffffffffffffffffffffffffffffff19811415615ebc57615ebc615ec5565b60000392915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114615f1c57600080fd5b50565b8015158114615f1c57600080fd5b6001600160d01b031981168114615f1c57600080fd5b6001600160801b0381168114615f1c57600080fdfea2646970667358221220ae01d45ee6c6a09dfe0c3e223faf6816094293643ec80556eebeda564144840b64736f6c6343000806003360a060405234801561001057600080fd5b5033606081901b608052610495610037600039600081816040015260ac01526104956000f3fe6080604052600436106100295760003560e01c80638da5cb5b1461002e578063c6f334121461007f575b600080fd5b34801561003a57600080fd5b506100627f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61009261008d36600461026c565b61009f565b60405161007691906103e6565b6060336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461011e5760405162461bcd60e51b815260206004820152600a60248201527f4f6e6c79206f776e65720000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b0384163b6101755760405162461bcd60e51b815260206004820152601860248201527f546172676574206973206e6f74206120636f6e747261637400000000000000006044820152606401610115565b6000846001600160a01b031684846040516101919291906103d6565b6000604051808303816000865af19150503d80600081146101ce576040519150601f19603f3d011682016040523d82523d6000602084013e6101d3565b606091505b5092509050806101ff576101e682610207565b60405162461bcd60e51b815260040161011591906103e6565b509392505050565b606060448251101561024c57505060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c79000000602082015290565b6004820191508180602001905181019061026691906102fd565b92915050565b60008060006040848603121561028157600080fd5b83356001600160a01b038116811461029857600080fd5b9250602084013567ffffffffffffffff808211156102b557600080fd5b818601915086601f8301126102c957600080fd5b8135818111156102d857600080fd5b8760208285010111156102ea57600080fd5b6020830194508093505050509250925092565b60006020828403121561030f57600080fd5b815167ffffffffffffffff8082111561032757600080fd5b818401915084601f83011261033b57600080fd5b81518181111561034d5761034d610430565b604051601f8201601f19908116603f0116810190838211818310171561037557610375610430565b8160405282815287602084870101111561038e57600080fd5b61039f836020830160208801610400565b979650505050505050565b600081518084526103c2816020860160208601610400565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b6020815260006103f960208301846103aa565b9392505050565b60005b8381101561041b578181015183820152602001610403565b8381111561042a576000848401525b50505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea264697066735822122022f2bc2ff8337797205081269ba37d2c0b2d782621a976afe0a806c421b4417c64736f6c6343000806003300000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e3000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1

Deployed Bytecode

0x6080604052600436106103335760003560e01c8063782006b6116101b0578063c13b1bd3116100ec578063e817b38511610095578063f6252c711161006f578063f6252c711461096b578063f887ea401461098b578063f888f220146109bf578063ffffffff1461077357600080fd5b8063e817b38514610925578063effae35314610938578063f06c2dfc1461095857600080fd5b8063c6f33412116100c6578063c6f33412146108b5578063de02cde7146108d5578063e4860339146108f557600080fd5b8063c13b1bd31461086e578063c4d61ff11461088f578063c5dd197b146108a257600080fd5b8063a8ee49fe11610159578063ae93c1b511610133578063ae93c1b5146107f2578063b9af392014610812578063bf1025f314610825578063c03981981461085b57600080fd5b8063a8ee49fe1461078f578063ad82110f146107bf578063adf8d478146107df57600080fd5b806397ff6a041161018a57806397ff6a041461072c57806399d4294014610760578063a4f0d7d01461077357600080fd5b8063782006b6146106e3578063798a828b146106f65780638377be501461071657600080fd5b806349c29d2b1161027f57806360e0b6361161022857806369fe0e2d1161020257806369fe0e2d1461067c5780636c208f101461069c5780636d4756d7146106af57806371e70168146106d057600080fd5b806360e0b6361461061357806366c5b31214610649578063687f0e4c1461065c57600080fd5b806356e596a81161025957806356e596a8146105e05780635909c12f146103bc5780635ba5e9f0146105f357600080fd5b806349c29d2b1461058d578063543645ae146105ad578063559742d9146105c057600080fd5b806324bd54b4116102e15780633fc8cef3116102bb5780633fc8cef31461050e578063441c70f71461055a57806344faded01461056d57600080fd5b806324bd54b4146104a25780632bcc69a0146104cd57806333e6035a146104ee57600080fd5b806310ab94321161031257806310ab94321461044f5780631e897afb1461046f5780632458028a1461048f57600080fd5b80156103bc57806305e64794146103ef5780630a28e95d1461042f57600080fd5b366103b757336001600160a01b037f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab116146103b55760405162461bcd60e51b815260206004820152601660248201527f4f6e6c7920726563656976652066726f6d20574554480000000000000000000060448201526064015b60405180910390fd5b005b600080fd5b3480156103c857600080fd5b506103d1600081565b6040516001600160e01b031990911681526020015b60405180910390f35b3480156103fb57600080fd5b5061041f61040a3660046151bd565b60056020526000908152604090205460ff1681565b60405190151581526020016103e6565b34801561043b57600080fd5b506103b561044a3660046151f7565b6109df565b34801561045b57600080fd5b5061041f61046a36600461564f565b610a97565b61048261047d36600461537b565b610ad2565b6040516103e69190615ae8565b6103b561049d366004615571565b610c1f565b6104b56104b03660046154aa565b610f14565b6040516001600160801b0390911681526020016103e6565b6104e06104db3660046151bd565b61116c565b6040519081526020016103e6565b3480156104fa57600080fd5b506103b5610509366004615743565b6112b5565b34801561051a57600080fd5b506105427f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab181565b6040516001600160a01b0390911681526020016103e6565b6104b5610568366004615454565b61160b565b34801561057957600080fd5b506103b561058836600461564f565b611a25565b34801561059957600080fd5b506103b56105a8366004615743565b611ac1565b6104b56105bb3660046154aa565b611d87565b3480156105cc57600080fd5b506103b56105db366004615634565b611e88565b6103b56105ee366004615849565b611f01565b3480156105ff57600080fd5b506103d161060e366004615634565b611f77565b34801561061f57600080fd5b5061054261062e36600461569e565b6002602052600090815260409020546001600160a01b031681565b6104e061065736600461569e565b611f9c565b34801561066857600080fd5b506103b561067736600461564f565b61205b565b34801561068857600080fd5b506103b5610697366004615a1f565b6120bd565b6104e06106aa3660046156bb565b61215c565b6106c26106bd3660046156fc565b612287565b6040516103e6929190615b4a565b6103b56106de366004615889565b6122ba565b6103b56106f136600461540d565b6123bb565b610709610704366004615428565b612462565b6040516103e69190615ba8565b34801561072257600080fd5b506104e060005481565b34801561073857600080fd5b506105427f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e3081565b6103b561076e366004615454565b61255a565b34801561077f57600080fd5b506103d16001600160e01b031981565b34801561079b57600080fd5b5061041f6107aa3660046151bd565b60046020526000908152604090205460ff1681565b3480156107cb57600080fd5b506103b56107da3660046152b5565b612577565b6104b56107ed366004615502565b612633565b3480156107fe57600080fd5b506103b561080d36600461566b565b6127bb565b6107096108203660046155ae565b612828565b34801561083157600080fd5b5061054261084036600461569e565b6003602052600090815260409020546001600160a01b031681565b6104e0610869366004615428565b612926565b61088161087c3660046155f7565b612ce8565b6040516103e6929190615be3565b6103b561089d3660046157aa565b613314565b6104e06108b0366004615428565b61341e565b6108c86108c3366004615230565b613a8d565b6040516103e69190615b95565b3480156108e157600080fd5b506103b56108f036600461564f565b613bb7565b34801561090157600080fd5b5061041f6109103660046151bd565b60066020526000908152604090205460ff1681565b6108c8610933366004615230565b613c24565b34801561094457600080fd5b506103b56109533660046152b5565b613d06565b6104e061096636600461582b565b613d98565b34801561097757600080fd5b506103b56109863660046151f7565b613e7d565b34801561099757600080fd5b506105427f00000000000000000000000083c4cb8b9eb49a8db87455a5e6bb8f6bb24d42d981565b3480156109cb57600080fd5b506103b56109da3660046151f7565b613eeb565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff16610a435760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b6001600160a01b038216600081815260046020526040808220805460ff191685151590811790915590519092917fb33b04e7f0b1c74e2a082ded974e43bb8434997412d2f8fc32e4224144dbd9fe91a35050565b6001600160e01b0319821660009081526007602090815260408083206001600160a01b038516845290915281205460ff165b90505b92915050565b60608167ffffffffffffffff811115610aed57610aed615ef1565b604051908082528060200260200182016040528015610b2057816020015b6060815260200190600190039081610b0b5790505b50905060005b82811015610c035760008030868685818110610b4457610b44615edb565b9050602002810190610b569190615c34565b604051610b64929190615a7d565b600060405180830381855af49150503d8060008114610b9f576040519150601f19603f3d011682016040523d82523d6000602084013e610ba4565b606091505b509150915081610bd057610bb781613f59565b60405162461bcd60e51b81526004016103ac9190615b95565b80848481518110610be357610be3615edb565b602002602001018190525050508080610bfb90615e5a565b915050610b26565b50600180546bffffffffffffffffffffffff1916905592915050565b6001600160801b03821615610d2857604051631e81f82960e01b81526001600160a01b03198516600482015233906001600160a01b037f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e301690631e81f8299060240160606040518083038186803b158015610c9957600080fd5b505afa158015610cad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd191906159ba565b516001600160a01b031614610d285760405162461bcd60e51b815260206004820152601760248201527f4f6e6c79206f726967696e207661756c74206f776e657200000000000000000060448201526064016103ac565b6001600160801b03811615610e3157604051631e81f82960e01b81526001600160a01b03198416600482015233906001600160a01b037f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e301690631e81f8299060240160606040518083038186803b158015610da257600080fd5b505afa158015610db6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dda91906159ba565b516001600160a01b031614610e315760405162461bcd60e51b815260206004820152601c60248201527f4f6e6c792064657374696e6174696f6e207661756c74206f776e65720000000060448201526064016103ac565b6040517f2458028a0000000000000000000000000000000000000000000000000000000081526001600160a01b03198086166004830152841660248201526001600160801b038084166044830152821660648201527f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b031690632458028a90608401608060405180830381600087803b158015610ed457600080fd5b505af1158015610ee8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0c9190615913565b505050505050565b6000806000610f2287613fb8565b915091506000610f358260200151614152565b90506000610f46836020015161427f565b604051631c8a4a0360e21b81526001600160a01b0319861660048201529091506000906001600160a01b037f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e301690637229280c90602401604080518083038186803b158015610fb457600080fd5b505afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec91906158f7565b835181516040517ffe2846b10000000000000000000000000000000000000000000000000000000081526001600160a01b0392831660048201526001600160801b039182166024820152908a16604482015291925083169063fe2846b190606401602060405180830381600087803b15801561106757600080fd5b505af115801561107b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061109f9190615a02565b95506110cc85858b8b6110be86600001516001600160801b03166142ef565b6110c790615e95565b61434e565b6040517ffa2968790000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0383169063fa29687990602401602060405180830381600087803b15801561112657600080fd5b505af115801561113a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115e9190615a02565b505050505050949350505050565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b0316906370a082319060240160206040518083038186803b1580156111ce57600080fd5b505afa1580156111e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112069190615a38565b6040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018290529091507f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561128457600080fd5b505af1158015611298573d6000803e3d6000fd5b506112b0925050506001600160a01b03831682614737565b919050565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff166113195760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b600061132483614152565b600001519050816001600160a01b031663dc3bfba96040518163ffffffff1660e01b815260040160206040518083038186803b15801561136357600080fd5b505afa158015611377573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139b91906151da565b6001600160a01b0316816001600160a01b0316146114215760405162461bcd60e51b815260206004820152602260248201527f4d69736d61746368656420706f6f6c206679546f6b656e20616e64207365726960448201527f657300000000000000000000000000000000000000000000000000000000000060648201526084016103ac565b816001600160a01b0316635001f3b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561145a57600080fd5b505afa15801561146e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149291906151da565b6001600160a01b0316816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156114d457600080fd5b505afa1580156114e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061150c91906151da565b6001600160a01b0316146115625760405162461bcd60e51b815260206004820152601f60248201527f4d69736d61746368656420706f6f6c206261736520616e64207365726965730060448201526064016103ac565b6001600160d01b03198316600090815260036020526040812080546001600160a01b0319166001600160a01b0385169081179091556115a25760006115a5565b60015b90506115b182826147bc565b6115bb83826147bc565b6115c58382614810565b6040516001600160a01b038416906001600160d01b03198616907f9b2f85ba13740543525ad2d1fc97e976093cce223fd72bdd789866b884470b3890600090a350505050565b60008082600f0b1261165f5760405162461bcd60e51b815260206004820152600f60248201527f4f6e6c792072657061792064656274000000000000000000000000000000000060448201526064016103ac565b60008061166b87613fb8565b91509150600061167e8260200151614152565b90507f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b031663550b02538360200151876116be90615e95565b6040516001600160e01b031960e085901b1681526001600160d01b031990921660048301526001600160801b03166024820152604401602060405180830381600087803b15801561170e57600080fd5b505af1158015611722573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117469190615a02565b6040517fae8ad4920000000000000000000000000000000000000000000000000000000081526001600160a01b031985166004820152600f88810b602483015287900b60448201529094507f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b03169063ae8ad492906064016040805180830381600087803b1580156117de57600080fd5b505af11580156117f2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181691906158f7565b5085600f0b60001461197e5760006118318360400151614864565b9050600087600f0b13156118ce57825160405163ceae3abd60e01b81526001600160a01b0391821660048201526001600160801b03891660248201529082169063ceae3abd90604401602060405180830381600087803b15801561189457600080fd5b505af11580156118a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118cc9190615a02565b505b600087600f0b121561197c576001600160a01b0381166312e5ff77896118f38a615e95565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401602060405180830381600087803b15801561194257600080fd5b505af1158015611956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197a9190615a02565b505b505b600061198d8260200151614864565b60405163ceae3abd60e01b81523360048201526001600160801b03871660248201529091506001600160a01b0382169063ceae3abd90604401602060405180830381600087803b1580156119e057600080fd5b505af11580156119f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a189190615a02565b5050505050949350505050565b81611a79611a4f826001600160e01b03191660009081526007602052604090206001015460e01b90565b6001600160e01b031916600090815260076020908152604080832033845290915290205460ff1690565b611ab25760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b611abc83836148d4565b505050565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff16611b255760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b604051630cdf468960e11b81526001600160d01b0319831660048201526000907f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b0316906319be8d129060240160206040518083038186803b158015611b9157600080fd5b505afa158015611ba5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bc991906151da565b90506001600160a01b038116611c215760405162461bcd60e51b815260206004820152600f60248201527f4173736574206e6f7420666f756e64000000000000000000000000000000000060448201526064016103ac565b806001600160a01b0316826001600160a01b03166338d52e0f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c6457600080fd5b505afa158015611c78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9c91906151da565b6001600160a01b031614611cf25760405162461bcd60e51b815260206004820152601960248201527f4d69736d61746368656420617373657420616e64206a6f696e0000000000000060448201526064016103ac565b6001600160d01b03198316600090815260026020526040812080546001600160a01b0319166001600160a01b038516908117909155611d32576000611d35565b60015b9050611d4182826147bc565b6040516001600160a01b038416906001600160d01b03198616907fa165be0a6237b515a1722eaa2ac0d02a97a7a04e0b31261556003a46c08cbf9f90600090a350505050565b6000806000611d9587613fb8565b915091506000611da88260200151614152565b90506000611db9836020015161427f565b82516040517fbcc1694f0000000000000000000000000000000000000000000000000000000081526001600160a01b0391821660048201526001600160801b038916602482015291925082169063bcc1694f90604401602060405180830381600087803b158015611e2957600080fd5b505af1158015611e3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e619190615a02565b9450611e7c84848a8a6110be8a6001600160801b03166142ef565b50505050949350505050565b80611eb2611a4f826001600160e01b03191660009081526007602052604090206001015460e01b90565b611eeb5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b611efd826001600160e01b031961496c565b5050565b6001600160a01b03831660009081526006602052604090205460ff16611f595760405162461bcd60e51b815260206004820152600d60248201526c2ab735b737bbb7103a37b5b2b760991b60448201526064016103ac565b611abc6001600160a01b03841633846001600160801b038516614a08565b6001600160e01b0319811660009081526007602052604081206001015460e01b610acc565b476000611fa883614864565b90507f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004016000604051808303818588803b15801561200557600080fd5b505af1158015612019573d6000803e3d6000fd5b506120559350506001600160a01b037f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab116915083905084614b13565b50919050565b6001600160a01b03811633146120b35760405162461bcd60e51b815260206004820152601660248201527f52656e6f756e6365206f6e6c7920666f722073656c660000000000000000000060448201526064016103ac565b611efd82826148d4565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff166121215760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b60008190556040518181527f20461e09b8e557b77e107939f9ce6544698123aad0fc964ac5cc59b7df2e608f9060200160405180910390a150565b60008061216885614152565b5190506001600160a01b038116631e9a695085856121fc576040516370a0823160e01b81523060048201526001600160a01b038516906370a082319060240160206040518083038186803b1580156121bf57600080fd5b505afa1580156121d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121f79190615a38565b6121fe565b855b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381600087803b15801561224457600080fd5b505af1158015612258573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227c9190615a38565b9150505b9392505050565b604080516060810182526000808252602082018190529181018290526122ae858585614c1d565b91509150935093915050565b6001600160a01b03871660009081526006602052604090205460ff166123125760405162461bcd60e51b815260206004820152600d60248201526c2ab735b737bbb7103a37b5b2b760991b60448201526064016103ac565b6040517fd505accf0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b038781166024830152604482018790526064820186905260ff8516608483015260a4820184905260c4820183905288169063d505accf9060e4015b600060405180830381600087803b15801561239a57600080fd5b505af11580156123ae573d6000803e3d6000fd5b5050505050505050505050565b60006123c682613fb8565b506040517f782006b60000000000000000000000000000000000000000000000000000000081526001600160a01b0319821660048201529091507f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b03169063782006b690602401600060405180830381600087803b15801561244e57600080fd5b505af1158015610f0c573d6000803e3d6000fd5b604080516060810182526000808252602082018190529181018290529061248884613fb8565b506040517f798a828b0000000000000000000000000000000000000000000000000000000081526001600160a01b0319821660048201526001600160a01b0385811660248301529192507f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e309091169063798a828b90604401606060405180830381600087803b15801561251a57600080fd5b505af115801561252e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255291906159ba565b949350505050565b60008061256686613fb8565b91509150610f0c828287878761434e565b60005b8251811015611abc576125c5611a4f84838151811061259b5761259b615edb565b60200260200101516001600160e01b03191660009081526007602052604090206001015460e01b90565b6125fe5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b61262183828151811061261357612613615edb565b6020026020010151836148d4565b8061262b81615e5a565b91505061257a565b600080600061264188613fb8565b915091506000612654826020015161427f565b6040517fb0f289210000000000000000000000000000000000000000000000000000000081526001600160801b03881660048201529091506001600160a01b0382169063b0f289219060240160206040518083038186803b1580156126b857600080fd5b505afa1580156126cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f09190615a02565b935061271c83838361270a8b6001600160801b03166142ef565b6110c7896001600160801b03166142ef565b6040516327af726d60e21b81526001600160a01b0389811660048301526001600160801b03808916602484015287166044830152821690639ebdc9b490606401602060405180830381600087803b15801561277657600080fd5b505af115801561278a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ae9190615a02565b5050505095945050505050565b816127e5611a4f826001600160e01b03191660009081526007602052604090206001015460e01b90565b61281e5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b611abc838361496c565b604080516060810182526000808252602082018190529181018290529061284e85613fb8565b506040517fb9af39200000000000000000000000000000000000000000000000000000000081526001600160a01b0319821660048201526001600160d01b03198087166024830152851660448201529091507f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b03169063b9af392090606401606060405180830381600087803b1580156128ee57600080fd5b505af1158015612902573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061227c91906159ba565b600080600061293485613fb8565b9150915060006129478260200151614152565b604051631c8a4a0360e21b81526001600160a01b0319851660048201529091506000906001600160a01b037f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e301690637229280c90602401604080518083038186803b1580156129b557600080fd5b505afa1580156129c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ed91906158f7565b82516040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015612a3557600080fd5b505afa158015612a49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6d9190615a38565b82519091506001600160801b0316811115612a925781516001600160801b0316612a94565b805b95508515612cab577f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b031663ae8ad49286612ad589614ee0565b612ade90615e95565b612ae78a614ee0565b612af090615e95565b6040516001600160e01b031960e086901b1681526001600160a01b03199093166004840152600f91820b6024840152900b60448201526064016040805180830381600087803b158015612b4257600080fd5b505af1158015612b56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b7a91906158f7565b5082516040517f9dc29fac000000000000000000000000000000000000000000000000000000008152306004820152602481018890526001600160a01b0390911690639dc29fac90604401600060405180830381600087803b158015612bdf57600080fd5b505af1158015612bf3573d6000803e3d6000fd5b505050506000612c068560400151614864565b9050806001600160a01b03166312e5ff7789612c218a614f32565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401602060405180830381600087803b158015612c7057600080fd5b505af1158015612c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca89190615a02565b50505b6000612cb78783615e17565b1115612cdd57612cdd87612ccb8884615e17565b85516001600160a01b03169190614b13565b505050505092915050565b604080516060810182526000808252602082018190529181018290529080612d0f87613fb8565b604051631c8a4a0360e21b81526001600160a01b0319831660048201529094509091506000907f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b031690637229280c90602401604080518083038186803b158015612d8057600080fd5b505afa158015612d94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612db891906158f7565b90506000612dc98560200151614152565b90506000612dd689614152565b90506000612de38a61427f565b8251602085015191925090600090612dfa90614864565b60208a0151875160405163550b025360e01b81526001600160d01b031990921660048301526001600160801b031660248201529091506000907f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b03169063550b025390604401602060405180830381600087803b158015612e8157600080fd5b505af1158015612e95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612eb99190615a02565b9050826001600160a01b03166340c10f19858e60ff1684612eda9190615d3f565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401600060405180830381600087803b158015612f2957600080fd5b505af1158015612f3d573d6000803e3d6000fd5b50506040516327af726d60e21b81526001600160a01b0385811660048301526001600160801b0380861660248401528f16604483015287169250639ebdc9b49150606401602060405180830381600087803b158015612f9b57600080fd5b505af1158015612faf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd39190615a02565b60405163ceae3abd60e01b81526001600160a01b038416600482018190526001600160801b0384166024830152919a5063ceae3abd90604401602060405180830381600087803b15801561302657600080fd5b505af115801561303a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061305e9190615a02565b506040517fd3d00f240000000000000000000000000000000000000000000000000000000081526001600160a01b03848116600483015285169063d3d00f2490602401602060405180830381600087803b1580156130bb57600080fd5b505af11580156130cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130f39190615a02565b50826001600160a01b0316639dc29fac848b8f60ff16856131149190615d3f565b61311e9190615def565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401600060405180830381600087803b15801561316d57600080fd5b505af1158015613181573d6000803e3d6000fd5b505050505050505080602001516001600160d01b03191686604001516001600160d01b031916141580156131b6575060005415155b1561320e576132016131dc600054876001600160801b0316614f7b90919063ffffffff16565b42836040015163ffffffff166131f29190615e17565b6131fc9190615d6e565b614f32565b61320b9086615d14565b94505b7f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b0316636295afac858b61325587600001516001600160801b03166142ef565b6132678a6001600160801b03166142ef565b6132719190615d8d565b6040516001600160e01b031960e086901b1681526001600160a01b031990931660048401526001600160d01b03199091166024830152600f0b604482015260640160a060405180830381600087803b1580156132cc57600080fd5b505af11580156132e0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330491906159d6565b5095505050505094509492505050565b6001600160a01b03881660009081526006602052604090205460ff1661336c5760405162461bcd60e51b815260206004820152600d60248201526c2ab735b737bbb7103a37b5b2b760991b60448201526064016103ac565b6040517f8fcbaf0c0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0388811660248301526044820188905260648201879052851515608483015260ff851660a483015260c4820184905260e48201839052891690638fcbaf0c9061010401600060405180830381600087803b1580156133fc57600080fd5b505af1158015613410573d6000803e3d6000fd5b505050505050505050505050565b600080600061342c85613fb8565b91509150600061343f8260200151614152565b604051631c8a4a0360e21b81526001600160a01b0319851660048201529091506000906001600160a01b037f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e301690637229280c90602401604080518083038186803b1580156134ad57600080fd5b505afa1580156134c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134e591906158f7565b6020830151604051630cdf468960e11b81526001600160d01b031990911660048201529091506000906001600160a01b037f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e3016906319be8d129060240160206040518083038186803b15801561355a57600080fd5b505afa15801561356e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061359291906151da565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a082319060240160206040518083038186803b1580156135d757600080fd5b505afa1580156135eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061360f9190615a38565b6020860151845160405163550b025360e01b81526001600160d01b031990921660048301526001600160801b031660248201529091506000907f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b03169063550b025390604401602060405180830381600087803b15801561369657600080fd5b505af11580156136aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ce9190615a02565b6001600160801b0316905060006136f2828411156136ec5782614f32565b83614f32565b905081816001600160801b0316146137da5760208701516040517f9dd6c00e0000000000000000000000000000000000000000000000000000000081526001600160d01b031990911660048201526001600160801b03821660248201527f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b031690639dd6c00e90604401602060405180830381600087803b15801561379d57600080fd5b505af11580156137b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137d59190615a02565b6137dd565b84515b6001600160801b039081169950811615613a3c577f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b031663ae8ad4928961382a8c614ee0565b61383390615e95565b61383c8d614ee0565b61384590615e95565b6040516001600160e01b031960e086901b1681526001600160a01b03199093166004840152600f91820b6024840152900b60448201526064016040805180830381600087803b15801561389757600080fd5b505af11580156138ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138cf91906158f7565b5060006138df8760200151614864565b90506138fe6001600160a01b038616826001600160801b038516614b13565b60405163ceae3abd60e01b81523060048201526001600160801b03831660248201526001600160a01b0382169063ceae3abd90604401602060405180830381600087803b15801561394e57600080fd5b505af1158015613962573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139869190615a02565b5060006139968960400151614864565b9050806001600160a01b03166312e5ff778d6139b18e614f32565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401602060405180830381600087803b158015613a0057600080fd5b505af1158015613a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a389190615a02565b5050505b6000613a516001600160801b03831685615e17565b1115613a7f57613a7f8a613a6e6001600160801b03841686615e17565b6001600160a01b0387169190614b13565b505050505050505092915050565b6001600160a01b03831660009081526005602052604090205460609060ff16613af85760405162461bcd60e51b815260206004820152601360248201527f556e6b6e6f776e20696e746567726174696f6e0000000000000000000000000060448201526064016103ac565b6040517fc6f334120000000000000000000000000000000000000000000000000000000081526001600160a01b037f00000000000000000000000083c4cb8b9eb49a8db87455a5e6bb8f6bb24d42d9169063c6f3341290613b6190879087908790600401615aa9565b600060405180830381600087803b158015613b7b57600080fd5b505af1158015613b8f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526125529190810190615761565b81613be1611a4f826001600160e01b03191660009081526007602052604090206001015460e01b90565b613c1a5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b611abc8383614f99565b6001600160a01b03831660009081526004602052604090205460609060ff16613c8f5760405162461bcd60e51b815260206004820152601360248201527f556e72656769737465726564206d6f64756c650000000000000000000000000060448201526064016103ac565b6000846001600160a01b03168484604051613cab929190615a7d565b600060405180830381855af49150503d8060008114613ce6576040519150601f19603f3d011682016040523d82523d6000602084013e613ceb565b606091505b509250905080613cfe57610bb782613f59565b509392505050565b60005b8251811015611abc57613d2a611a4f84838151811061259b5761259b615edb565b613d635760405162461bcd60e51b815260206004820152600a60248201526927b7363c9030b236b4b760b11b60448201526064016103ac565b613d86838281518110613d7857613d78615edb565b602002602001015183614f99565b80613d9081615e5a565b915050613d09565b6001600160a01b03821660009081526006602052604081205460ff16613df05760405162461bcd60e51b815260206004820152600d60248201526c2ab735b737bbb7103a37b5b2b760991b60448201526064016103ac565b6040516370a0823160e01b81523060048201526001600160a01b038416906370a082319060240160206040518083038186803b158015613e2f57600080fd5b505afa158015613e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e679190615a38565b9050610acc6001600160a01b0384168383614b13565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff16613ee15760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b611efd82826147bc565b600080356001600160e01b031916815260076020908152604080832033845290915290205460ff16613f4f5760405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b60448201526064016103ac565b611efd8282614810565b6060604482511015613f9e57505060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c79000000602082015290565b60048201915081806020019051810190610acc9190615761565b604080516060810182526000808252602082018190529181018290526001600160a01b0319831661404c5760015460a01b6001600160a01b03191661403f5760405162461bcd60e51b815260206004820152601060248201527f5661756c74206e6f74206361636865640000000000000000000000000000000060448201526064016103ac565b60015460a01b9150614050565b8291505b604051631e81f82960e01b81526001600160a01b0319831660048201527f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b031690631e81f8299060240160606040518083038186803b1580156140b957600080fd5b505afa1580156140cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140f191906159ba565b80519091506001600160a01b0316331461414d5760405162461bcd60e51b815260206004820152601060248201527f4f6e6c79207661756c74206f776e65720000000000000000000000000000000060448201526064016103ac565b915091565b604080516060810182526000808252602082018190528183015290517f55d03e340000000000000000000000000000000000000000000000000000000081526001600160d01b0319831660048201526001600160a01b037f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e3016906355d03e349060240160606040518083038186803b1580156141ed57600080fd5b505afa158015614201573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614225919061593f565b80519091506001600160a01b03166112b05760405162461bcd60e51b815260206004820152601060248201527f536572696573206e6f7420666f756e640000000000000000000000000000000060448201526064016103ac565b6001600160d01b031981166000908152600360205260409020546001600160a01b0316806112b05760405162461bcd60e51b815260206004820152600e60248201527f506f6f6c206e6f7420666f756e6400000000000000000000000000000000000060448201526064016103ac565b60006f7fffffffffffffffffffffffffffffff6001600160801b038316111561434a5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b60448201526064016103ac565b5090565b604080516060810182526000808252602082018190529181019190915281600f0b600014614386576143838560200151614152565b90505b60008083600f0b1380156143b6575081602001516001600160d01b03191686604001516001600160d01b03191614155b80156143c3575060005415155b1561440b576144086143e360005485600f0b614f7b90919063ffffffff16565b42846040015163ffffffff166143f99190615e17565b6144039190615d6e565b614ee0565b90505b6001600160a01b037f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e301663ae8ad49288866144468588615cb3565b6040516001600160e01b031960e086901b1681526001600160a01b03199093166004840152600f91820b6024840152900b60448201526064016040805180830381600087803b15801561449857600080fd5b505af11580156144ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144d091906158f7565b5083600f0b6000146146385760006144eb8760400151614864565b9050600085600f0b131561458857865160405163ceae3abd60e01b81526001600160a01b0391821660048201526001600160801b03871660248201529082169063ceae3abd90604401602060405180830381600087803b15801561454e57600080fd5b505af1158015614562573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145869190615a02565b505b600085600f0b1215614636576001600160a01b0381166312e5ff77876145ad88615e95565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401602060405180830381600087803b1580156145fc57600080fd5b505af1158015614610573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146349190615a02565b505b505b82600f0b60001461472e57600083600f0b13156146da5781516040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301526001600160801b0386166024830152909116906340c10f1990604401600060405180830381600087803b1580156146bd57600080fd5b505af11580156146d1573d6000803e3d6000fd5b5050505061472e565b81516001600160a01b0316639dc29fac336146f486615e95565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526001600160801b03166024820152604401612380565b50505050505050565b60408051600080825260208201928390529182916001600160a01b03861691859161476191615a8d565b60006040518083038185875af1925050503d806000811461479e576040519150601f19603f3d011682016040523d82523d6000602084013e6147a3565b606091505b5091509150816147b657610bb781613f59565b50505050565b6001600160a01b038216600081815260066020526040808220805460ff191685151590811790915590519092917f654ff2be0f58b1b437adcc6ff9868ab309fc9979c02811bca8f9a7bd95a217b691a35050565b6001600160a01b038216600081815260056020526040808220805460ff191685151590811790915590519092917f3f708a815f33c6ad64cc991b28ca6b465b31c3d0b7459b295fb3f095cd76c54291a35050565b6001600160d01b031981166000908152600260205260409020546001600160a01b0316806112b05760405162461bcd60e51b815260206004820152600e60248201527f4a6f696e206e6f7420666f756e6400000000000000000000000000000000000060448201526064016103ac565b6001600160e01b0319821660009081526007602090815260408083206001600160a01b038516845290915290205460ff1615611efd576001600160e01b0319821660008181526007602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339391927f4ddc7b757e7bdd7254a9cd39452d307a52761bc824625c6a33104a075d8099e691a45050565b6001600160e01b0319811661499d836001600160e01b03191660009081526007602052604090206001015460e01b90565b6001600160e01b03191614611efd576001600160e01b0319828116600081815260076020526040808220600101805463ffffffff191660e087901c17905551928416927fd348e2220a50b4500ec353f6e802d2f14dd1b5d6786148fd1bbcc570bf92d4739190a35050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691614a9a9190615a8d565b6000604051808303816000865af19150503d8060008114614ad7576040519150601f19603f3d011682016040523d82523d6000602084013e614adc565b606091505b5091509150818015614b06575080511580614b06575080806020019051810190614b0691906153f0565b610f0c57610bb781613f59565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691614b9d9190615a8d565b6000604051808303816000865af19150503d8060008114614bda576040519150601f19603f3d011682016040523d82523d6000602084013e614bdf565b606091505b5091509150818015614c09575080511580614c09575080806020019051810190614c0991906153f0565b614c1657610bb781613f59565b5050505050565b60408051606080820183526000808352602080840182905283850182905284513390931b6bffffffffffffffffffffffff19168382015242603484015260f886901b7fff000000000000000000000000000000000000000000000000000000000000001660548401528451603581850301815260559093019094528151919093012091505b604051631e81f82960e01b81526001600160a01b0319831660048201526000907f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b031690631e81f8299060240160606040518083038186803b158015614d0e57600080fd5b505afa158015614d22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614d4691906159ba565b602001516001600160d01b03191614614ddf57614dd8614d6584615e75565b9350836040516bffffffffffffffffffffffff193360601b1660208201524260348201527fff0000000000000000000000000000000000000000000000000000000000000060f883901b166054820152600090605501604051602081830303815290604052805190602001209050919050565b9150614ca2565b6040517f272c0a6e0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0319831660248201526001600160d01b03198087166044830152851660648201527f00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e306001600160a01b03169063272c0a6e90608401606060405180830381600087803b158015614e8157600080fd5b505af1158015614e95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614eb991906159ba565b600180546bffffffffffffffffffffffff191660a085901c17905591959194509092505050565b60006f7fffffffffffffffffffffffffffffff82111561434a5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b60448201526064016103ac565b60006001600160801b0382111561434a5760405162461bcd60e51b815260206004820152600d60248201526c43617374206f766572666c6f7760981b60448201526064016103ac565b6000614f878284615d6e565b670de0b6b3a764000090049392505050565b6001600160e01b0319821660009081526007602090815260408083206001600160a01b038516845290915290205460ff16611efd576001600160e01b0319821660008181526007602090815260408083206001600160a01b0386168085529252808320805460ff1916600117905551339391927fe6231789d19137da31d0550f4ba9ee379020a8cfb64cb79bf1790c996d2e616591a45050565b600067ffffffffffffffff83111561504d5761504d615ef1565b615060601f8401601f1916602001615c82565b905082815283838301111561507457600080fd5b612280836020830184615e2e565b80356112b081615f07565b80356001600160a01b0319811681146112b057600080fd5b80356001600160e01b0319811681146112b057600080fd5b8035600f81900b81146112b057600080fd5b6000604082840312156150e157600080fd5b6040516040810181811067ffffffffffffffff8211171561510457615104615ef1565b8060405250809150825161511781615f43565b8152602083015161512781615f43565b6020919091015292915050565b60006060828403121561514657600080fd5b6040516060810181811067ffffffffffffffff8211171561516957615169615ef1565b8060405250809150825161517c81615f07565b8152602083015161518c81615f2d565b6020820152604083015161519f81615f2d565b6040919091015292915050565b803560ff811681146112b057600080fd5b6000602082840312156151cf57600080fd5b813561228081615f07565b6000602082840312156151ec57600080fd5b815161228081615f07565b6000806040838503121561520a57600080fd5b823561521581615f07565b9150602083013561522581615f1f565b809150509250929050565b60008060006040848603121561524557600080fd5b833561525081615f07565b9250602084013567ffffffffffffffff8082111561526d57600080fd5b818601915086601f83011261528157600080fd5b81358181111561529057600080fd5b8760208285010111156152a257600080fd5b6020830194508093505050509250925092565b600080604083850312156152c857600080fd5b823567ffffffffffffffff808211156152e057600080fd5b818501915085601f8301126152f457600080fd5b813560208282111561530857615308615ef1565b8160051b9250615319818401615c82565b8281528181019085830185870184018b101561533457600080fd5b600096505b8487101561535e5761534a816150a5565b835260019690960195918301918301615339565b50965061536e9050878201615082565b9450505050509250929050565b6000806020838503121561538e57600080fd5b823567ffffffffffffffff808211156153a657600080fd5b818501915085601f8301126153ba57600080fd5b8135818111156153c957600080fd5b8660208260051b85010111156153de57600080fd5b60209290920196919550909350505050565b60006020828403121561540257600080fd5b815161228081615f1f565b60006020828403121561541f57600080fd5b610ac98261508d565b6000806040838503121561543b57600080fd5b6154448361508d565b9150602083013561522581615f07565b6000806000806080858703121561546a57600080fd5b6154738561508d565b9350602085013561548381615f07565b9250615491604086016150bd565b915061549f606086016150bd565b905092959194509250565b600080600080608085870312156154c057600080fd5b6154c98561508d565b935060208501356154d981615f07565b92506154e7604086016150bd565b915060608501356154f781615f43565b939692955090935050565b600080600080600060a0868803121561551a57600080fd5b6155238661508d565b9450602086013561553381615f07565b9350604086013561554381615f43565b9250606086013561555381615f43565b9150608086013561556381615f43565b809150509295509295909350565b6000806000806080858703121561558757600080fd5b6155908561508d565b935061559e6020860161508d565b925060408501356154e781615f43565b6000806000606084860312156155c357600080fd5b6155cc8461508d565b925060208401356155dc81615f2d565b915060408401356155ec81615f2d565b809150509250925092565b6000806000806080858703121561560d57600080fd5b6156168561508d565b9350602085013561562681615f2d565b92506154e7604086016151ac565b60006020828403121561564657600080fd5b610ac9826150a5565b6000806040838503121561566257600080fd5b615444836150a5565b6000806040838503121561567e57600080fd5b615687836150a5565b9150615695602084016150a5565b90509250929050565b6000602082840312156156b057600080fd5b813561228081615f2d565b6000806000606084860312156156d057600080fd5b83356156db81615f2d565b925060208401356156eb81615f07565b929592945050506040919091013590565b60008060006060848603121561571157600080fd5b833561571c81615f2d565b9250602084013561572c81615f2d565b915061573a604085016151ac565b90509250925092565b6000806040838503121561575657600080fd5b823561544481615f2d565b60006020828403121561577357600080fd5b815167ffffffffffffffff81111561578a57600080fd5b8201601f8101841361579b57600080fd5b61255284825160208401615033565b600080600080600080600080610100898b0312156157c757600080fd5b88356157d281615f07565b975060208901356157e281615f07565b96506040890135955060608901359450608089013561580081615f1f565b935061580e60a08a016151ac565b925060c0890135915060e089013590509295985092959890939650565b6000806040838503121561583e57600080fd5b823561544481615f07565b60008060006060848603121561585e57600080fd5b833561586981615f07565b9250602084013561587981615f07565b915060408401356155ec81615f43565b600080600080600080600060e0888a0312156158a457600080fd5b87356158af81615f07565b965060208801356158bf81615f07565b955060408801359450606088013593506158db608089016151ac565b925060a0880135915060c0880135905092959891949750929550565b60006040828403121561590957600080fd5b610ac983836150cf565b6000806080838503121561592657600080fd5b61593084846150cf565b915061569584604085016150cf565b60006060828403121561595157600080fd5b6040516060810181811067ffffffffffffffff8211171561597457615974615ef1565b604052825161598281615f07565b8152602083015161599281615f2d565b6020820152604083015163ffffffff811681146159ae57600080fd5b60408201529392505050565b6000606082840312156159cc57600080fd5b610ac98383615134565b60008060a083850312156159e957600080fd5b6159f38484615134565b915061569584606085016150cf565b600060208284031215615a1457600080fd5b815161228081615f43565b600060208284031215615a3157600080fd5b5035919050565b600060208284031215615a4a57600080fd5b5051919050565b60008151808452615a69816020860160208601615e2e565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b60008251615a9f818460208701615e2e565b9190910192915050565b6001600160a01b038416815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015615b3d57603f19888603018452615b2b858351615a51565b94509285019290850190600101615b0f565b5092979650505050505050565b6001600160a01b03198316815260808101612280602083018480516001600160a01b031682526020808201516001600160d01b03199081169184019190915260409182015116910152565b602081526000610ac96020830184615a51565b60608101610acc828480516001600160a01b031682526020808201516001600160d01b03199081169184019190915260409182015116910152565b60808101615c1e828580516001600160a01b031682526020808201516001600160d01b03199081169184019190915260409182015116910152565b6001600160801b03831660608301529392505050565b6000808335601e19843603018112615c4b57600080fd5b83018035915067ffffffffffffffff821115615c6657600080fd5b602001915036819003821315615c7b57600080fd5b9250929050565b604051601f8201601f1916810167ffffffffffffffff81118282101715615cab57615cab615ef1565b604052919050565b600081600f0b83600f0b60008212826f7fffffffffffffffffffffffffffffff03821381151615615ce657615ce6615ec5565b826f7fffffffffffffffffffffffffffffff19038212811615615d0b57615d0b615ec5565b50019392505050565b60006001600160801b03808316818516808303821115615d3657615d36615ec5565b01949350505050565b60006001600160801b0380831681851681830481118215151615615d6557615d65615ec5565b02949350505050565b6000816000190483118215151615615d8857615d88615ec5565b500290565b600081600f0b83600f0b60008112816f7fffffffffffffffffffffffffffffff1901831281151615615dc157615dc1615ec5565b816f7fffffffffffffffffffffffffffffff018313811615615de557615de5615ec5565b5090039392505050565b60006001600160801b0383811690831681811015615e0f57615e0f615ec5565b039392505050565b600082821015615e2957615e29615ec5565b500390565b60005b83811015615e49578181015183820152602001615e31565b838111156147b65750506000910152565b6000600019821415615e6e57615e6e615ec5565b5060010190565b600060ff821660ff811415615e8c57615e8c615ec5565b60010192915050565b600081600f0b6f7fffffffffffffffffffffffffffffff19811415615ebc57615ebc615ec5565b60000392915050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114615f1c57600080fd5b50565b8015158114615f1c57600080fd5b6001600160d01b031981168114615f1c57600080fd5b6001600160801b0381168114615f1c57600080fdfea2646970667358221220ae01d45ee6c6a09dfe0c3e223faf6816094293643ec80556eebeda564144840b64736f6c63430008060033

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

00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e3000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1

-----Decoded View---------------
Arg [0] : cauldron (address): 0x23cc87FBEBDD67ccE167Fa9Ec6Ad3b7fE3892E30
Arg [1] : weth (address): 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000023cc87fbebdd67cce167fa9ec6ad3b7fe3892e30
Arg [1] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1


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