Contract 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c 2

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x07aa21a9b580ba32c3bb404ded618c7995e6a82931f7174ea1c8a42cd01b80060x6080604047042442022-01-16 17:46:48123 days 11 hrs ago0xb8f02248d53f7edfa38e79263e743e9390f81942 IN  Create: FusePoolDirectoryArbitrum0 ETH0.088832177274 ETH
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x28a913c9fea5c5b7ccdf2eddf2f7d55f23ac458add148abbda7a553728cb4215119311822022-05-12 19:07:587 days 9 hrs ago 0x11e658214247565568d6a0c0fd8e54c58f0b27d0 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xde09a67658a91f3cd9d40d03cf0afd74c33a0c4f9a58db16620c82bd1ff44eed107242612022-04-28 8:37:2821 days 20 hrs ago 0xf28225edafa505a8bcf1a034442c89e0675fca24 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x0aa50e550488ac9e0007176a29fd78c14599bf5fac7659de39871a1fd8cb13a2107005702022-04-28 1:40:4122 days 3 hrs ago 0xff75e131c711e4310c045317779d39b3b4f718c4 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x4c30d1b760a352314aa86b498e68319c99119a5cadb2cf01113c5fab185db1a7105707802022-04-26 9:11:1423 days 19 hrs ago 0x1e96682fadd54a2ff49d8e906da4d04ea119fe99 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x2c53e0a7773314809b28308e8b5dcea3bd121c21495478b2d2c08ece2537f67a105707452022-04-26 9:10:2623 days 19 hrs ago 0x1e96682fadd54a2ff49d8e906da4d04ea119fe99 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x2258a739b5ec7ec67f8c7fa6b8c9543ea5eba86a634e1d68b4db31dc65c4d935105027822022-04-25 6:52:3824 days 21 hrs ago 0xf28225edafa505a8bcf1a034442c89e0675fca24 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xd00cfec77e0b8379ef8f02e595a0be9fcfd9387d0f32d3699a4eb3a29c1d930c104781482022-04-24 20:27:5525 days 8 hrs ago 0xf23ea0b5f14afcbe532a1df273f7b233ebe41c78 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x9efba3d8ebc7e1d3f77e73da7ab89bf280d4d2af9fc87d3d19ceb6e35e4ade1b100665802022-04-19 2:22:4231 days 2 hrs ago 0xf28225edafa505a8bcf1a034442c89e0675fca24 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xc4681998d9ab89927b4d235c7460b0725ad9e8d9b0dcf63f091eb80891840fa2100665252022-04-19 2:21:3231 days 2 hrs ago 0xf28225edafa505a8bcf1a034442c89e0675fca24 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xb3f73f864cb99bc97b554d307b1436ef19895497981abe565aadce72f538ffef100169252022-04-18 8:10:4431 days 20 hrs ago 0xc201b8c8dd22c779025e16f1825c90e1e6dd6a08 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x4d6aa071fbaaa7a303b36e9d23970b21dc0ad8d3fa0060a19cc425203636a80e100161022022-04-18 7:49:1831 days 20 hrs ago 0xc201b8c8dd22c779025e16f1825c90e1e6dd6a08 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x0bab1a856dfb6d6104bd6227e63319e3a132c82dca8bf6f8aa8db3ece1cfda56100158552022-04-18 7:42:5531 days 21 hrs ago 0xc201b8c8dd22c779025e16f1825c90e1e6dd6a08 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x24426d3da0d7c6eebf06df311eef5346c56e8afe281eb82c5ac64ee350b67982100144152022-04-18 7:11:2431 days 21 hrs ago 0x23cbf6d1b738423365c6930f075ed6feef7d14f3 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xa2f6241e561e1e29117f38eed5acabd70bd2fbdff37b220b87453c15a130f047100143562022-04-18 7:10:5131 days 21 hrs ago 0x23cbf6d1b738423365c6930f075ed6feef7d14f3 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x100058024c4d198226c85e2a89bdd574ca386af5729d3f8c7478f573a9fe3a19100142062022-04-18 7:07:3031 days 21 hrs ago 0x23cbf6d1b738423365c6930f075ed6feef7d14f3 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xd35948619af18628f253e998f6f417eb779a0de34be0f732375610b80fa53f9199680862022-04-17 12:51:2332 days 15 hrs ago 0x23cbf6d1b738423365c6930f075ed6feef7d14f3 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xc7d78e8035853de6b123af45d57630a2dbd4b031ce1ab88975e6de87e673732e99590542022-04-17 9:13:4832 days 19 hrs ago 0x23cbf6d1b738423365c6930f075ed6feef7d14f3 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x848f6af1e774be9959115786759872e045eaf5646032647431d8ed097923b43a99449362022-04-17 2:55:5933 days 1 hr ago 0x91f3be13569e134cbccd5bb33bd3eedd41cf71ba 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xcbef55afa118f32fcc3b5de33fe981a0ece1b67aa98651a709489151b8139a6299441992022-04-17 2:39:5433 days 2 hrs ago 0x91f3be13569e134cbccd5bb33bd3eedd41cf71ba 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x0f5386fab187843eb0b4e042acfe2ba1a2ec9905fac99880d61d3c6b1460ff1799441442022-04-17 2:38:4233 days 2 hrs ago 0x91f3be13569e134cbccd5bb33bd3eedd41cf71ba 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xe425ed9e3c5731b6b4183e1fc0a66f9139b134988ccb3ba526e96a57c4b14a8699410862022-04-17 1:23:4933 days 3 hrs ago 0xbd77d91baa57aa1acaee8f27bfc0ad00c9931c20 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xead592947f7606d679537bf485a6a2f5801de5dccaf4c01a9ce9e50ac552cbc898784692022-04-15 20:28:1434 days 8 hrs ago 0xb308082a84f0cedabde8f8c019dc28c2140c9822 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x1f47710732fc9f9b7a5260153f1278d5af91e870ee8558faebf1c0a38d6d2eea96803222022-04-12 7:46:2137 days 21 hrs ago 0x1e96682fadd54a2ff49d8e906da4d04ea119fe99 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0xa104d21e3687f288378bfc351863f7748aa7a4f83ca1edc73719befb532a756395987722022-04-10 17:50:1939 days 10 hrs ago 0x435b7d470767cb121f37dd296b2ac7913fdf5427 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
0x6694e1817c2e0203fad3d34191d0660ad2053e1f503015319738b33505d885e195818342022-04-10 8:24:4539 days 20 hrs ago 0x17ae0a6be2e97b384165626db2569729d5006640 0x7c99ae5a1e01a8942575c906a3abbcf7f2fa3f0c0 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FusePoolDirectoryArbitrum

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 11 : FusePoolDirectoryArbitrum.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "../../FusePoolDirectory.sol";

/**
 * @title FusePoolDirectoryArbitrum
 * @author David Lucid <[email protected]> (https://github.com/davidlucid)
 * @notice FusePoolDirectoryArbitrum is a directory for Fuse interest rate pools on Arbitrum.
 */
contract FusePoolDirectoryArbitrum is FusePoolDirectory {
    /**
     * @dev Deploys a new Fuse pool and adds to the directory.
     * @param name The name of the pool.
     * @param implementation The Comptroller implementation contract address.
     * @param enforceWhitelist Boolean indicating if the pool's supplier/borrower whitelist is to be enforced.
     * @param closeFactor The pool's close factor (scaled by 1e18).
     * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18).
     * @param priceOracle The pool's PriceOracle contract address.
     * @return The index of the registered Fuse pool and the Unitroller proxy address.
     */
    function deployPool(string memory name, address implementation, bool enforceWhitelist, uint256 closeFactor, uint256 liquidationIncentive, address priceOracle) external override returns (uint256, address) {
        // Input validation
        require(implementation != address(0), "No Comptroller implementation contract address specified.");
        require(priceOracle != address(0), "No PriceOracle contract address specified.");

        // Deploy Unitroller using msg.sender, name, and block.number as a salt
        bytes memory unitrollerCreationCode = hex"60806040526001805460ff60a81b1960ff60a01b19909116600160a01b1716600160a81b17905534801561003257600080fd5b50600080546001600160a01b03191633179055610ae1806100546000396000f3fe6080604052600436106100a75760003560e01c8063bb82aa5e11610064578063bb82aa5e14610437578063c1e803341461044c578063dcfbc0c714610461578063e992a04114610476578063e9c714f2146104a9578063f851a440146104be576100a7565b80630225ab9d1461032b5780630a755ec21461036957806326782247146103925780632f1069ba146103c35780636f63af0b146103d8578063b71d1a0c14610404575b3330146102a85760408051600481526024810182526020810180516001600160e01b0316633757348b60e21b1781529151815160009360609330939092909182918083835b6020831061010b5780518252601f1990920191602091820191016100ec565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461016b576040519150601f19603f3d011682016040523d82523d6000602084013e610170565b606091505b5091509150600082156101975781806020019051602081101561019257600080fd5b505190505b80156102a4576002546040805163bbcdd6d360e01b81526001600160a01b03909216600483015251600091734afb2b3dc111d091ca6c46c024d1d2f17bf477e19163bbcdd6d391602480820192602092909190829003018186803b1580156101fe57600080fd5b505afa158015610212573d6000803e3d6000fd5b505050506040513d602081101561022857600080fd5b50516002549091506001600160a01b038083169116146102a257600280546001600160a01b038381166001600160a01b0319831617928390556040805192821680845293909116602083015280517fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a9281900390910190a1505b505b5050505b6002546040516000916001600160a01b031690829036908083838082843760405192019450600093509091505080830381855af49150503d806000811461030b576040519150601f19603f3d011682016040523d82523d6000602084013e610310565b606091505b505090506040513d6000823e818015610327573d82f35b3d82fd5b34801561033757600080fd5b506103576004803603602081101561034e57600080fd5b503515156104d3565b60408051918252519081900360200190f35b34801561037557600080fd5b5061037e61056f565b604080519115158252519081900360200190f35b34801561039e57600080fd5b506103a761057f565b604080516001600160a01b039092168252519081900360200190f35b3480156103cf57600080fd5b5061037e61058e565b3480156103e457600080fd5b50610357600480360360208110156103fb57600080fd5b5035151561059e565b34801561041057600080fd5b506103576004803603602081101561042757600080fd5b50356001600160a01b031661063a565b34801561044357600080fd5b506103a76106bd565b34801561045857600080fd5b506103576106cc565b34801561046d57600080fd5b506103a76107c7565b34801561048257600080fd5b506103576004803603602081101561049957600080fd5b50356001600160a01b03166107d6565b3480156104b557600080fd5b506103576108f6565b3480156104ca57600080fd5b506103a76109dc565b60006104dd6109eb565b6104f4576104ed60016005610a46565b905061056a565b60015460ff600160a81b90910416151582151514156105145760006104ed565b60018054831515600160a81b810260ff60a81b199092169190911790915560408051918252517f10f9a0a95673b0837d1dce21fd3bffcb6d760435e9b5300b75a271182f75f8229181900360200190a160005b90505b919050565b600154600160a81b900460ff1681565b6001546001600160a01b031681565b600154600160a01b900460ff1681565b60006105a86109eb565b6105b8576104ed60016005610a46565b60015460ff600160a01b90910416151582151514156105d85760006104ed565b60018054831515600160a01b90810260ff60a01b199092169190911791829055604080519190920460ff161515815290517fabb56a15fd39488c914b324690b88f30d7daec63d2131ca0ef47e5739068c86e9181900360200190a16000610567565b60006106446109eb565b610654576104ed60016010610a46565b600180546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a160005b9392505050565b6002546001600160a01b031681565b6003546000906001600160a01b0316331415806106f257506003546001600160a01b0316155b1561070957610702600180610a46565b90506107c4565b60028054600380546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a92908290030190a1600354604080516001600160a01b038085168252909216602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160005b925050505b90565b6003546001600160a01b031681565b60006107e06109eb565b6107f0576104ed60016012610a46565b60025460408051639d244f9f60e01b81526001600160a01b039283166004820152918416602483015251734afb2b3dc111d091ca6c46c024d1d2f17bf477e191639d244f9f916044808301926020929190829003018186803b15801561085557600080fd5b505afa158015610869573d6000803e3d6000fd5b505050506040513d602081101561087f57600080fd5b5051610891576104ed60016011610a46565b600380546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160006106b6565b6001546000906001600160a01b031633141580610911575033155b156109225761070260016000610a46565b60008054600180546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600154604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160006107bf565b6000546001600160a01b031681565b600080546001600160a01b031633148015610a0f5750600154600160a81b900460ff165b80610a41575033734afb2b3dc111d091ca6c46c024d1d2f17bf477e1148015610a415750600154600160a01b900460ff165b905090565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836015811115610a7557fe5b83601b811115610a8157fe5b604080519283526020830191909152600082820152519081900360600190a18260158111156106b657fefea265627a7a72315820b43a56e6c98a4da586c0bea9fd7bf158b8665b39690ed8e5fa39d00c94c43f8364736f6c63430005110032";
        bytes32 salt = keccak256(abi.encodePacked(msg.sender, name, block.number));
        address proxy;

        assembly {
            proxy := create2(0, add(unitrollerCreationCode, 32), mload(unitrollerCreationCode), salt)
            if iszero(extcodesize(proxy)) {
                revert(0, "Failed to deploy Unitroller.")
            }
        }

        // Setup Unitroller
        Unitroller unitroller = Unitroller(proxy);
        require(unitroller._setPendingImplementation(implementation) == 0, "Failed to set pending implementation on Unitroller."); // Checks Comptroller implementation whitelist
        Comptroller comptrollerImplementation = Comptroller(implementation);
        comptrollerImplementation._become(unitroller);
        Comptroller comptrollerProxy = Comptroller(proxy);

        // Set pool parameters
        require(comptrollerProxy._setCloseFactor(closeFactor) == 0, "Failed to set pool close factor.");
        require(comptrollerProxy._setLiquidationIncentive(liquidationIncentive) == 0, "Failed to set pool liquidation incentive.");
        require(comptrollerProxy._setPriceOracle(PriceOracle(priceOracle)) == 0, "Failed to set pool price oracle.");

        // Whitelist
        if (enforceWhitelist) require(comptrollerProxy._setWhitelistEnforcement(true) == 0, "Failed to enforce supplier/borrower whitelist.");

        // Enable auto-implementation
        require(comptrollerProxy._toggleAutoImplementations(true) == 0, "Failed to enable pool auto implementations.");

        // Make msg.sender the admin
        require(unitroller._setPendingAdmin(msg.sender) == 0, "Failed to set pending admin on Unitroller.");

        // Register the pool with this FusePoolDirectory
        return (_registerPool(name, proxy), proxy);
    }
}

File 2 of 11 : Unitroller.sol
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.6.12;

/**
 * @title ComptrollerCore
 * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.
 * CTokens should reference this contract as their comptroller.
 */
interface Unitroller {
    function _setPendingImplementation(address newPendingImplementation) external returns (uint);
    function _setPendingAdmin(address newPendingAdmin) external returns (uint);
}

File 3 of 11 : RewardsDistributor.sol
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.6.12;

import "./CToken.sol";

/**
 * @title RewardsDistributor
 * @author Compound
 */
interface RewardsDistributor {
    /// @dev The token to reward (i.e., COMP)
    function rewardToken() external view returns (address);

    /// @notice The portion of compRate that each market currently receives
    function compSupplySpeeds(address) external view returns (uint);

    /// @notice The portion of compRate that each market currently receives
    function compBorrowSpeeds(address) external view returns (uint);

    /// @notice The COMP accrued but not yet transferred to each user
    function compAccrued(address) external view returns (uint);

    /**
     * @notice Keeps the flywheel moving pre-mint and pre-redeem
     * @dev Called by the Comptroller
     * @param cToken The relevant market
     * @param supplier The minter/redeemer
     */
    function flywheelPreSupplierAction(address cToken, address supplier) external;

    /**
     * @notice Keeps the flywheel moving pre-borrow and pre-repay
     * @dev Called by the Comptroller
     * @param cToken The relevant market
     * @param borrower The borrower
     */
    function flywheelPreBorrowerAction(address cToken, address borrower) external;

    /**
     * @notice Returns an array of all markets.
     */
    function getAllMarkets() external view returns (CToken[] memory);
}

File 4 of 11 : PriceOracle.sol
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.6.12;

import "./CToken.sol";

interface PriceOracle {
    /**
      * @notice Get the underlying price of a cToken asset
      * @param cToken The cToken to get the underlying price of
      * @return The underlying asset price mantissa (scaled by 1e18).
      *  Zero means the price is unavailable.
      */
    function getUnderlyingPrice(CToken cToken) external view returns (uint);
}

File 5 of 11 : Comptroller.sol
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.6.12;

import "./PriceOracle.sol";
import "./CToken.sol";
import "./Unitroller.sol";
import "./RewardsDistributor.sol";

/**
 * @title Compound's Comptroller Contract
 * @author Compound
 */
interface Comptroller {
    function admin() external view returns (address);
    function adminHasRights() external view returns (bool);
    function fuseAdminHasRights() external view returns (bool);

    function oracle() external view returns (PriceOracle);
    function closeFactorMantissa() external view returns (uint);
    function liquidationIncentiveMantissa() external view returns (uint);

    function markets(address cToken) external view returns (bool, uint);

    function getAssetsIn(address account) external view returns (CToken[] memory);
    function checkMembership(address account, CToken cToken) external view returns (bool);
    function getAccountLiquidity(address account) external view returns (uint, uint, uint);

    function _setPriceOracle(PriceOracle newOracle) external returns (uint);
    function _setCloseFactor(uint newCloseFactorMantissa) external returns (uint256);
    function _setLiquidationIncentive(uint newLiquidationIncentiveMantissa) external returns (uint);
    function _become(Unitroller unitroller) external;

    function borrowGuardianPaused(address cToken) external view returns (bool);

    function getRewardsDistributors() external view returns (RewardsDistributor[] memory);
    function getAllMarkets() external view returns (CToken[] memory);
    function getAllBorrowers() external view returns (address[] memory);
    function suppliers(address account) external view returns (bool);
    function enforceWhitelist() external view returns (bool);
    function whitelist(address account) external view returns (bool);

    function _setWhitelistEnforcement(bool enforce) external returns (uint);
    function _setWhitelistStatuses(address[] calldata _suppliers, bool[] calldata statuses) external returns (uint);

    function _toggleAutoImplementations(bool enabled) external returns (uint);
}

File 6 of 11 : CToken.sol
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.6.12;

/**
 * @title Compound's CToken Contract
 * @notice Abstract base for CTokens
 * @author Compound
 */
interface CToken {
    function admin() external view returns (address);
    function adminHasRights() external view returns (bool);
    function fuseAdminHasRights() external view returns (bool);
    function symbol() external view returns (string memory);
    function comptroller() external view returns (address);
    function adminFeeMantissa() external view returns (uint256);
    function fuseFeeMantissa() external view returns (uint256);
    function reserveFactorMantissa() external view returns (uint256);
    function totalReserves() external view returns (uint);
    function totalAdminFees() external view returns (uint);
    function totalFuseFees() external view returns (uint);

    function isCToken() external view returns (bool);
    function isCEther() external view returns (bool);

    function balanceOf(address owner) external view returns (uint);
    function balanceOfUnderlying(address owner) external returns (uint);
    function borrowRatePerBlock() external view returns (uint);
    function supplyRatePerBlock() external view returns (uint);
    function totalBorrowsCurrent() external returns (uint);
    function borrowBalanceStored(address account) external view returns (uint);
    function exchangeRateStored() external view returns (uint);
    function getCash() external view returns (uint);

    function redeem(uint redeemTokens) external returns (uint);
    function redeemUnderlying(uint redeemAmount) external returns (uint);
}

File 7 of 11 : FusePoolDirectory.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

import "./external/compound/Comptroller.sol";
import "./external/compound/Unitroller.sol";
import "./external/compound/PriceOracle.sol";

/**
 * @title FusePoolDirectory
 * @author David Lucid <[email protected]> (https://github.com/davidlucid)
 * @notice FusePoolDirectory is a directory for Fuse interest rate pools.
 */
contract FusePoolDirectory is OwnableUpgradeable {
    /**
     * @dev Initializes a deployer whitelist if desired.
     * @param _enforceDeployerWhitelist Boolean indicating if the deployer whitelist is to be enforced.
     * @param _deployerWhitelist Array of Ethereum accounts to be whitelisted.
     */
    function initialize(bool _enforceDeployerWhitelist, address[] memory _deployerWhitelist) public initializer {
        __Ownable_init();
        enforceDeployerWhitelist = _enforceDeployerWhitelist;
        for (uint256 i = 0; i < _deployerWhitelist.length; i++) deployerWhitelist[_deployerWhitelist[i]] = true;
    }

    /**
     * @dev Struct for a Fuse interest rate pool.
     */
    struct FusePool {
        string name;
        address creator;
        address comptroller;
        uint256 blockPosted;
        uint256 timestampPosted;
    }

    /**
     * @dev Array of Fuse interest rate pools.
     */
    FusePool[] public pools;

    /**
     * @dev Maps Ethereum accounts to arrays of Fuse pool indexes.
     */
    mapping(address => uint256[]) private _poolsByAccount;

    /**
     * @dev Maps Fuse pool Comptroller addresses to bools indicating if they have been registered via the directory.
     */
    mapping(address => bool) public poolExists;

    /**
     * @dev Emitted when a new Fuse pool is added to the directory.
     */
    event PoolRegistered(uint256 index, FusePool pool);

    /**
     * @dev Booleans indicating if the deployer whitelist is enforced.
     */
    bool public enforceDeployerWhitelist;

    /**
     * @dev Maps Ethereum accounts to booleans indicating if they are allowed to deploy pools.
     */
    mapping(address => bool) public deployerWhitelist;

    /**
     * @dev Controls if the deployer whitelist is to be enforced.
     * @param enforce Boolean indicating if the deployer whitelist is to be enforced.
     */
    function _setDeployerWhitelistEnforcement(bool enforce) external onlyOwner {
        enforceDeployerWhitelist = enforce;
    }

    /**
     * @dev Adds/removes Ethereum accounts to the deployer whitelist.
     * @param deployers Array of Ethereum accounts to be whitelisted.
     * @param status Whether to add or remove the accounts.
     */
    function _editDeployerWhitelist(address[] calldata deployers, bool status) external onlyOwner {
        require(deployers.length > 0, "No deployers supplied.");
        for (uint256 i = 0; i < deployers.length; i++) deployerWhitelist[deployers[i]] = status;
    }

    /**
     * @dev Adds a new Fuse pool to the directory (without checking msg.sender).
     * @param name The name of the pool.
     * @param comptroller The pool's Comptroller proxy contract address.
     * @return The index of the registered Fuse pool.
     */
    function _registerPool(string memory name, address comptroller) internal returns (uint256) {
        require(!poolExists[comptroller], "Pool already exists in the directory.");
        require(!enforceDeployerWhitelist || deployerWhitelist[msg.sender], "Sender is not on deployer whitelist.");
        require(bytes(name).length <= 100, "No pool name supplied.");
        FusePool memory pool = FusePool(name, msg.sender, comptroller, block.number, block.timestamp);
        pools.push(pool);
        _poolsByAccount[msg.sender].push(pools.length - 1);
        poolExists[comptroller] = true;
        emit PoolRegistered(pools.length - 1, pool);
        return pools.length - 1;
    }

    /**
     * @dev Deploys a new Fuse pool and adds to the directory.
     * @param name The name of the pool.
     * @param implementation The Comptroller implementation contract address.
     * @param enforceWhitelist Boolean indicating if the pool's supplier/borrower whitelist is to be enforced.
     * @param closeFactor The pool's close factor (scaled by 1e18).
     * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18).
     * @param priceOracle The pool's PriceOracle contract address.
     * @return The index of the registered Fuse pool and the Unitroller proxy address.
     */
    function deployPool(string memory name, address implementation, bool enforceWhitelist, uint256 closeFactor, uint256 liquidationIncentive, address priceOracle) external virtual returns (uint256, address) {
        // Input validation
        require(implementation != address(0), "No Comptroller implementation contract address specified.");
        require(priceOracle != address(0), "No PriceOracle contract address specified.");

        // Deploy Unitroller using msg.sender, name, and block.number as a salt
        bytes memory unitrollerCreationCode = hex"60806040526001805460ff60a81b1960ff60a01b19909116600160a01b1716600160a81b17905534801561003257600080fd5b50600080546001600160a01b03191633179055610ae1806100546000396000f3fe6080604052600436106100a75760003560e01c8063bb82aa5e11610064578063bb82aa5e14610437578063c1e803341461044c578063dcfbc0c714610461578063e992a04114610476578063e9c714f2146104a9578063f851a440146104be576100a7565b80630225ab9d1461032b5780630a755ec21461036957806326782247146103925780632f1069ba146103c35780636f63af0b146103d8578063b71d1a0c14610404575b3330146102a85760408051600481526024810182526020810180516001600160e01b0316633757348b60e21b1781529151815160009360609330939092909182918083835b6020831061010b5780518252601f1990920191602091820191016100ec565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461016b576040519150601f19603f3d011682016040523d82523d6000602084013e610170565b606091505b5091509150600082156101975781806020019051602081101561019257600080fd5b505190505b80156102a4576002546040805163bbcdd6d360e01b81526001600160a01b0390921660048301525160009173a731585ab05fc9f83555cf9bff8f58ee94e18f859163bbcdd6d391602480820192602092909190829003018186803b1580156101fe57600080fd5b505afa158015610212573d6000803e3d6000fd5b505050506040513d602081101561022857600080fd5b50516002549091506001600160a01b038083169116146102a257600280546001600160a01b038381166001600160a01b0319831617928390556040805192821680845293909116602083015280517fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a9281900390910190a1505b505b5050505b6002546040516000916001600160a01b031690829036908083838082843760405192019450600093509091505080830381855af49150503d806000811461030b576040519150601f19603f3d011682016040523d82523d6000602084013e610310565b606091505b505090506040513d6000823e818015610327573d82f35b3d82fd5b34801561033757600080fd5b506103576004803603602081101561034e57600080fd5b503515156104d3565b60408051918252519081900360200190f35b34801561037557600080fd5b5061037e61056f565b604080519115158252519081900360200190f35b34801561039e57600080fd5b506103a761057f565b604080516001600160a01b039092168252519081900360200190f35b3480156103cf57600080fd5b5061037e61058e565b3480156103e457600080fd5b50610357600480360360208110156103fb57600080fd5b5035151561059e565b34801561041057600080fd5b506103576004803603602081101561042757600080fd5b50356001600160a01b031661063a565b34801561044357600080fd5b506103a76106bd565b34801561045857600080fd5b506103576106cc565b34801561046d57600080fd5b506103a76107c7565b34801561048257600080fd5b506103576004803603602081101561049957600080fd5b50356001600160a01b03166107d6565b3480156104b557600080fd5b506103576108f6565b3480156104ca57600080fd5b506103a76109dc565b60006104dd6109eb565b6104f4576104ed60016005610a46565b905061056a565b60015460ff600160a81b90910416151582151514156105145760006104ed565b60018054831515600160a81b810260ff60a81b199092169190911790915560408051918252517f10f9a0a95673b0837d1dce21fd3bffcb6d760435e9b5300b75a271182f75f8229181900360200190a160005b90505b919050565b600154600160a81b900460ff1681565b6001546001600160a01b031681565b600154600160a01b900460ff1681565b60006105a86109eb565b6105b8576104ed60016005610a46565b60015460ff600160a01b90910416151582151514156105d85760006104ed565b60018054831515600160a01b90810260ff60a01b199092169190911791829055604080519190920460ff161515815290517fabb56a15fd39488c914b324690b88f30d7daec63d2131ca0ef47e5739068c86e9181900360200190a16000610567565b60006106446109eb565b610654576104ed60016010610a46565b600180546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a160005b9392505050565b6002546001600160a01b031681565b6003546000906001600160a01b0316331415806106f257506003546001600160a01b0316155b1561070957610702600180610a46565b90506107c4565b60028054600380546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a92908290030190a1600354604080516001600160a01b038085168252909216602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160005b925050505b90565b6003546001600160a01b031681565b60006107e06109eb565b6107f0576104ed60016012610a46565b60025460408051639d244f9f60e01b81526001600160a01b03928316600482015291841660248301525173a731585ab05fc9f83555cf9bff8f58ee94e18f8591639d244f9f916044808301926020929190829003018186803b15801561085557600080fd5b505afa158015610869573d6000803e3d6000fd5b505050506040513d602081101561087f57600080fd5b5051610891576104ed60016011610a46565b600380546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160006106b6565b6001546000906001600160a01b031633141580610911575033155b156109225761070260016000610a46565b60008054600180546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600154604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160006107bf565b6000546001600160a01b031681565b600080546001600160a01b031633148015610a0f5750600154600160a81b900460ff165b80610a4157503373a731585ab05fc9f83555cf9bff8f58ee94e18f85148015610a415750600154600160a01b900460ff165b905090565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836015811115610a7557fe5b83601b811115610a8157fe5b604080519283526020830191909152600082820152519081900360600190a18260158111156106b657fefea265627a7a72315820a5cf9491a370c17ee98b3c08c728cc0ddad83bd43ca76c92dc106835bfccb25664736f6c63430005110032";
        bytes32 salt = keccak256(abi.encodePacked(msg.sender, name, block.number));
        address proxy;

        assembly {
            proxy := create2(0, add(unitrollerCreationCode, 32), mload(unitrollerCreationCode), salt)
            if iszero(extcodesize(proxy)) {
                revert(0, "Failed to deploy Unitroller.")
            }
        }

        // Setup Unitroller
        Unitroller unitroller = Unitroller(proxy);
        require(unitroller._setPendingImplementation(implementation) == 0, "Failed to set pending implementation on Unitroller."); // Checks Comptroller implementation whitelist
        Comptroller comptrollerImplementation = Comptroller(implementation);
        comptrollerImplementation._become(unitroller);
        Comptroller comptrollerProxy = Comptroller(proxy);

        // Set pool parameters
        require(comptrollerProxy._setCloseFactor(closeFactor) == 0, "Failed to set pool close factor.");
        require(comptrollerProxy._setLiquidationIncentive(liquidationIncentive) == 0, "Failed to set pool liquidation incentive.");
        require(comptrollerProxy._setPriceOracle(PriceOracle(priceOracle)) == 0, "Failed to set pool price oracle.");

        // Whitelist
        if (enforceWhitelist) require(comptrollerProxy._setWhitelistEnforcement(true) == 0, "Failed to enforce supplier/borrower whitelist.");

        // Enable auto-implementation
        require(comptrollerProxy._toggleAutoImplementations(true) == 0, "Failed to enable pool auto implementations.");

        // Make msg.sender the admin
        require(unitroller._setPendingAdmin(msg.sender) == 0, "Failed to set pending admin on Unitroller.");

        // Register the pool with this FusePoolDirectory
        return (_registerPool(name, proxy), proxy);
    }

    /**
     * @notice Returns arrays of all Fuse pools' data.
     * @dev This function is not designed to be called in a transaction: it is too gas-intensive.
     */
    function getAllPools() external view returns (FusePool[] memory) {
        return pools;
    }

    /**
     * @notice Returns arrays of all public Fuse pool indexes and data.
     * @dev This function is not designed to be called in a transaction: it is too gas-intensive.
     */
    function getPublicPools() external view returns (uint256[] memory, FusePool[] memory) {
        uint256 arrayLength = 0;

        for (uint256 i = 0; i < pools.length; i++) {
            try Comptroller(pools[i].comptroller).enforceWhitelist() returns (bool enforceWhitelist) {
                if (enforceWhitelist) continue;
            } catch { }

            arrayLength++;
        }

        uint256[] memory indexes = new uint256[](arrayLength);
        FusePool[] memory publicPools = new FusePool[](arrayLength);
        uint256 index = 0;

        for (uint256 i = 0; i < pools.length; i++) {
            try Comptroller(pools[i].comptroller).enforceWhitelist() returns (bool enforceWhitelist) {
                if (enforceWhitelist) continue;
            } catch { }

            indexes[index] = i;
            publicPools[index] = pools[i];
            index++;
        }

        return (indexes, publicPools);
    }

    /**
     * @notice Returns arrays of Fuse pool indexes and data created by `account`.
     */
    function getPoolsByAccount(address account) external view returns (uint256[] memory, FusePool[] memory) {
        uint256[] memory indexes = new uint256[](_poolsByAccount[account].length);
        FusePool[] memory accountPools = new FusePool[](_poolsByAccount[account].length);

        for (uint256 i = 0; i < _poolsByAccount[account].length; i++) {
            indexes[i] = _poolsByAccount[account][i];
            accountPools[i] = pools[_poolsByAccount[account][i]];
        }

        return (indexes, accountPools);
    }

    /**
     * @dev Maps Ethereum accounts to arrays of Fuse pool Comptroller proxy contract addresses.
     */
    mapping(address => address[]) private _bookmarks;

    /**
     * @notice Returns arrays of Fuse pool Unitroller (Comptroller proxy) contract addresses bookmarked by `account`.
     */
    function getBookmarks(address account) external view returns (address[] memory) {
        return _bookmarks[account];
    }

    /**
     * @notice Bookmarks a Fuse pool Unitroller (Comptroller proxy) contract addresses.
     */
    function bookmarkPool(address comptroller) external {
        _bookmarks[msg.sender].push(comptroller);
    }

    /**
     * @notice Modify existing Fuse pool name.
     */
    function setPoolName(uint256 index, string calldata name) external {
        Comptroller _comptroller = Comptroller(pools[index].comptroller);
        require(msg.sender == _comptroller.admin() && _comptroller.adminHasRights() || msg.sender == owner());
        pools[index].name = name;
    }

    /**
     * @dev Maps Ethereum accounts to booleans indicating if they are a whitelisted admin.
     */
    mapping(address => bool) public adminWhitelist;

    /**
     * @dev Event emitted when the admin whitelist is updated.
     */
    event AdminWhitelistUpdated(address[] admins, bool status);

    /**
     * @dev Adds/removes Ethereum accounts to the admin whitelist.
     * @param admins Array of Ethereum accounts to be whitelisted.
     * @param status Whether to add or remove the accounts.
     */
    function _editAdminWhitelist(address[] calldata admins, bool status) external onlyOwner {
        require(admins.length > 0, "No admins supplied.");
        for (uint256 i = 0; i < admins.length; i++) adminWhitelist[admins[i]] = status;
        emit AdminWhitelistUpdated(admins, status);
    }

    /**
     * @notice Returns arrays of all public Fuse pool indexes and data with whitelisted admins.
     * @dev This function is not designed to be called in a transaction: it is too gas-intensive.
     */
    function getPublicPoolsByVerification(bool whitelistedAdmin) external view returns (uint256[] memory, FusePool[] memory) {
        uint256 arrayLength = 0;

        for (uint256 i = 0; i < pools.length; i++) {
            Comptroller comptroller = Comptroller(pools[i].comptroller);

            try comptroller.enforceWhitelist() returns (bool enforceWhitelist) {
                if (enforceWhitelist) continue;

                try comptroller.admin() returns (address admin) {
                    if (whitelistedAdmin != adminWhitelist[admin]) continue;
                } catch { }
            } catch { }

            arrayLength++;
        }

        uint256[] memory indexes = new uint256[](arrayLength);
        FusePool[] memory publicPools = new FusePool[](arrayLength);
        uint256 index = 0;

        for (uint256 i = 0; i < pools.length; i++) {
            Comptroller comptroller = Comptroller(pools[i].comptroller);

            try comptroller.enforceWhitelist() returns (bool enforceWhitelist) {
                if (enforceWhitelist) continue;

                try comptroller.admin() returns (address admin) {
                    if (whitelistedAdmin != adminWhitelist[admin]) continue;
                } catch { }
            } catch { }

            indexes[index] = i;
            publicPools[index] = pools[i];
            index++;
        }

        return (indexes, publicPools);
    }
}

File 8 of 11 : ContextUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;
import "../proxy/Initializable.sol";

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

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

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

File 9 of 11 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

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

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

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

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

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

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

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 10 of 11 : Initializable.sol
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;

import "../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || _isConstructor() || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /// @dev Returns true if and only if the function is running in the constructor
    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

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

pragma solidity >=0.6.0 <0.8.0;

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

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

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

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

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
    uint256[49] private __gap;
}

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

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"admins","type":"address[]"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"AdminWhitelistUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"comptroller","type":"address"},{"internalType":"uint256","name":"blockPosted","type":"uint256"},{"internalType":"uint256","name":"timestampPosted","type":"uint256"}],"indexed":false,"internalType":"struct FusePoolDirectory.FusePool","name":"pool","type":"tuple"}],"name":"PoolRegistered","type":"event"},{"inputs":[{"internalType":"address[]","name":"admins","type":"address[]"},{"internalType":"bool","name":"status","type":"bool"}],"name":"_editAdminWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"deployers","type":"address[]"},{"internalType":"bool","name":"status","type":"bool"}],"name":"_editDeployerWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enforce","type":"bool"}],"name":"_setDeployerWhitelistEnforcement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"adminWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"comptroller","type":"address"}],"name":"bookmarkPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"implementation","type":"address"},{"internalType":"bool","name":"enforceWhitelist","type":"bool"},{"internalType":"uint256","name":"closeFactor","type":"uint256"},{"internalType":"uint256","name":"liquidationIncentive","type":"uint256"},{"internalType":"address","name":"priceOracle","type":"address"}],"name":"deployPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"deployerWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enforceDeployerWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllPools","outputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"comptroller","type":"address"},{"internalType":"uint256","name":"blockPosted","type":"uint256"},{"internalType":"uint256","name":"timestampPosted","type":"uint256"}],"internalType":"struct FusePoolDirectory.FusePool[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getBookmarks","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getPoolsByAccount","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"comptroller","type":"address"},{"internalType":"uint256","name":"blockPosted","type":"uint256"},{"internalType":"uint256","name":"timestampPosted","type":"uint256"}],"internalType":"struct FusePoolDirectory.FusePool[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPublicPools","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"comptroller","type":"address"},{"internalType":"uint256","name":"blockPosted","type":"uint256"},{"internalType":"uint256","name":"timestampPosted","type":"uint256"}],"internalType":"struct FusePoolDirectory.FusePool[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"whitelistedAdmin","type":"bool"}],"name":"getPublicPoolsByVerification","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"comptroller","type":"address"},{"internalType":"uint256","name":"blockPosted","type":"uint256"},{"internalType":"uint256","name":"timestampPosted","type":"uint256"}],"internalType":"struct FusePoolDirectory.FusePool[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_enforceDeployerWhitelist","type":"bool"},{"internalType":"address[]","name":"_deployerWhitelist","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pools","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"address","name":"comptroller","type":"address"},{"internalType":"uint256","name":"blockPosted","type":"uint256"},{"internalType":"uint256","name":"timestampPosted","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"string","name":"name","type":"string"}],"name":"setPoolName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b5061379b806100206000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80635710c6d8116100ad578063a970e76c11610071578063a970e76c14610270578063ac4afa3814610283578063b86579d4146102a7578063d88ff1f4146102ba578063f2fde38b146102cf5761012c565b80635710c6d81461020c578063715018a61461022d5780638da5cb5b14610235578063a155497c1461024a578063a3ed91c61461025d5761012c565b8063218a3bbe116100f4578063218a3bbe146101a857806326bb81d7146101c957806343e20a1d146101d15780634a7462ee146101e45780634ae26ea1146102045761012c565b806304f03c6f1461013157806307421978146101465780630a83d1b0146101595780631e1c6a071461016c57806320c32bfe14610195575b600080fd5b61014461013f366004612216565b6102e2565b005b610144610154366004612157565b61033d565b610144610167366004612196565b61037c565b61017f61017a366004612157565b61047a565b60405161018c91906126bf565b60405180910390f35b6101446101a336600461240f565b61048f565b6101bb6101b6366004612216565b610612565b60405161018c929190612668565b61017f610ab5565b61017f6101df366004612157565b610abe565b6101f76101f2366004612157565b610ad3565b60405161018c9190612608565b6101bb610b49565b61021f61021a36600461230e565b610e99565b60405161018c929190612b82565b610144611437565b61023d6114c0565b60405161018c919061259b565b610144610258366004612196565b6114cf565b6101bb61026b366004612157565b611592565b61017f61027e366004612157565b611823565b6102966102913660046123df565b611838565b60405161018c9594939291906126ca565b6101446102b536600461224e565b61190f565b6102c2611a03565b60405161018c9190612655565b6101446102dd366004612157565b611b2d565b6102ea611bee565b6001600160a01b03166102fb6114c0565b6001600160a01b03161461032a5760405162461bcd60e51b815260040161032190612970565b60405180910390fd5b6068805460ff1916911515919091179055565b336000908152606a602090815260408220805460018101825590835291200180546001600160a01b0319166001600160a01b0392909216919091179055565b610384611bee565b6001600160a01b03166103956114c0565b6001600160a01b0316146103bb5760405162461bcd60e51b815260040161032190612970565b816103d85760405162461bcd60e51b81526004016103219061273f565b60005b828110156104395781606b60008686858181106103f457fe5b90506020020160208101906104099190612157565b6001600160a01b031681526020810191909152604001600020805460ff19169115159190911790556001016103db565b507f31b67e6853df85403a8c4f4f46dc53f48f700d6917c8e3ec8c77a0e6fd56793b83838360405161046d939291906125af565b60405180910390a1505050565b60676020526000908152604090205460ff1681565b60006065848154811061049e57fe5b600091825260209182902060026005909202010154604080516303e1469160e61b815290516001600160a01b039092169350839263f851a44092600480840193829003018186803b1580156104f257600080fd5b505afa158015610506573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052a919061217a565b6001600160a01b0316336001600160a01b03161480156105b65750806001600160a01b0316630a755ec26040518163ffffffff1660e01b815260040160206040518083038186803b15801561057e57600080fd5b505afa158015610592573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105b69190612232565b806105d957506105c46114c0565b6001600160a01b0316336001600160a01b0316145b6105e257600080fd5b8282606586815481106105f157fe5b6000918252602090912061060b9360059092020191611fff565b5050505050565b6060806000805b6065548110156107805760006065828154811061063257fe5b60009182526020918290206002600590920201015460408051630b09572160e41b815290516001600160a01b039092169350839263b095721092600480840193829003018186803b15801561068657600080fd5b505afa9250505080156106b6575060408051601f3d908101601f191682019092526106b391810190612232565b60015b6106bf57610770565b80156106cc575050610778565b816001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561070557600080fd5b505afa925050508015610735575060408051601f3d908101601f191682019092526107329181019061217a565b60015b61073e5761076e565b6001600160a01b0381166000908152606b602052604090205460ff1615158815151461076c57505050610778565b505b505b506001909101905b600101610619565b5060608167ffffffffffffffff8111801561079a57600080fd5b506040519080825280602002602001820160405280156107c4578160200160208202803683370190505b50905060608267ffffffffffffffff811180156107e057600080fd5b5060405190808252806020026020018201604052801561081a57816020015b61080761207d565b8152602001906001900390816107ff5790505b5090506000805b606554811015610aa85760006065828154811061083a57fe5b60009182526020918290206002600590920201015460408051630b09572160e41b815290516001600160a01b039092169350839263b095721092600480840193829003018186803b15801561088e57600080fd5b505afa9250505080156108be575060408051601f3d908101601f191682019092526108bb91810190612232565b60015b6108c757610978565b80156108d4575050610aa0565b816001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b15801561090d57600080fd5b505afa92505050801561093d575060408051601f3d908101601f1916820190925261093a9181019061217a565b60015b61094657610976565b6001600160a01b0381166000908152606b602052604090205460ff1615158b15151461097457505050610aa0565b505b505b8185848151811061098557fe5b6020026020010181815250506065828154811061099e57fe5b600091825260209182902060408051600593909302909101805460026001821615610100026000190190911604601f8101859004909402830160c090810190925260a0830184815292939092849290918491840182828015610a415780601f10610a1657610100808354040283529160200191610a41565b820191906000526020600020905b815481529060010190602001808311610a2457829003601f168201915b505050918352505060018201546001600160a01b0390811660208301526002830154166040820152600382015460608201526004909101546080909101528451859085908110610a8d57fe5b6020908102919091010152506001909101905b600101610821565b5091945092505050915091565b60685460ff1681565b606b6020526000908152604090205460ff1681565b6001600160a01b0381166000908152606a6020908152604091829020805483518184028101840190945280845260609392830182828015610b3d57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b1f575b50505050509050919050565b6060806000805b606554811015610c0e5760658181548110610b6757fe5b60009182526020918290206002600590920201015460408051630b09572160e41b815290516001600160a01b039092169263b095721092600480840193829003018186803b158015610bb857600080fd5b505afa925050508015610be8575060408051601f3d908101601f19168201909252610be591810190612232565b60015b610bf157610bff565b8015610bfd5750610c06565b505b6001909101905b600101610b50565b5060608167ffffffffffffffff81118015610c2857600080fd5b50604051908082528060200260200182016040528015610c52578160200160208202803683370190505b50905060608267ffffffffffffffff81118015610c6e57600080fd5b50604051908082528060200260200182016040528015610ca857816020015b610c9561207d565b815260200190600190039081610c8d5790505b5090506000805b606554811015610e8d5760658181548110610cc657fe5b60009182526020918290206002600590920201015460408051630b09572160e41b815290516001600160a01b039092169263b095721092600480840193829003018186803b158015610d1757600080fd5b505afa925050508015610d47575060408051601f3d908101601f19168201909252610d4491810190612232565b60015b610d5057610d5e565b8015610d5c5750610e85565b505b80848381518110610d6b57fe5b60200260200101818152505060658181548110610d8457fe5b600091825260209182902060408051600593909302909101805460026001821615610100026000190190911604601f8101859004909402830160c090810190925260a0830184815292939092849290918491840182828015610e275780601f10610dfc57610100808354040283529160200191610e27565b820191906000526020600020905b815481529060010190602001808311610e0a57829003601f168201915b505050918352505060018201546001600160a01b0390811660208301526002830154166040820152600382015460608201526004909101546080909101528351849084908110610e7357fe5b60209081029190910101526001909101905b600101610caf565b50919450925050509091565b6000806001600160a01b038716610ec25760405162461bcd60e51b81526004016103219061287e565b6001600160a01b038316610ee85760405162461bcd60e51b8152600401610321906129f8565b606060405180610b600160405280610b358152602001612c31610b35913990506000338a43604051602001610f1f9392919061255c565b6040516020818303038152906040528051906020012090506000818351602085016000f59050803b610f70577f4661696c656420746f206465706c6f7920556e6974726f6c6c65722e000000006000fd5b60405163e992a04160e01b815281906001600160a01b0382169063e992a04190610f9e908e9060040161259b565b602060405180830381600087803b158015610fb857600080fd5b505af1158015610fcc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ff091906123f7565b1561100d5760405162461bcd60e51b8152600401610321906129a5565b604051630ea826e360e11b81528b906001600160a01b03821690631d504dc69061103b90859060040161259b565b600060405180830381600087803b15801561105557600080fd5b505af1158015611069573d6000803e3d6000fd5b505060405163317b0b7760e01b81528592506001600160a01b038316915063317b0b779061109b908e90600401612b79565b602060405180830381600087803b1580156110b557600080fd5b505af11580156110c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110ed91906123f7565b1561110a5760405162461bcd60e51b81526004016103219061270a565b604051634fd42e1760e01b81526001600160a01b03821690634fd42e1790611136908d90600401612b79565b602060405180830381600087803b15801561115057600080fd5b505af1158015611164573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118891906123f7565b156111a55760405162461bcd60e51b81526004016103219061276c565b6040516355ee1fe160e01b81526001600160a01b038216906355ee1fe1906111d1908c9060040161259b565b602060405180830381600087803b1580156111eb57600080fd5b505af11580156111ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122391906123f7565b156112405760405162461bcd60e51b8152600401610321906127fb565b8b156112e257604051634a956fad60e11b81526001600160a01b0382169063952adf5a90611273906001906004016126bf565b602060405180830381600087803b15801561128d57600080fd5b505af11580156112a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c591906123f7565b156112e25760405162461bcd60e51b815260040161032190612a42565b604051636a9998b360e11b81526001600160a01b0382169063d53331669061130f906001906004016126bf565b602060405180830381600087803b15801561132957600080fd5b505af115801561133d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061136191906123f7565b1561137e5760405162461bcd60e51b8152600401610321906128db565b604051632dc7468360e21b81526001600160a01b0384169063b71d1a0c906113aa90339060040161259b565b602060405180830381600087803b1580156113c457600080fd5b505af11580156113d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113fc91906123f7565b156114195760405162461bcd60e51b815260040161032190612926565b6114238e85611bf2565b9e939d50929b505050505050505050505050565b61143f611bee565b6001600160a01b03166114506114c0565b6001600160a01b0316146114765760405162461bcd60e51b815260040161032190612970565b6033546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3603380546001600160a01b0319169055565b6033546001600160a01b031690565b6114d7611bee565b6001600160a01b03166114e86114c0565b6001600160a01b03161461150e5760405162461bcd60e51b815260040161032190612970565b8161152b5760405162461bcd60e51b815260040161032190612a90565b60005b8281101561158c57816069600086868581811061154757fe5b905060200201602081019061155c9190612157565b6001600160a01b031681526020810191909152604001600020805460ff191691151591909117905560010161152e565b50505050565b6001600160a01b0381166000908152606660205260409020546060908190819067ffffffffffffffff811180156115c857600080fd5b506040519080825280602002602001820160405280156115f2578160200160208202803683370190505b506001600160a01b03851660009081526066602052604090205490915060609067ffffffffffffffff8111801561162857600080fd5b5060405190808252806020026020018201604052801561166257816020015b61164f61207d565b8152602001906001900390816116475790505b50905060005b6001600160a01b038616600090815260666020526040902054811015611818576001600160a01b03861660009081526066602052604090208054829081106116ac57fe5b90600052602060002001548382815181106116c357fe5b602002602001018181525050606560666000886001600160a01b03166001600160a01b03168152602001908152602001600020828154811061170157fe5b90600052602060002001548154811061171657fe5b600091825260209182902060408051600593909302909101805460026001821615610100026000190190911604601f8101859004909402830160c090810190925260a08301848152929390928492909184918401828280156117b95780601f1061178e576101008083540402835291602001916117b9565b820191906000526020600020905b81548152906001019060200180831161179c57829003601f168201915b505050918352505060018201546001600160a01b039081166020830152600283015416604082015260038201546060820152600490910154608090910152825183908390811061180557fe5b6020908102919091010152600101611668565b509092509050915091565b60696020526000908152604090205460ff1681565b6065818154811061184557fe5b60009182526020918290206005919091020180546040805160026001841615610100026000190190931692909204601f8101859004850283018501909152808252919350918391908301828280156118de5780601f106118b3576101008083540402835291602001916118de565b820191906000526020600020905b8154815290600101906020018083116118c157829003601f168201915b5050505060018301546002840154600385015460049095015493946001600160a01b03928316949290911692509085565b600054610100900460ff16806119285750611928611dfa565b80611936575060005460ff16155b6119525760405162461bcd60e51b815260040161032190612830565b600054610100900460ff1615801561197d576000805460ff1961ff0019909116610100171660011790555b611985611e0b565b6068805460ff191684151517905560005b82518110156119eb576001606960008584815181106119b157fe5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff1916911515919091179055600101611996565b5080156119fe576000805461ff00191690555b505050565b60606065805480602002602001604051908101604052809291908181526020016000905b82821015611b245760008481526020908190206040805160058602909201805460026001821615610100026000190190911604601f8101859004909402830160c090810190925260a0830184815292939092849290918491840182828015611ad05780601f10611aa557610100808354040283529160200191611ad0565b820191906000526020600020905b815481529060010190602001808311611ab357829003601f168201915b50505091835250506001828101546001600160a01b03908116602080850191909152600285015490911660408401526003840154606084015260049093015460809092019190915291835292019101611a27565b50505050905090565b611b35611bee565b6001600160a01b0316611b466114c0565b6001600160a01b031614611b6c5760405162461bcd60e51b815260040161032190612970565b6001600160a01b038116611b925760405162461bcd60e51b8152600401610321906127b5565b6033546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b6001600160a01b03811660009081526067602052604081205460ff1615611c2b5760405162461bcd60e51b815260040161032190612af0565b60685460ff161580611c4c57503360009081526069602052604090205460ff165b611c685760405162461bcd60e51b815260040161032190612b35565b606483511115611c8a5760405162461bcd60e51b815260040161032190612ac0565b611c9261207d565b506040805160a081018252848152336020808301919091526001600160a01b0385169282019290925243606082015242608082015260658054600181018255600091909152815180519293849360059093027f8ff97419363ffd7000167f130ef7168fbea05faf9251824ca5043f113cc6a7c70192611d1492849201906120be565b50602082810151600183810180546001600160a01b03199081166001600160a01b0394851617909155604080870151600287018054909316908516179091556060860151600386015560809095015160049094019390935533600090815260668352848120606580548254808801845592845285842060001991820193019290925592891682526067909352849020805460ff1916909317909255905491517f18075ab463b4dc5842f37ecd67abeb192eda5d073f2c08509e189ad173d5c02092611de29201908490612b99565b60405180910390a15050606554600019015b92915050565b6000611e0530611e9e565b15905090565b600054610100900460ff1680611e245750611e24611dfa565b80611e32575060005460ff16155b611e4e5760405162461bcd60e51b815260040161032190612830565b600054610100900460ff16158015611e79576000805460ff1961ff0019909116610100171660011790555b611e81611ea4565b611e89611f25565b8015611e9b576000805461ff00191690555b50565b3b151590565b600054610100900460ff1680611ebd5750611ebd611dfa565b80611ecb575060005460ff16155b611ee75760405162461bcd60e51b815260040161032190612830565b600054610100900460ff16158015611e89576000805460ff1961ff0019909116610100171660011790558015611e9b576000805461ff001916905550565b600054610100900460ff1680611f3e5750611f3e611dfa565b80611f4c575060005460ff16155b611f685760405162461bcd60e51b815260040161032190612830565b600054610100900460ff16158015611f93576000805460ff1961ff0019909116610100171660011790555b6000611f9d611bee565b603380546001600160a01b0319166001600160a01b038316908117909155604051919250906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3508015611e9b576000805461ff001916905550565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106120405782800160ff1982351617855561206d565b8280016001018555821561206d579182015b8281111561206d578235825591602001919060010190612052565b5061207992915061212c565b5090565b6040518060a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106120ff57805160ff191683800117855561206d565b8280016001018555821561206d579182015b8281111561206d578251825591602001919060010190612111565b5b80821115612079576000815560010161212d565b8035611df481612c0d565b8035611df481612c22565b600060208284031215612168578081fd5b813561217381612c0d565b9392505050565b60006020828403121561218b578081fd5b815161217381612c0d565b6000806000604084860312156121aa578182fd5b833567ffffffffffffffff808211156121c1578384fd5b818601915086601f8301126121d4578384fd5b8135818111156121e2578485fd5b87602080830285010111156121f5578485fd5b6020928301955093505084013561220b81612c22565b809150509250925092565b600060208284031215612227578081fd5b813561217381612c22565b600060208284031215612243578081fd5b815161217381612c22565b60008060408385031215612260578182fd5b823561226b81612c22565b915060208381013567ffffffffffffffff80821115612288578384fd5b818601915086601f83011261229b578384fd5b8135818111156122a9578485fd5b83810291506122b9848301612bba565b8181528481019084860184860187018b10156122d3578788fd5b8795505b838610156122fd576122e98b82612141565b8352600195909501949186019186016122d7565b508096505050505050509250929050565b60008060008060008060c08789031215612326578182fd5b863567ffffffffffffffff8082111561233d578384fd5b818901915089601f830112612350578384fd5b81358181111561235e578485fd5b60209150612374601f8201601f19168301612bba565b8181528b83838601011115612387578586fd5b8183850184830137908101820185905297506123a58a8a8301612141565b965050506123b6886040890161214c565b935060608701359250608087013591506123d38860a08901612141565b90509295509295509295565b6000602082840312156123f0578081fd5b5035919050565b600060208284031215612408578081fd5b5051919050565b600080600060408486031215612423578283fd5b83359250602084013567ffffffffffffffff80821115612441578384fd5b818601915086601f830112612454578384fd5b813581811115612462578485fd5b876020828501011115612473578485fd5b6020830194508093505050509250925092565b6000815180845260208085018081965082840281019150828601855b858110156124cc5782840389526124ba848351612505565b988501989350908401906001016124a2565b5091979650505050505050565b600081518084526124f1816020860160208601612be1565b601f01601f19169290920160200192915050565b6000815160a0845261251a60a08501826124d9565b9050602083015160018060a01b038082166020870152806040860151166040870152505060608301516060850152608083015160808501528091505092915050565b60006bffffffffffffffffffffffff198560601b1682528351612586816014850160208801612be1565b60149201918201929092526034019392505050565b6001600160a01b0391909116815260200190565b6040808252810183905260008460608301825b868110156125f257602083356125d781612c0d565b6001600160a01b0316835292830192909101906001016125c2565b5080925050508215156020830152949350505050565b6020808252825182820181905260009190848201906040850190845b818110156126495783516001600160a01b031683529284019291840191600101612624565b50909695505050505050565b6000602082526121736020830184612486565b604080825283519082018190526000906020906060840190828701845b828110156126a157815184529284019290840190600101612685565b505050838103828501526126b58186612486565b9695505050505050565b901515815260200190565b600060a082526126dd60a08301886124d9565b6001600160a01b039687166020840152949095166040820152606081019290925260809091015292915050565b6020808252818101527f4661696c656420746f2073657420706f6f6c20636c6f736520666163746f722e604082015260600190565b60208082526013908201527227379030b236b4b7399039bab8383634b2b21760691b604082015260600190565b60208082526029908201527f4661696c656420746f2073657420706f6f6c206c69717569646174696f6e20696040820152683731b2b73a34bb329760b91b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252818101527f4661696c656420746f2073657420706f6f6c207072696365206f7261636c652e604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526039908201527f4e6f20436f6d7074726f6c6c657220696d706c656d656e746174696f6e20636f60408201527f6e74726163742061646472657373207370656369666965642e00000000000000606082015260800190565b6020808252602b908201527f4661696c656420746f20656e61626c6520706f6f6c206175746f20696d706c6560408201526a36b2b73a30ba34b7b7399760a91b606082015260800190565b6020808252602a908201527f4661696c656420746f207365742070656e64696e672061646d696e206f6e20556040820152693734ba3937b63632b91760b11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526033908201527f4661696c656420746f207365742070656e64696e6720696d706c656d656e74616040820152723a34b7b71037b7102ab734ba3937b63632b91760691b606082015260800190565b6020808252602a908201527f4e6f2050726963654f7261636c6520636f6e747261637420616464726573732060408201526939b832b1b4b334b2b21760b11b606082015260800190565b6020808252602e908201527f4661696c656420746f20656e666f72636520737570706c6965722f626f72726f60408201526d3bb2b9103bb434ba32b634b9ba1760911b606082015260800190565b6020808252601690820152752737903232b83637bcb2b9399039bab8383634b2b21760511b604082015260600190565b6020808252601690820152752737903837b7b6103730b6b29039bab8383634b2b21760511b604082015260600190565b60208082526025908201527f506f6f6c20616c72656164792065786973747320696e207468652064697265636040820152643a37b93c9760d91b606082015260800190565b60208082526024908201527f53656e646572206973206e6f74206f6e206465706c6f7965722077686974656c60408201526334b9ba1760e11b606082015260800190565b90815260200190565b9182526001600160a01b0316602082015260400190565b600083825260406020830152612bb26040830184612505565b949350505050565b60405181810167ffffffffffffffff81118282101715612bd957600080fd5b604052919050565b60005b83811015612bfc578181015183820152602001612be4565b8381111561158c5750506000910152565b6001600160a01b0381168114611e9b57600080fd5b8015158114611e9b57600080fdfe60806040526001805460ff60a81b1960ff60a01b19909116600160a01b1716600160a81b17905534801561003257600080fd5b50600080546001600160a01b03191633179055610ae1806100546000396000f3fe6080604052600436106100a75760003560e01c8063bb82aa5e11610064578063bb82aa5e14610437578063c1e803341461044c578063dcfbc0c714610461578063e992a04114610476578063e9c714f2146104a9578063f851a440146104be576100a7565b80630225ab9d1461032b5780630a755ec21461036957806326782247146103925780632f1069ba146103c35780636f63af0b146103d8578063b71d1a0c14610404575b3330146102a85760408051600481526024810182526020810180516001600160e01b0316633757348b60e21b1781529151815160009360609330939092909182918083835b6020831061010b5780518252601f1990920191602091820191016100ec565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855afa9150503d806000811461016b576040519150601f19603f3d011682016040523d82523d6000602084013e610170565b606091505b5091509150600082156101975781806020019051602081101561019257600080fd5b505190505b80156102a4576002546040805163bbcdd6d360e01b81526001600160a01b03909216600483015251600091734afb2b3dc111d091ca6c46c024d1d2f17bf477e19163bbcdd6d391602480820192602092909190829003018186803b1580156101fe57600080fd5b505afa158015610212573d6000803e3d6000fd5b505050506040513d602081101561022857600080fd5b50516002549091506001600160a01b038083169116146102a257600280546001600160a01b038381166001600160a01b0319831617928390556040805192821680845293909116602083015280517fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a9281900390910190a1505b505b5050505b6002546040516000916001600160a01b031690829036908083838082843760405192019450600093509091505080830381855af49150503d806000811461030b576040519150601f19603f3d011682016040523d82523d6000602084013e610310565b606091505b505090506040513d6000823e818015610327573d82f35b3d82fd5b34801561033757600080fd5b506103576004803603602081101561034e57600080fd5b503515156104d3565b60408051918252519081900360200190f35b34801561037557600080fd5b5061037e61056f565b604080519115158252519081900360200190f35b34801561039e57600080fd5b506103a761057f565b604080516001600160a01b039092168252519081900360200190f35b3480156103cf57600080fd5b5061037e61058e565b3480156103e457600080fd5b50610357600480360360208110156103fb57600080fd5b5035151561059e565b34801561041057600080fd5b506103576004803603602081101561042757600080fd5b50356001600160a01b031661063a565b34801561044357600080fd5b506103a76106bd565b34801561045857600080fd5b506103576106cc565b34801561046d57600080fd5b506103a76107c7565b34801561048257600080fd5b506103576004803603602081101561049957600080fd5b50356001600160a01b03166107d6565b3480156104b557600080fd5b506103576108f6565b3480156104ca57600080fd5b506103a76109dc565b60006104dd6109eb565b6104f4576104ed60016005610a46565b905061056a565b60015460ff600160a81b90910416151582151514156105145760006104ed565b60018054831515600160a81b810260ff60a81b199092169190911790915560408051918252517f10f9a0a95673b0837d1dce21fd3bffcb6d760435e9b5300b75a271182f75f8229181900360200190a160005b90505b919050565b600154600160a81b900460ff1681565b6001546001600160a01b031681565b600154600160a01b900460ff1681565b60006105a86109eb565b6105b8576104ed60016005610a46565b60015460ff600160a01b90910416151582151514156105d85760006104ed565b60018054831515600160a01b90810260ff60a01b199092169190911791829055604080519190920460ff161515815290517fabb56a15fd39488c914b324690b88f30d7daec63d2131ca0ef47e5739068c86e9181900360200190a16000610567565b60006106446109eb565b610654576104ed60016010610a46565b600180546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a160005b9392505050565b6002546001600160a01b031681565b6003546000906001600160a01b0316331415806106f257506003546001600160a01b0316155b1561070957610702600180610a46565b90506107c4565b60028054600380546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a92908290030190a1600354604080516001600160a01b038085168252909216602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160005b925050505b90565b6003546001600160a01b031681565b60006107e06109eb565b6107f0576104ed60016012610a46565b60025460408051639d244f9f60e01b81526001600160a01b039283166004820152918416602483015251734afb2b3dc111d091ca6c46c024d1d2f17bf477e191639d244f9f916044808301926020929190829003018186803b15801561085557600080fd5b505afa158015610869573d6000803e3d6000fd5b505050506040513d602081101561087f57600080fd5b5051610891576104ed60016011610a46565b600380546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160006106b6565b6001546000906001600160a01b031633141580610911575033155b156109225761070260016000610a46565b60008054600180546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600154604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a160006107bf565b6000546001600160a01b031681565b600080546001600160a01b031633148015610a0f5750600154600160a81b900460ff165b80610a41575033734afb2b3dc111d091ca6c46c024d1d2f17bf477e1148015610a415750600154600160a01b900460ff165b905090565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836015811115610a7557fe5b83601b811115610a8157fe5b604080519283526020830191909152600082820152519081900360600190a18260158111156106b657fefea265627a7a72315820b43a56e6c98a4da586c0bea9fd7bf158b8665b39690ed8e5fa39d00c94c43f8364736f6c63430005110032a264697066735822122061aa096f6e94ba0a0e76c9c887876ec0206737fccf8459630ce495221832dbbe64736f6c634300060c0033

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