ETH Price: $2,228.07 (-2.69%)

Contract

0xcf37B62109b537fa0Cb9A90Af4CA72f6fb85E241
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Sync Dollar Bala...165874842023-02-09 0:01:35750 days ago1675900895IN
Frax Finance: AMO Minter
0 ETH0.0690873532.21782314
Sync Dollar Bala...148255322022-05-22 20:49:581012 days ago1653252598IN
Frax Finance: AMO Minter
0 ETH0.0142673918.05142796
Sync Dollar Bala...148034402022-05-19 6:22:251016 days ago1652941345IN
Frax Finance: AMO Minter
0 ETH0.0165829520.97963359
Sync Dollar Bala...148034172022-05-19 6:16:161016 days ago1652940976IN
Frax Finance: AMO Minter
0 ETH0.0157829218.84053265
Sync Dollar Bala...147849252022-05-16 7:28:111019 days ago1652686091IN
Frax Finance: AMO Minter
0 ETH0.0190007324.0357715
Sync Dollar Bala...146136012022-04-19 5:03:061046 days ago1650344586IN
Frax Finance: AMO Minter
0 ETH0.0280877935.53477787
Sync Dollar Bala...145412512022-04-07 21:41:111057 days ago1649367671IN
Frax Finance: AMO Minter
0 ETH0.0435581255.10652187
Sync Dollar Bala...141819032022-02-11 1:46:111113 days ago1644543971IN
Frax Finance: AMO Minter
0 ETH0.0591815762.27364345
Sync Dollar Bala...139097902021-12-31 0:01:261155 days ago1640908886IN
Frax Finance: AMO Minter
0 ETH0.10486593142.54344867
Sync Dollar Bala...136999402021-11-28 3:17:591188 days ago1638069479IN
Frax Finance: AMO Minter
0 ETH0.081216298.68588052
Sync Dollar Bala...136998732021-11-28 3:01:531188 days ago1638068513IN
Frax Finance: AMO Minter
0 ETH0.10215512124.12877844
Sync Dollar Bala...136997292021-11-28 2:29:081188 days ago1638066548IN
Frax Finance: AMO Minter
0 ETH0.1090934132.55948764
Sync Dollar Bala...136996972021-11-28 2:18:321188 days ago1638065912IN
Frax Finance: AMO Minter
0 ETH0.08745683106.26887387
Sync Dollar Bala...136101462021-11-13 21:50:101202 days ago1636840210IN
Frax Finance: AMO Minter
0 ETH0.10682516155.01115433
Sync Dollar Bala...135662142021-11-07 0:33:541209 days ago1636245234IN
Frax Finance: AMO Minter
0 ETH0.07135722102.57471534
Sync Dollar Bala...135658042021-11-06 23:05:471209 days ago1636239947IN
Frax Finance: AMO Minter
0 ETH0.08380182120.46358822
Sync Dollar Bala...135602432021-11-06 2:01:171210 days ago1636164077IN
Frax Finance: AMO Minter
0 ETH0.0623107290.5851554
Sync Dollar Bala...135601822021-11-06 1:49:481210 days ago1636163388IN
Frax Finance: AMO Minter
0 ETH0.08022328116.6258191
Sync Dollar Bala...135342392021-11-01 23:52:021214 days ago1635810722IN
Frax Finance: AMO Minter
0 ETH0.11204852199.97666316
Sync Dollar Bala...134877352021-10-25 16:40:041222 days ago1635180004IN
Frax Finance: AMO Minter
0 ETH0.4685592154.14414741
Sync Dollar Bala...134693112021-10-22 19:32:441225 days ago1634931164IN
Frax Finance: AMO Minter
0 ETH0.09791261109.95079439
Sync Dollar Bala...134523092021-10-20 3:49:251227 days ago1634701765IN
Frax Finance: AMO Minter
0 ETH0.0660286173.93913905
Mint Fxs For AMO133680002021-10-06 22:06:181240 days ago1633557978IN
Frax Finance: AMO Minter
0 ETH0.10278812217
Mint Fxs For AMO133679952021-10-06 22:05:121240 days ago1633557912IN
Frax Finance: AMO Minter
0 ETH0.10548996222.70396126
Mint Frax For AM...133679912021-10-06 22:04:551240 days ago1633557895IN
Frax Finance: AMO Minter
0 ETH0.69668633224.31776468
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FraxAMOMinter

Compiler Version
v0.8.6+commit.11564f7e

Optimization Enabled:
Yes with 100000 runs

Other Settings:
default evmVersion, GNU GPLv2 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-09-14
*/

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.0;

// Sources flattened with hardhat v2.6.2 https://hardhat.org

// File contracts/Math/SafeMath.sol


/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}


// File contracts/Frax/IFrax.sol


interface IFrax {
  function COLLATERAL_RATIO_PAUSER() external view returns (bytes32);
  function DEFAULT_ADMIN_ADDRESS() external view returns (address);
  function DEFAULT_ADMIN_ROLE() external view returns (bytes32);
  function addPool(address pool_address ) external;
  function allowance(address owner, address spender ) external view returns (uint256);
  function approve(address spender, uint256 amount ) external returns (bool);
  function balanceOf(address account ) external view returns (uint256);
  function burn(uint256 amount ) external;
  function burnFrom(address account, uint256 amount ) external;
  function collateral_ratio_paused() external view returns (bool);
  function controller_address() external view returns (address);
  function creator_address() external view returns (address);
  function decimals() external view returns (uint8);
  function decreaseAllowance(address spender, uint256 subtractedValue ) external returns (bool);
  function eth_usd_consumer_address() external view returns (address);
  function eth_usd_price() external view returns (uint256);
  function frax_eth_oracle_address() external view returns (address);
  function frax_info() external view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256);
  function frax_pools(address ) external view returns (bool);
  function frax_pools_array(uint256 ) external view returns (address);
  function frax_price() external view returns (uint256);
  function frax_step() external view returns (uint256);
  function fxs_address() external view returns (address);
  function fxs_eth_oracle_address() external view returns (address);
  function fxs_price() external view returns (uint256);
  function genesis_supply() external view returns (uint256);
  function getRoleAdmin(bytes32 role ) external view returns (bytes32);
  function getRoleMember(bytes32 role, uint256 index ) external view returns (address);
  function getRoleMemberCount(bytes32 role ) external view returns (uint256);
  function globalCollateralValue() external view returns (uint256);
  function global_collateral_ratio() external view returns (uint256);
  function grantRole(bytes32 role, address account ) external;
  function hasRole(bytes32 role, address account ) external view returns (bool);
  function increaseAllowance(address spender, uint256 addedValue ) external returns (bool);
  function last_call_time() external view returns (uint256);
  function minting_fee() external view returns (uint256);
  function name() external view returns (string memory);
  function owner_address() external view returns (address);
  function pool_burn_from(address b_address, uint256 b_amount ) external;
  function pool_mint(address m_address, uint256 m_amount ) external;
  function price_band() external view returns (uint256);
  function price_target() external view returns (uint256);
  function redemption_fee() external view returns (uint256);
  function refreshCollateralRatio() external;
  function refresh_cooldown() external view returns (uint256);
  function removePool(address pool_address ) external;
  function renounceRole(bytes32 role, address account ) external;
  function revokeRole(bytes32 role, address account ) external;
  function setController(address _controller_address ) external;
  function setETHUSDOracle(address _eth_usd_consumer_address ) external;
  function setFRAXEthOracle(address _frax_oracle_addr, address _weth_address ) external;
  function setFXSAddress(address _fxs_address ) external;
  function setFXSEthOracle(address _fxs_oracle_addr, address _weth_address ) external;
  function setFraxStep(uint256 _new_step ) external;
  function setMintingFee(uint256 min_fee ) external;
  function setOwner(address _owner_address ) external;
  function setPriceBand(uint256 _price_band ) external;
  function setPriceTarget(uint256 _new_price_target ) external;
  function setRedemptionFee(uint256 red_fee ) external;
  function setRefreshCooldown(uint256 _new_cooldown ) external;
  function setTimelock(address new_timelock ) external;
  function symbol() external view returns (string memory);
  function timelock_address() external view returns (address);
  function toggleCollateralRatio() external;
  function totalSupply() external view returns (uint256);
  function transfer(address recipient, uint256 amount ) external returns (bool);
  function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool);
  function weth_address() external view returns (address);
}


// File contracts/FXS/IFxs.sol


interface IFxs {
  function DEFAULT_ADMIN_ROLE() external view returns(bytes32);
  function FRAXStablecoinAdd() external view returns(address);
  function FXS_DAO_min() external view returns(uint256);
  function allowance(address owner, address spender) external view returns(uint256);
  function approve(address spender, uint256 amount) external returns(bool);
  function balanceOf(address account) external view returns(uint256);
  function burn(uint256 amount) external;
  function burnFrom(address account, uint256 amount) external;
  function checkpoints(address, uint32) external view returns(uint32 fromBlock, uint96 votes);
  function decimals() external view returns(uint8);
  function decreaseAllowance(address spender, uint256 subtractedValue) external returns(bool);
  function genesis_supply() external view returns(uint256);
  function getCurrentVotes(address account) external view returns(uint96);
  function getPriorVotes(address account, uint256 blockNumber) external view returns(uint96);
  function getRoleAdmin(bytes32 role) external view returns(bytes32);
  function getRoleMember(bytes32 role, uint256 index) external view returns(address);
  function getRoleMemberCount(bytes32 role) external view returns(uint256);
  function grantRole(bytes32 role, address account) external;
  function hasRole(bytes32 role, address account) external view returns(bool);
  function increaseAllowance(address spender, uint256 addedValue) external returns(bool);
  function mint(address to, uint256 amount) external;
  function name() external view returns(string memory);
  function numCheckpoints(address) external view returns(uint32);
  function oracle_address() external view returns(address);
  function owner_address() external view returns(address);
  function pool_burn_from(address b_address, uint256 b_amount) external;
  function pool_mint(address m_address, uint256 m_amount) external;
  function renounceRole(bytes32 role, address account) external;
  function revokeRole(bytes32 role, address account) external;
  function setFRAXAddress(address frax_contract_address) external;
  function setFXSMinDAO(uint256 min_FXS) external;
  function setOracle(address new_oracle) external;
  function setOwner(address _owner_address) external;
  function setTimelock(address new_timelock) external;
  function symbol() external view returns(string memory);
  function timelock_address() external view returns(address);
  function toggleVotes() external;
  function totalSupply() external view returns(uint256);
  function trackingVotes() external view returns(bool);
  function transfer(address recipient, uint256 amount) external returns(bool);
  function transferFrom(address sender, address recipient, uint256 amount) external returns(bool);
}


// File contracts/Uniswap/TransferHelper.sol


// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
    }

    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
    }

    function safeTransferETH(address to, uint value) internal {
        (bool success,) = to.call{value:value}(new bytes(0));
        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
    }
}


// File contracts/Staking/Owned.sol


// https://docs.synthetix.io/contracts/Owned
contract Owned {
    address public owner;
    address public nominatedOwner;

    constructor (address _owner) public {
        require(_owner != address(0), "Owner address cannot be 0");
        owner = _owner;
        emit OwnerChanged(address(0), _owner);
    }

    function nominateNewOwner(address _owner) external onlyOwner {
        nominatedOwner = _owner;
        emit OwnerNominated(_owner);
    }

    function acceptOwnership() external {
        require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
        emit OwnerChanged(owner, nominatedOwner);
        owner = nominatedOwner;
        nominatedOwner = address(0);
    }

    modifier onlyOwner {
        require(msg.sender == owner, "Only the contract owner may perform this action");
        _;
    }

    event OwnerNominated(address newOwner);
    event OwnerChanged(address oldOwner, address newOwner);
}


// File contracts/Oracle/AggregatorV3Interface.sol


interface AggregatorV3Interface {

  function decimals() external view returns (uint8);
  function description() external view returns (string memory);
  function version() external view returns (uint256);

  // getRoundData and latestRoundData should both raise "No data present"
  // if they do not have data to report, instead of returning unset values
  // which could be misinterpreted as actual reported values.
  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

}


// File contracts/Frax/IFraxAMOMinter.sol


// MAY need to be updated
interface IFraxAMOMinter {
  function FRAX() external view returns(address);
  function FXS() external view returns(address);
  function acceptOwnership() external;
  function addAMO(address amo_address, bool sync_too) external;
  function allAMOAddresses() external view returns(address[] memory);
  function allAMOsLength() external view returns(uint256);
  function amoProfit(address amo_address) external view returns(int256);
  function amos(address) external view returns(bool);
  function amos_array(uint256) external view returns(address);
  function burnFXS(uint256 amount) external;
  function burnFraxFromAMO(uint256 frax_amount) external;
  function burnFxsFromAMO(uint256 fxs_amount) external;
  function col_idx() external view returns(uint256);
  function collatDollarBalance() external view returns(uint256);
  function collatDollarBalanceStored() external view returns(uint256);
  function collat_borrow_cap() external view returns(int256);
  function collat_borrowed_balances(address) external view returns(int256);
  function collat_borrowed_sum() external view returns(int256);
  function collateral_address() external view returns(address);
  function collateral_token() external view returns(address);
  function custodian_address() external view returns(address);
  function fraxDollarBalanceStored() external view returns(uint256);
  function giveCollatToAMO(address destination_amo, uint256 collat_amount) external;
  function min_cr() external view returns(uint256);
  function mintFraxForAMO(address destination_amo, uint256 frax_amount) external;
  function mint_balances(address) external view returns(int256);
  function mint_cap() external view returns(int256);
  function mint_sum() external view returns(int256);
  function missing_decimals() external view returns(uint256);
  function nominateNewOwner(address _owner) external;
  function nominatedOwner() external view returns(address);
  function override_collat_balance() external view returns(bool);
  function override_collat_balance_amount() external view returns(uint256);
  function owner() external view returns(address);
  function pool() external view returns(address);
  function receiveCollatFromAMO(uint256 usdc_amount) external;
  function recoverERC20(address tokenAddress, uint256 tokenAmount) external;
  function removeAMO(address amo_address, bool sync_too) external;
  function setCustodian(address _custodian_address) external;
  function setFraxPool(address _pool_address) external;
  function setMinimumCollateralRatio(uint256 _min_cr) external;
  function setMintCap(uint256 _mint_cap) external;
  function setOverrideCollatBalance(bool _state, uint256 _balance) external;
  function setTimelock(address new_timelock) external;
  function syncDollarBalances() external;
  function timelock_address() external view returns(address);
  function unspentProfitGlobal() external view returns(int256);
}


// File contracts/Common/Context.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 Context {
    function _msgSender() internal view virtual returns (address payable) {
        return payable(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;
    }
}


// File contracts/ERC20/IERC20.sol



/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see {ERC20Detailed}.
 */
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 contracts/Utils/Address.sol


/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @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);
    }

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(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 contracts/ERC20/ERC20.sol





/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20Mintable}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
 
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;
    uint8 private _decimals;
    
    /**
     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
     * a default value of 18.
     *
     * To select a different value for {decimals}, use {_setupDecimals}.
     *
     * All three of these values are immutable: they can only be set once during
     * construction.
     */
    constructor (string memory __name, string memory __symbol) public {
        _name = __name;
        _symbol = __symbol;
        _decimals = 18;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.approve(address spender, uint256 amount)
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from the caller.
     *
     * See {ERC20-_burn}.
     */
    function burn(uint256 amount) public virtual {
        _burn(_msgSender(), amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, deducting from the caller's
     * allowance.
     *
     * See {ERC20-_burn} and {ERC20-allowance}.
     *
     * Requirements:
     *
     * - the caller must have allowance for `accounts`'s tokens of at least
     * `amount`.
     */
    function burnFrom(address account, uint256 amount) public virtual {
        uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance");

        _approve(account, _msgSender(), decreasedAllowance);
        _burn(account, amount);
    }


    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See {_burn} and {_approve}.
     */
    function _burnFrom(address account, uint256 amount) internal virtual {
        _burn(account, amount);
        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of `from`'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of `from`'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}


// File contracts/Frax/Pools/FraxPoolV3.sol


// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ============================ FraxPoolV3 ============================
// ====================================================================
// Allows multiple stablecoins (fixed amount at initialization) as collateral
// LUSD, sUSD, USDP, Wrapped UST, and FEI initially
// For this pool, the goal is to accept crypto-backed / overcollateralized stablecoins to limit
// government / regulatory risk (e.g. USDC blacklisting until holders KYC)

// Frax Finance: https://github.com/FraxFinance

// Primary Author(s)
// Travis Moore: https://github.com/FortisFortuna

// Reviewer(s) / Contributor(s)
// Jason Huan: https://github.com/jasonhuan
// Sam Kazemian: https://github.com/samkazemian
// Dennis: github.com/denett
// Hameed








contract FraxPoolV3 is Owned {
    using SafeMath for uint256;
    // SafeMath automatically included in Solidity >= 8.0.0

    /* ========== STATE VARIABLES ========== */

    // Core
    address public timelock_address;
    address public custodian_address; // Custodian is an EOA (or msig) with pausing privileges only, in case of an emergency
    IFrax private FRAX = IFrax(0x853d955aCEf822Db058eb8505911ED77F175b99e);
    IFxs private FXS = IFxs(0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0);
    mapping(address => bool) public amo_minter_addresses; // minter address -> is it enabled
    AggregatorV3Interface public priceFeedFRAXUSD = AggregatorV3Interface(0xB9E1E3A9feFf48998E45Fa90847ed4D467E8BcfD);
    AggregatorV3Interface public priceFeedFXSUSD = AggregatorV3Interface(0x6Ebc52C8C1089be9eB3945C4350B68B8E4C2233f);
    uint256 private chainlink_frax_usd_decimals;
    uint256 private chainlink_fxs_usd_decimals;

    // Collateral
    address[] public collateral_addresses;
    string[] public collateral_symbols;
    uint256[] public missing_decimals; // Number of decimals needed to get to E18. collateral index -> missing_decimals
    uint256[] public pool_ceilings; // Total across all collaterals. Accounts for missing_decimals
    uint256[] public collateral_prices; // Stores price of the collateral, if price is paused
    mapping(address => uint256) public collateralAddrToIdx; // collateral addr -> collateral index
    mapping(address => bool) public enabled_collaterals; // collateral address -> is it enabled
    
    // Redeem related
    mapping (address => uint256) public redeemFXSBalances;
    mapping (address => mapping(uint256 => uint256)) public redeemCollateralBalances; // Address -> collateral index -> balance
    uint256[] public unclaimedPoolCollateral; // collateral index -> balance
    uint256 public unclaimedPoolFXS;
    mapping (address => uint256) public lastRedeemed; // Collateral independent
    uint256 public redemption_delay = 2; // Number of blocks to wait before being able to collectRedemption()
    uint256 public redeem_price_threshold = 990000; // $0.99
    uint256 public mint_price_threshold = 1010000; // $1.01
    
    // Buyback related
    mapping(uint256 => uint256) public bbkHourlyCum; // Epoch hour ->  Collat out in that hour (E18)
    uint256 public bbkMaxColE18OutPerHour = 1000e18;

    // Recollat related
    mapping(uint256 => uint256) public rctHourlyCum; // Epoch hour ->  FXS out in that hour
    uint256 public rctMaxFxsOutPerHour = 1000e18;

    // Fees and rates
    // getters are in collateral_information()
    uint256[] private minting_fee;
    uint256[] private redemption_fee;
    uint256[] private buyback_fee;
    uint256[] private recollat_fee;
    uint256 public bonus_rate; // Bonus rate on FXS minted during recollateralize(); 6 decimals of precision, set to 0.75% on genesis
    
    // Constants for various precisions
    uint256 private constant PRICE_PRECISION = 1e6;

    // Pause variables
    // getters are in collateral_information()
    bool[] private mintPaused; // Collateral-specific
    bool[] private redeemPaused; // Collateral-specific
    bool[] private recollateralizePaused; // Collateral-specific
    bool[] private buyBackPaused; // Collateral-specific

    /* ========== MODIFIERS ========== */

    modifier onlyByOwnGov() {
        require(msg.sender == timelock_address || msg.sender == owner, "Not owner or timelock");
        _;
    }

    modifier onlyByOwnGovCust() {
        require(msg.sender == timelock_address || msg.sender == owner || msg.sender == custodian_address, "Not owner, tlck, or custd");
        _;
    }

    modifier onlyAMOMinters() {
        require(amo_minter_addresses[msg.sender], "Not an AMO Minter");
        _;
    }

    modifier collateralEnabled(uint256 col_idx) {
        require(enabled_collaterals[collateral_addresses[col_idx]], "Collateral disabled");
        _;
    }
 
    /* ========== CONSTRUCTOR ========== */
    
    constructor (
        address _pool_manager_address,
        address _custodian_address,
        address _timelock_address,
        address[] memory _collateral_addresses,
        uint256[] memory _pool_ceilings,
        uint256[] memory _initial_fees
    ) Owned(_pool_manager_address){
        // Core
        timelock_address = _timelock_address;
        custodian_address = _custodian_address;

        // Fill collateral info
        collateral_addresses = _collateral_addresses;
        for (uint256 i = 0; i < _collateral_addresses.length; i++){ 
            // For fast collateral address -> collateral idx lookups later
            collateralAddrToIdx[_collateral_addresses[i]] = i;

            // Set all of the collaterals initially to disabled
            enabled_collaterals[_collateral_addresses[i]] = false;

            // Add in the missing decimals
            missing_decimals.push(uint256(18).sub(ERC20(_collateral_addresses[i]).decimals()));

            // Add in the collateral symbols
            collateral_symbols.push(ERC20(_collateral_addresses[i]).symbol());

            // Initialize unclaimed pool collateral
            unclaimedPoolCollateral.push(0);

            // Initialize paused prices to $1 as a backup
            collateral_prices.push(PRICE_PRECISION);

            // Handle the fees
            minting_fee.push(_initial_fees[0]);
            redemption_fee.push(_initial_fees[1]);
            buyback_fee.push(_initial_fees[2]);
            recollat_fee.push(_initial_fees[3]);

            // Handle the pauses
            mintPaused.push(false);
            redeemPaused.push(false);
            recollateralizePaused.push(false);
            buyBackPaused.push(false);
        }

        // Pool ceiling
        pool_ceilings = _pool_ceilings;

        // Set the decimals
        chainlink_frax_usd_decimals = priceFeedFRAXUSD.decimals();
        chainlink_fxs_usd_decimals = priceFeedFXSUSD.decimals();
    }

    /* ========== STRUCTS ========== */
    
    struct CollateralInformation {
        uint256 index;
        string symbol;
        address col_addr;
        bool is_enabled;
        uint256 missing_decs;
        uint256 price;
        uint256 pool_ceiling;
        bool mint_paused;
        bool redeem_paused;
        bool recollat_paused;
        bool buyback_paused;
        uint256 minting_fee;
        uint256 redemption_fee;
        uint256 buyback_fee;
        uint256 recollat_fee;
    }

    /* ========== VIEWS ========== */

    // Helpful for UIs
    function collateral_information(address collat_address) external view returns (CollateralInformation memory return_data){
        require(enabled_collaterals[collat_address], "Invalid collateral");

        // Get the index
        uint256 idx = collateralAddrToIdx[collat_address];
        
        return_data = CollateralInformation(
            idx, // [0]
            collateral_symbols[idx], // [1]
            collat_address, // [2]
            enabled_collaterals[collat_address], // [3]
            missing_decimals[idx], // [4]
            collateral_prices[idx], // [5]
            pool_ceilings[idx], // [6]
            mintPaused[idx], // [7]
            redeemPaused[idx], // [8]
            recollateralizePaused[idx], // [9]
            buyBackPaused[idx], // [10]
            minting_fee[idx], // [11]
            redemption_fee[idx], // [12]
            buyback_fee[idx], // [13]
            recollat_fee[idx] // [14]
        );
    }

    function allCollaterals() external view returns (address[] memory) {
        return collateral_addresses;
    }

    function getFRAXPrice() public view returns (uint256) {
        ( , int price, , , ) = priceFeedFRAXUSD.latestRoundData();
        return uint256(price).mul(PRICE_PRECISION).div(10 ** chainlink_frax_usd_decimals);
    }

    function getFXSPrice() public view returns (uint256) {
        ( , int price, , , ) = priceFeedFXSUSD.latestRoundData();
        return uint256(price).mul(PRICE_PRECISION).div(10 ** chainlink_fxs_usd_decimals);
    }

    // Returns the FRAX value in collateral tokens
    function getFRAXInCollateral(uint256 col_idx, uint256 frax_amount) public view returns (uint256) {
        return frax_amount.mul(PRICE_PRECISION).div(10 ** missing_decimals[col_idx]).div(collateral_prices[col_idx]);
    }

    // Used by some functions.
    function freeCollatBalance(uint256 col_idx) public view returns (uint256) {
        return ERC20(collateral_addresses[col_idx]).balanceOf(address(this)).sub(unclaimedPoolCollateral[col_idx]);
    }

    // Returns dollar value of collateral held in this Frax pool, in E18
    function collatDollarBalance() external view returns (uint256 balance_tally) {
        balance_tally = 0;

        // Test 1
        for (uint256 i = 0; i < collateral_addresses.length; i++){ 
            balance_tally += freeCollatBalance(i).mul(10 ** missing_decimals[i]).mul(collateral_prices[i]).div(PRICE_PRECISION);
        }

    }

    function comboCalcBbkRct(uint256 cur, uint256 max, uint256 theo) internal pure returns (uint256) {
        if (cur >= max) {
            // If the hourly limit has already been reached, return 0;
            return 0;
        }
        else {
            // Get the available amount
            uint256 available = max.sub(cur);

            if (theo >= available) {
                // If the the theoretical is more than the available, return the available
                return available;
            }
            else {
                // Otherwise, return the theoretical amount
                return theo;
            }
        } 
    }

    // Returns the value of excess collateral (in E18) held globally, compared to what is needed to maintain the global collateral ratio
    // Also has throttling to avoid dumps during large price movements
    function buybackAvailableCollat() public view returns (uint256) {
        uint256 total_supply = FRAX.totalSupply();
        uint256 global_collateral_ratio = FRAX.global_collateral_ratio();
        uint256 global_collat_value = FRAX.globalCollateralValue();

        if (global_collateral_ratio > PRICE_PRECISION) global_collateral_ratio = PRICE_PRECISION; // Handles an overcollateralized contract with CR > 1
        uint256 required_collat_dollar_value_d18 = (total_supply.mul(global_collateral_ratio)).div(PRICE_PRECISION); // Calculates collateral needed to back each 1 FRAX with $1 of collateral at current collat ratio
        
        if (global_collat_value > required_collat_dollar_value_d18) {
            // Get the theoretical buyback amount
            uint256 theoretical_bbk_amt = global_collat_value.sub(required_collat_dollar_value_d18);

            // See how much has collateral has been issued this hour
            uint256 current_hr_bbk = bbkHourlyCum[curEpochHr()];

            // Account for the throttling
            return comboCalcBbkRct(current_hr_bbk, bbkMaxColE18OutPerHour, theoretical_bbk_amt);
        }
        else return 0;
    }

    // Returns the missing amount of collateral (in E18) needed to maintain the collateral ratio
    function recollatTheoColAvailableE18() public view returns (uint256) {
        uint256 frax_total_supply = FRAX.totalSupply();
        uint256 effective_collateral_ratio = FRAX.globalCollateralValue().mul(PRICE_PRECISION).div(frax_total_supply); // Returns it in 1e6
        
        uint256 desired_collat_e24 = (FRAX.global_collateral_ratio()).mul(frax_total_supply);
        uint256 effective_collat_e24 = effective_collateral_ratio.mul(frax_total_supply);

        // Return 0 if already overcollateralized
        // Otherwise, return the deficiency
        if (effective_collat_e24 >= desired_collat_e24) return 0;
        else {
            return (desired_collat_e24.sub(effective_collat_e24)).div(PRICE_PRECISION);
        }
    }

    // Returns the value of FXS available to be used for recollats
    // Also has throttling to avoid dumps during large price movements
    function recollatAvailableFxs() public view returns (uint256) {
        uint256 fxs_price = getFXSPrice();

        // Get the amount of collateral theoretically available
        uint256 recollat_theo_available_e18 = recollatTheoColAvailableE18();

        // Get the amount of FXS theoretically outputtable
        uint256 fxs_theo_out = recollat_theo_available_e18.mul(PRICE_PRECISION).div(fxs_price);

        // See how much FXS has been issued this hour
        uint256 current_hr_rct = rctHourlyCum[curEpochHr()];

        // Account for the throttling
        return comboCalcBbkRct(current_hr_rct, rctMaxFxsOutPerHour, fxs_theo_out);
    }

    // Returns the current epoch hour
    function curEpochHr() public view returns (uint256) {
        return (block.timestamp / 3600); // Truncation desired
    }

    /* ========== PUBLIC FUNCTIONS ========== */

     function mintFrax(
        uint256 col_idx, 
        uint256 frax_amt,
        uint256 frax_out_min,
        bool one_to_one_override
    ) external collateralEnabled(col_idx) returns (
        uint256 total_frax_mint, 
        uint256 collat_needed, 
        uint256 fxs_needed
    ) {
        require(mintPaused[col_idx] == false, "Minting is paused");

        // Prevent unneccessary mints
        require(getFRAXPrice() >= mint_price_threshold, "Frax price too low");

        uint256 global_collateral_ratio = FRAX.global_collateral_ratio();

        if (one_to_one_override || global_collateral_ratio >= PRICE_PRECISION) { 
            // 1-to-1, overcollateralized, or user selects override
            collat_needed = getFRAXInCollateral(col_idx, frax_amt);
            fxs_needed = 0;
        } else if (global_collateral_ratio == 0) { 
            // Algorithmic
            collat_needed = 0;
            fxs_needed = frax_amt.mul(PRICE_PRECISION).div(getFXSPrice());
        } else { 
            // Fractional
            uint256 frax_for_collat = frax_amt.mul(global_collateral_ratio).div(PRICE_PRECISION);
            uint256 frax_for_fxs = frax_amt.sub(frax_for_collat);
            collat_needed = getFRAXInCollateral(col_idx, frax_for_collat);
            fxs_needed = frax_for_fxs.mul(PRICE_PRECISION).div(getFXSPrice());
        }

        // Subtract the minting fee
        total_frax_mint = (frax_amt.mul(PRICE_PRECISION.sub(minting_fee[col_idx]))).div(PRICE_PRECISION);

        // Checks
        require((frax_out_min <= total_frax_mint), "FRAX slippage");
        require(freeCollatBalance(col_idx).add(collat_needed) <= pool_ceilings[col_idx], "Pool ceiling");

        // Take the FXS and collateral first
        FXS.pool_burn_from(msg.sender, fxs_needed);
        TransferHelper.safeTransferFrom(collateral_addresses[col_idx], msg.sender, address(this), collat_needed);

        // Mint the FRAX
        FRAX.pool_mint(msg.sender, total_frax_mint);
    }

    function redeemFrax(
        uint256 col_idx, 
        uint256 frax_amount, 
        uint256 fxs_out_min, 
        uint256 col_out_min
    ) external collateralEnabled(col_idx) returns (
        uint256 collat_out, 
        uint256 fxs_out
    ) {
        require(redeemPaused[col_idx] == false, "Redeeming is paused");

        // Prevent unneccessary redemptions that could adversely affect the FXS price
        require(getFRAXPrice() <= redeem_price_threshold, "Frax price too high");

        uint256 global_collateral_ratio = FRAX.global_collateral_ratio();
        uint256 frax_after_fee = (frax_amount.mul(PRICE_PRECISION.sub(redemption_fee[col_idx]))).div(PRICE_PRECISION);

        // Assumes $1 FRAX in all cases
        if(global_collateral_ratio >= PRICE_PRECISION) { 
            // 1-to-1 or overcollateralized
            collat_out = frax_after_fee
                            .mul(collateral_prices[col_idx])
                            .div(10 ** (6 + missing_decimals[col_idx])); // PRICE_PRECISION + missing decimals
            fxs_out = 0;
        } else if (global_collateral_ratio == 0) { 
            // Algorithmic
            fxs_out = frax_after_fee
                            .mul(PRICE_PRECISION)
                            .div(getFXSPrice());
            collat_out = 0;
        } else { 
            // Fractional
            collat_out = frax_after_fee
                            .mul(global_collateral_ratio)
                            .mul(collateral_prices[col_idx])
                            .div(10 ** (12 + missing_decimals[col_idx])); // PRICE_PRECISION ^2 + missing decimals
            fxs_out = frax_after_fee
                            .mul(PRICE_PRECISION.sub(global_collateral_ratio))
                            .div(getFXSPrice()); // PRICE_PRECISIONS CANCEL OUT
        }

        // Checks
        require(collat_out <= (ERC20(collateral_addresses[col_idx])).balanceOf(address(this)).sub(unclaimedPoolCollateral[col_idx]), "Insufficient pool collateral");
        require(collat_out >= col_out_min, "Collateral slippage");
        require(fxs_out >= fxs_out_min, "FXS slippage");

        // Account for the redeem delay
        redeemCollateralBalances[msg.sender][col_idx] = redeemCollateralBalances[msg.sender][col_idx].add(collat_out);
        unclaimedPoolCollateral[col_idx] = unclaimedPoolCollateral[col_idx].add(collat_out);

        redeemFXSBalances[msg.sender] = redeemFXSBalances[msg.sender].add(fxs_out);
        unclaimedPoolFXS = unclaimedPoolFXS.add(fxs_out);

        lastRedeemed[msg.sender] = block.number;

        FRAX.pool_burn_from(msg.sender, frax_amount);
        FXS.pool_mint(address(this), fxs_out);
    }

    // After a redemption happens, transfer the newly minted FXS and owed collateral from this pool
    // contract to the user. Redemption is split into two functions to prevent flash loans from being able
    // to take out FRAX/collateral from the system, use an AMM to trade the new price, and then mint back into the system.
    function collectRedemption(uint256 col_idx) external returns (uint256 fxs_amount, uint256 collateral_amount) {
        require(redeemPaused[col_idx] == false, "Redeeming is paused");
        require((lastRedeemed[msg.sender].add(redemption_delay)) <= block.number, "Too soon");
        bool sendFXS = false;
        bool sendCollateral = false;

        // Use Checks-Effects-Interactions pattern
        if(redeemFXSBalances[msg.sender] > 0){
            fxs_amount = redeemFXSBalances[msg.sender];
            redeemFXSBalances[msg.sender] = 0;
            unclaimedPoolFXS = unclaimedPoolFXS.sub(fxs_amount);
            sendFXS = true;
        }
        
        if(redeemCollateralBalances[msg.sender][col_idx] > 0){
            collateral_amount = redeemCollateralBalances[msg.sender][col_idx];
            redeemCollateralBalances[msg.sender][col_idx] = 0;
            unclaimedPoolCollateral[col_idx] = unclaimedPoolCollateral[col_idx].sub(collateral_amount);
            sendCollateral = true;
        }

        // Send out the tokens
        if(sendFXS){
            TransferHelper.safeTransfer(address(FXS), msg.sender, fxs_amount);
        }
        if(sendCollateral){
            TransferHelper.safeTransfer(collateral_addresses[col_idx], msg.sender, collateral_amount);
        }
    }

    // Function can be called by an FXS holder to have the protocol buy back FXS with excess collateral value from a desired collateral pool
    // This can also happen if the collateral ratio > 1
    function buyBackFxs(uint256 col_idx, uint256 fxs_amount, uint256 col_out_min) external collateralEnabled(col_idx) returns (uint256 col_out) {
        require(buyBackPaused[col_idx] == false, "Buyback is paused");
        uint256 fxs_price = getFXSPrice();
        uint256 available_excess_collat_dv = buybackAvailableCollat();

        // If the total collateral value is higher than the amount required at the current collateral ratio then buy back up to the possible FXS with the desired collateral
        require(available_excess_collat_dv > 0, "Insuf Collat Avail For BBK");

        // Make sure not to take more than is available
        uint256 fxs_dollar_value_d18 = fxs_amount.mul(fxs_price).div(PRICE_PRECISION);
        require(fxs_dollar_value_d18 <= available_excess_collat_dv, "Insuf Collat Avail For BBK");

        // Get the equivalent amount of collateral based on the market value of FXS provided 
        uint256 collateral_equivalent_d18 = fxs_dollar_value_d18.mul(PRICE_PRECISION).div(collateral_prices[col_idx]);
        col_out = collateral_equivalent_d18.div(10 ** missing_decimals[col_idx]); // In its natural decimals()

        // Subtract the buyback fee
        col_out = (col_out.mul(PRICE_PRECISION.sub(buyback_fee[col_idx]))).div(PRICE_PRECISION);

        // Check for slippage
        require(col_out >= col_out_min, "Collateral slippage");

        // Take in and burn the FXS, then send out the collateral
        FXS.pool_burn_from(msg.sender, fxs_amount);
        TransferHelper.safeTransfer(collateral_addresses[col_idx], msg.sender, col_out);

        // Increment the outbound collateral, in E18, for that hour
        // Used for buyback throttling
        bbkHourlyCum[curEpochHr()] += collateral_equivalent_d18;
    }

    // When the protocol is recollateralizing, we need to give a discount of FXS to hit the new CR target
    // Thus, if the target collateral ratio is higher than the actual value of collateral, minters get FXS for adding collateral
    // This function simply rewards anyone that sends collateral to a pool with the same amount of FXS + the bonus rate
    // Anyone can call this function to recollateralize the protocol and take the extra FXS value from the bonus rate as an arb opportunity
    function recollateralize(uint256 col_idx, uint256 collateral_amount, uint256 fxs_out_min) external collateralEnabled(col_idx) returns (uint256 fxs_out) {
        require(recollateralizePaused[col_idx] == false, "Recollat is paused");
        uint256 collateral_amount_d18 = collateral_amount * (10 ** missing_decimals[col_idx]);
        uint256 fxs_price = getFXSPrice();

        // Get the amount of FXS actually available (accounts for throttling)
        uint256 fxs_actually_available = recollatAvailableFxs();

        // Calculated the attempted amount of FXS
        fxs_out = collateral_amount_d18.mul(PRICE_PRECISION.add(bonus_rate).sub(recollat_fee[col_idx])).div(fxs_price);

        // Make sure there is FXS available
        require(fxs_out <= fxs_actually_available, "Insuf FXS Avail For RCT");

        // Check slippage
        require(fxs_out >= fxs_out_min, "FXS slippage");

        // Don't take in more collateral than the pool ceiling for this token allows
        require(freeCollatBalance(col_idx).add(collateral_amount) <= pool_ceilings[col_idx], "Pool ceiling");

        // Take in the collateral and pay out the FXS
        TransferHelper.safeTransferFrom(collateral_addresses[col_idx], msg.sender, address(this), collateral_amount);
        FXS.pool_mint(msg.sender, fxs_out);

        // Increment the outbound FXS, in E18
        // Used for recollat throttling
        rctHourlyCum[curEpochHr()] += fxs_out;
    }

    // Bypasses the gassy mint->redeem cycle for AMOs to borrow collateral
    function amoMinterBorrow(uint256 collateral_amount) external onlyAMOMinters {
        // Checks the col_idx of the minter as an additional safety check
        uint256 minter_col_idx = IFraxAMOMinter(msg.sender).col_idx();

        // Transfer
        TransferHelper.safeTransfer(collateral_addresses[minter_col_idx], msg.sender, collateral_amount);
    }

    /* ========== RESTRICTED FUNCTIONS, CUSTODIAN CAN CALL TOO ========== */

    function toggleMRBR(uint256 col_idx, uint8 tog_idx) external onlyByOwnGovCust {
        if (tog_idx == 0) mintPaused[col_idx] = !mintPaused[col_idx];
        else if (tog_idx == 1) redeemPaused[col_idx] = !redeemPaused[col_idx];
        else if (tog_idx == 2) buyBackPaused[col_idx] = !buyBackPaused[col_idx];
        else if (tog_idx == 3) recollateralizePaused[col_idx] = !recollateralizePaused[col_idx];

        emit MRBRToggled(col_idx, tog_idx);
    }

    /* ========== RESTRICTED FUNCTIONS, GOVERNANCE ONLY ========== */

    // Add an AMO Minter
    function addAMOMinter(address amo_minter_addr) external onlyByOwnGov {
        require(amo_minter_addr != address(0), "Zero address detected");

        // Make sure the AMO Minter has collatDollarBalance()
        uint256 collat_val_e18 = IFraxAMOMinter(amo_minter_addr).collatDollarBalance();
        require(collat_val_e18 >= 0, "Invalid AMO");

        amo_minter_addresses[amo_minter_addr] = true;

        emit AMOMinterAdded(amo_minter_addr);
    }

    // Remove an AMO Minter 
    function removeAMOMinter(address amo_minter_addr) external onlyByOwnGov {
        amo_minter_addresses[amo_minter_addr] = false;
        
        emit AMOMinterRemoved(amo_minter_addr);
    }

    function setCollateralPrice(uint256 col_idx, uint256 _new_price) external onlyByOwnGov {
        collateral_prices[col_idx] = _new_price;

        emit CollateralPriceSet(col_idx, _new_price);
    }

    // Could also be called toggleCollateral
    function toggleCollateral(uint256 col_idx) external onlyByOwnGov {
        address col_address = collateral_addresses[col_idx];
        enabled_collaterals[col_address] = !enabled_collaterals[col_address];

        emit CollateralToggled(col_idx, enabled_collaterals[col_address]);
    }

    function setPoolCeiling(uint256 col_idx, uint256 new_ceiling) external onlyByOwnGov {
        pool_ceilings[col_idx] = new_ceiling;

        emit PoolCeilingSet(col_idx, new_ceiling);
    }

    function setFees(uint256 col_idx, uint256 new_mint_fee, uint256 new_redeem_fee, uint256 new_buyback_fee, uint256 new_recollat_fee) external onlyByOwnGov {
        minting_fee[col_idx] = new_mint_fee;
        redemption_fee[col_idx] = new_redeem_fee;
        buyback_fee[col_idx] = new_buyback_fee;
        recollat_fee[col_idx] = new_recollat_fee;

        emit FeesSet(col_idx, new_mint_fee, new_redeem_fee, new_buyback_fee, new_recollat_fee);
    }

    function setPoolParameters(uint256 new_bonus_rate, uint256 new_redemption_delay) external onlyByOwnGov {
        bonus_rate = new_bonus_rate;
        redemption_delay = new_redemption_delay;
        emit PoolParametersSet(new_bonus_rate, new_redemption_delay);
    }

    function setPriceThresholds(uint256 new_mint_price_threshold, uint256 new_redeem_price_threshold) external onlyByOwnGov {
        mint_price_threshold = new_mint_price_threshold;
        redeem_price_threshold = new_redeem_price_threshold;
        emit PriceThresholdsSet(new_mint_price_threshold, new_redeem_price_threshold);
    }

    function setBbkRctPerHour(uint256 _bbkMaxColE18OutPerHour, uint256 _rctMaxFxsOutPerHour) external onlyByOwnGov {
        bbkMaxColE18OutPerHour = _bbkMaxColE18OutPerHour;
        rctMaxFxsOutPerHour = _rctMaxFxsOutPerHour;
        emit BbkRctPerHourSet(_bbkMaxColE18OutPerHour, _rctMaxFxsOutPerHour);
    }

    // Set the Chainlink oracles
    function setOracles(address _frax_usd_chainlink_addr, address _fxs_usd_chainlink_addr) external onlyByOwnGov {
        // Set the instances
        priceFeedFRAXUSD = AggregatorV3Interface(_frax_usd_chainlink_addr);
        priceFeedFXSUSD = AggregatorV3Interface(_fxs_usd_chainlink_addr);

        // Set the decimals
        chainlink_frax_usd_decimals = priceFeedFRAXUSD.decimals();
        chainlink_fxs_usd_decimals = priceFeedFXSUSD.decimals();
        
        emit OraclesSet(_frax_usd_chainlink_addr, _fxs_usd_chainlink_addr);
    }

    function setCustodian(address new_custodian) external onlyByOwnGov {
        custodian_address = new_custodian;

        emit CustodianSet(new_custodian);
    }

    function setTimelock(address new_timelock) external onlyByOwnGov {
        timelock_address = new_timelock;

        emit TimelockSet(new_timelock);
    }

    /* ========== EVENTS ========== */
    event CollateralToggled(uint256 col_idx, bool new_state);
    event PoolCeilingSet(uint256 col_idx, uint256 new_ceiling);
    event FeesSet(uint256 col_idx, uint256 new_mint_fee, uint256 new_redeem_fee, uint256 new_buyback_fee, uint256 new_recollat_fee);
    event PoolParametersSet(uint256 new_bonus_rate, uint256 new_redemption_delay);
    event PriceThresholdsSet(uint256 new_bonus_rate, uint256 new_redemption_delay);
    event BbkRctPerHourSet(uint256 bbkMaxColE18OutPerHour, uint256 rctMaxFxsOutPerHour);
    event AMOMinterAdded(address amo_minter_addr);
    event AMOMinterRemoved(address amo_minter_addr);
    event OraclesSet(address frax_usd_chainlink_addr, address fxs_usd_chainlink_addr);
    event CustodianSet(address new_custodian);
    event TimelockSet(address new_timelock);
    event MRBRToggled(uint256 col_idx, uint8 tog_idx);
    event CollateralPriceSet(uint256 col_idx, uint256 new_price);
}


// File contracts/Frax/Pools/IFraxPool.sol


interface IFraxPool {
    function minting_fee() external returns (uint256);
    function redeemCollateralBalances(address addr) external returns (uint256);
    function redemption_fee() external returns (uint256);
    function buyback_fee() external returns (uint256);
    function recollat_fee() external returns (uint256);
    function collatDollarBalance() external returns (uint256);
    function availableExcessCollatDV() external returns (uint256);
    function getCollateralPrice() external returns (uint256);
    function setCollatETHOracle(address _collateral_weth_oracle_address, address _weth_address) external;
    function mint1t1FRAX(uint256 collateral_amount, uint256 FRAX_out_min) external;
    function mintAlgorithmicFRAX(uint256 fxs_amount_d18, uint256 FRAX_out_min) external;
    function mintFractionalFRAX(uint256 collateral_amount, uint256 fxs_amount, uint256 FRAX_out_min) external;
    function redeem1t1FRAX(uint256 FRAX_amount, uint256 COLLATERAL_out_min) external;
    function redeemFractionalFRAX(uint256 FRAX_amount, uint256 FXS_out_min, uint256 COLLATERAL_out_min) external;
    function redeemAlgorithmicFRAX(uint256 FRAX_amount, uint256 FXS_out_min) external;
    function collectRedemption() external;
    function recollateralizeFRAX(uint256 collateral_amount, uint256 FXS_out_min) external;
    function buyBackFXS(uint256 FXS_amount, uint256 COLLATERAL_out_min) external;
    function toggleMinting() external;
    function toggleRedeeming() external;
    function toggleRecollateralize() external;
    function toggleBuyBack() external;
    function toggleCollateralPrice(uint256 _new_price) external;
    function setPoolParameters(uint256 new_ceiling, uint256 new_bonus_rate, uint256 new_redemption_delay, uint256 new_mint_fee, uint256 new_redeem_fee, uint256 new_buyback_fee, uint256 new_recollat_fee) external;
    function setTimelock(address new_timelock) external;
    function setOwner(address _owner_address) external;
}


// File contracts/Misc_AMOs/IAMO.sol

pragma experimental ABIEncoderV2;

interface IAMO {
    function dollarBalances() external view returns (uint256 frax_val_e18, uint256 collat_val_e18);
}


// File contracts/Frax/FraxAMOMinter.sol


// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// =========================== FraxAMOMinter ==========================
// ====================================================================
// globalCollateralValue() in Frax.sol is gassy because of the loop and all of the AMOs attached to it. 
// This minter would be single mint point for all of the AMOs, and would track the collatDollarBalance with a
// state variable after any mint occurs, or manually with a sync() call
// Frax Finance: https://github.com/FraxFinance

// Primary Author(s)
// Travis Moore: https://github.com/FortisFortuna

// Reviewer(s) / Contributor(s)
// Jason Huan: https://github.com/jasonhuan
// Sam Kazemian: https://github.com/samkazemian
// Dennis: github.com/denett
// Hameed









contract FraxAMOMinter is Owned {
    // SafeMath automatically included in Solidity >= 8.0.0

    /* ========== STATE VARIABLES ========== */

    // Core
    IFrax public FRAX = IFrax(0x853d955aCEf822Db058eb8505911ED77F175b99e);
    IFxs public FXS = IFxs(0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0);
    ERC20 public collateral_token;
    FraxPoolV3 public pool = FraxPoolV3(0x2fE065e6FFEf9ac95ab39E5042744d695F560729);
    IFraxPool public old_pool = IFraxPool(0x1864Ca3d47AaB98Ee78D11fc9DCC5E7bADdA1c0d);
    address public timelock_address;
    address public custodian_address;

    // Collateral related
    address public collateral_address;
    uint256 public col_idx;

    // AMO addresses
    address[] public amos_array;
    mapping(address => bool) public amos; // Mapping is also used for faster verification

    // Price constants
    uint256 private constant PRICE_PRECISION = 1e6;

    // Max amount of collateral the contract can borrow from the FraxPool
    int256 public collat_borrow_cap = int256(10000000e6);

    // Max amount of FRAX and FXS this contract can mint
    int256 public frax_mint_cap = int256(100000000e18);
    int256 public fxs_mint_cap = int256(100000000e18);

    // Minimum collateral ratio needed for new FRAX minting
    uint256 public min_cr = 810000;

    // Frax mint balances
    mapping(address => int256) public frax_mint_balances; // Amount of FRAX the contract minted, by AMO
    int256 public frax_mint_sum = 0; // Across all AMOs

    // Fxs mint balances
    mapping(address => int256) public fxs_mint_balances; // Amount of FXS the contract minted, by AMO
    int256 public fxs_mint_sum = 0; // Across all AMOs

    // Collateral borrowed balances
    mapping(address => int256) public collat_borrowed_balances; // Amount of collateral the contract borrowed, by AMO
    int256 public collat_borrowed_sum = 0; // Across all AMOs

    // FRAX balance related
    uint256 public fraxDollarBalanceStored = 0;

    // Collateral balance related
    uint256 public missing_decimals;
    uint256 public collatDollarBalanceStored = 0;

    // AMO balance corrections
    mapping(address => int256[2]) public correction_offsets_amos;
    // [amo_address][0] = AMO's frax_val_e18
    // [amo_address][1] = AMO's collat_val_e18

    /* ========== CONSTRUCTOR ========== */
    
    constructor (
        address _owner_address,
        address _custodian_address,
        address _timelock_address,
        address _collateral_address,
        address _pool_address
    ) Owned(_owner_address) {
        custodian_address = _custodian_address;
        timelock_address = _timelock_address;

        // Pool related
        pool = FraxPoolV3(_pool_address);

        // Collateral related
        collateral_address = _collateral_address;
        col_idx = pool.collateralAddrToIdx(_collateral_address);
        collateral_token = ERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
        missing_decimals = uint(18) - collateral_token.decimals();
    }

    /* ========== MODIFIERS ========== */

    modifier onlyByOwnGov() {
        require(msg.sender == timelock_address || msg.sender == owner, "Not owner or timelock");
        _;
    }

    modifier validAMO(address amo_address) {
        require(amos[amo_address], "Invalid AMO");
        _;
    }

    /* ========== VIEWS ========== */

    function collatDollarBalance() external view returns (uint256) {
        (, uint256 collat_val_e18) = dollarBalances();
        return collat_val_e18;
    }

    function dollarBalances() public view returns (uint256 frax_val_e18, uint256 collat_val_e18) {
        frax_val_e18 = fraxDollarBalanceStored;
        collat_val_e18 = collatDollarBalanceStored;
    }

    function allAMOAddresses() external view returns (address[] memory) {
        return amos_array;
    }

    function allAMOsLength() external view returns (uint256) {
        return amos_array.length;
    }

    function fraxTrackedGlobal() external view returns (int256) {
        return int256(fraxDollarBalanceStored) - frax_mint_sum - (collat_borrowed_sum * int256(10 ** missing_decimals));
    }

    function fraxTrackedAMO(address amo_address) external view returns (int256) {
        (uint256 frax_val_e18, ) = IAMO(amo_address).dollarBalances();
        int256 frax_val_e18_corrected = int256(frax_val_e18) + correction_offsets_amos[amo_address][0];
        return frax_val_e18_corrected - frax_mint_balances[amo_address] - ((collat_borrowed_balances[amo_address]) * int256(10 ** missing_decimals));
    }

    /* ========== PUBLIC FUNCTIONS ========== */

    // Callable by anyone willing to pay the gas
    function syncDollarBalances() public {
        uint256 total_frax_value_d18 = 0;
        uint256 total_collateral_value_d18 = 0; 
        for (uint i = 0; i < amos_array.length; i++){ 
            // Exclude null addresses
            address amo_address = amos_array[i];
            if (amo_address != address(0)){
                (uint256 frax_val_e18, uint256 collat_val_e18) = IAMO(amo_address).dollarBalances();
                total_frax_value_d18 += uint256(int256(frax_val_e18) + correction_offsets_amos[amo_address][0]);
                total_collateral_value_d18 += uint256(int256(collat_val_e18) + correction_offsets_amos[amo_address][1]);
            }
        }
        fraxDollarBalanceStored = total_frax_value_d18;
        collatDollarBalanceStored = total_collateral_value_d18;
    }

    /* ========== OLD POOL / BACKWARDS COMPATIBILITY ========== */

    function oldPoolRedeem(uint256 frax_amount) external onlyByOwnGov {
        uint256 redemption_fee = old_pool.redemption_fee();
        uint256 col_price_usd = old_pool.getCollateralPrice();
        uint256 global_collateral_ratio = FRAX.global_collateral_ratio();
        uint256 redeem_amount_E6 = ((frax_amount * (uint256(1e6) - redemption_fee)) / 1e6) / (10 ** missing_decimals);
        uint256 expected_collat_amount = (redeem_amount_E6 * global_collateral_ratio) / 1e6;
        expected_collat_amount = (expected_collat_amount * 1e6) / col_price_usd;

        require((collat_borrowed_sum + int256(expected_collat_amount)) <= collat_borrow_cap, "Borrow cap");
        collat_borrowed_sum += int256(expected_collat_amount);

        // Mint the frax 
        FRAX.pool_mint(address(this), frax_amount);

        // Redeem the frax
        FRAX.approve(address(old_pool), frax_amount);
        old_pool.redeemFractionalFRAX(frax_amount, 0, 0);
    }

    function oldPoolCollectAndGive(address destination_amo) external onlyByOwnGov validAMO(destination_amo) {
        // Get the amount to be collected
        uint256 collat_amount = old_pool.redeemCollateralBalances(address(this));
        
        // Collect the redemption
        old_pool.collectRedemption();

        // Mark the destination amo's borrowed amount
        collat_borrowed_balances[destination_amo] += int256(collat_amount);

        // Give the collateral to the AMO
        TransferHelper.safeTransfer(collateral_address, destination_amo, collat_amount);

        // Sync
        syncDollarBalances();
    }

    /* ========== OWNER / GOVERNANCE FUNCTIONS ONLY ========== */
    // Only owner or timelock can call, to limit risk 

    // ------------------------------------------------------------------
    // ------------------------------ FRAX ------------------------------
    // ------------------------------------------------------------------

    // This contract is essentially marked as a 'pool' so it can call OnlyPools functions like pool_mint and pool_burn_from
    // on the main FRAX contract
    function mintFraxForAMO(address destination_amo, uint256 frax_amount) external onlyByOwnGov validAMO(destination_amo) {
        int256 frax_amt_i256 = int256(frax_amount);

        // Make sure you aren't minting more than the mint cap
        require((frax_mint_sum + frax_amt_i256) <= frax_mint_cap, "Mint cap reached");
        frax_mint_balances[destination_amo] += frax_amt_i256;
        frax_mint_sum += frax_amt_i256;

        // Make sure the FRAX minting wouldn't push the CR down too much
        // This is also a sanity check for the int256 math
        uint256 current_collateral_E18 = FRAX.globalCollateralValue();
        uint256 cur_frax_supply = FRAX.totalSupply();
        uint256 new_frax_supply = cur_frax_supply + frax_amount;
        uint256 new_cr = (current_collateral_E18 * PRICE_PRECISION) / new_frax_supply;
        require(new_cr >= min_cr, "CR would be too low");

        // Mint the FRAX to the AMO
        FRAX.pool_mint(destination_amo, frax_amount);

        // Sync
        syncDollarBalances();
    }

    function burnFraxFromAMO(uint256 frax_amount) external validAMO(msg.sender) {
        int256 frax_amt_i256 = int256(frax_amount);

        // Burn first
        FRAX.pool_burn_from(msg.sender, frax_amount);

        // Then update the balances
        frax_mint_balances[msg.sender] -= frax_amt_i256;
        frax_mint_sum -= frax_amt_i256;

        // Sync
        syncDollarBalances();
    }

    // ------------------------------------------------------------------
    // ------------------------------- FXS ------------------------------
    // ------------------------------------------------------------------

    function mintFxsForAMO(address destination_amo, uint256 fxs_amount) external onlyByOwnGov validAMO(destination_amo) {
        int256 fxs_amt_i256 = int256(fxs_amount);

        // Make sure you aren't minting more than the mint cap
        require((fxs_mint_sum + fxs_amt_i256) <= fxs_mint_cap, "Mint cap reached");
        fxs_mint_balances[destination_amo] += fxs_amt_i256;
        fxs_mint_sum += fxs_amt_i256;

        // Mint the FXS to the AMO
        FXS.pool_mint(destination_amo, fxs_amount);

        // Sync
        syncDollarBalances();
    }

    function burnFxsFromAMO(uint256 fxs_amount) external validAMO(msg.sender) {
        int256 fxs_amt_i256 = int256(fxs_amount);

        // Burn first
        FXS.pool_burn_from(msg.sender, fxs_amount);

        // Then update the balances
        fxs_mint_balances[msg.sender] -= fxs_amt_i256;
        fxs_mint_sum -= fxs_amt_i256;

        // Sync
        syncDollarBalances();
    }

    // ------------------------------------------------------------------
    // --------------------------- Collateral ---------------------------
    // ------------------------------------------------------------------

    function giveCollatToAMO(
        address destination_amo,
        uint256 collat_amount
    ) external onlyByOwnGov validAMO(destination_amo) {
        int256 collat_amount_i256 = int256(collat_amount);

        require((collat_borrowed_sum + collat_amount_i256) <= collat_borrow_cap, "Borrow cap");
        collat_borrowed_balances[destination_amo] += collat_amount_i256;
        collat_borrowed_sum += collat_amount_i256;

        // Borrow the collateral
        pool.amoMinterBorrow(collat_amount);

        // Give the collateral to the AMO
        TransferHelper.safeTransfer(collateral_address, destination_amo, collat_amount);

        // Sync
        syncDollarBalances();
    }

    function receiveCollatFromAMO(uint256 usdc_amount) external validAMO(msg.sender) {
        int256 collat_amt_i256 = int256(usdc_amount);

        // Give back first
        TransferHelper.safeTransferFrom(collateral_address, msg.sender, address(pool), usdc_amount);

        // Then update the balances
        collat_borrowed_balances[msg.sender] -= collat_amt_i256;
        collat_borrowed_sum -= collat_amt_i256;

        // Sync
        syncDollarBalances();
    }

    /* ========== RESTRICTED GOVERNANCE FUNCTIONS ========== */

    // Adds an AMO 
    function addAMO(address amo_address, bool sync_too) public onlyByOwnGov {
        require(amo_address != address(0), "Zero address detected");

        (uint256 frax_val_e18, uint256 collat_val_e18) = IAMO(amo_address).dollarBalances();
        require(frax_val_e18 >= 0 && collat_val_e18 >= 0, "Invalid AMO");

        require(amos[amo_address] == false, "Address already exists");
        amos[amo_address] = true; 
        amos_array.push(amo_address);

        // Mint balances
        frax_mint_balances[amo_address] = 0;
        fxs_mint_balances[amo_address] = 0;
        collat_borrowed_balances[amo_address] = 0;

        // Offsets
        correction_offsets_amos[amo_address][0] = 0;
        correction_offsets_amos[amo_address][1] = 0;

        if (sync_too) syncDollarBalances();

        emit AMOAdded(amo_address);
    }

    // Removes an AMO
    function removeAMO(address amo_address, bool sync_too) public onlyByOwnGov {
        require(amo_address != address(0), "Zero address detected");
        require(amos[amo_address] == true, "Address nonexistant");
        
        // Delete from the mapping
        delete amos[amo_address];

        // 'Delete' from the array by setting the address to 0x0
        for (uint i = 0; i < amos_array.length; i++){ 
            if (amos_array[i] == amo_address) {
                amos_array[i] = address(0); // This will leave a null in the array and keep the indices the same
                break;
            }
        }

        if (sync_too) syncDollarBalances();

        emit AMORemoved(amo_address);
    }

    function setTimelock(address new_timelock) external onlyByOwnGov {
        require(new_timelock != address(0), "Timelock address cannot be 0");
        timelock_address = new_timelock;
    }

    function setCustodian(address _custodian_address) external onlyByOwnGov {
        require(_custodian_address != address(0), "Custodian address cannot be 0");        
        custodian_address = _custodian_address;
    }

    function setFraxMintCap(uint256 _frax_mint_cap) external onlyByOwnGov {
        frax_mint_cap = int256(_frax_mint_cap);
    }

    function setFxsMintCap(uint256 _fxs_mint_cap) external onlyByOwnGov {
        fxs_mint_cap = int256(_fxs_mint_cap);
    }

    function setCollatBorrowCap(uint256 _collat_borrow_cap) external onlyByOwnGov {
        collat_borrow_cap = int256(_collat_borrow_cap);
    }

    function setMinimumCollateralRatio(uint256 _min_cr) external onlyByOwnGov {
        min_cr = _min_cr;
    }

    function setAMOCorrectionOffsets(address amo_address, int256 frax_e18_correction, int256 collat_e18_correction) external onlyByOwnGov {
        correction_offsets_amos[amo_address][0] = frax_e18_correction;
        correction_offsets_amos[amo_address][1] = collat_e18_correction;

        syncDollarBalances();
    }

    function setFraxPool(address _pool_address) external onlyByOwnGov {
        pool = FraxPoolV3(_pool_address);

        // Make sure the collaterals match, or balances could get corrupted
        require(pool.collateralAddrToIdx(collateral_address) == col_idx, "col_idx mismatch");
    }

    function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyByOwnGov {
        // Can only be triggered by owner or governance
        TransferHelper.safeTransfer(tokenAddress, owner, tokenAmount);
        
        emit Recovered(tokenAddress, tokenAmount);
    }

    // Generic proxy
    function execute(
        address _to,
        uint256 _value,
        bytes calldata _data
    ) external onlyByOwnGov returns (bool, bytes memory) {
        (bool success, bytes memory result) = _to.call{value:_value}(_data);
        return (success, result);
    }

    /* ========== EVENTS ========== */

    event AMOAdded(address amo_address);
    event AMORemoved(address amo_address);
    event Recovered(address token, uint256 amount);
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_owner_address","type":"address"},{"internalType":"address","name":"_custodian_address","type":"address"},{"internalType":"address","name":"_timelock_address","type":"address"},{"internalType":"address","name":"_collateral_address","type":"address"},{"internalType":"address","name":"_pool_address","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"amo_address","type":"address"}],"name":"AMOAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"amo_address","type":"address"}],"name":"AMORemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"inputs":[],"name":"FRAX","outputs":[{"internalType":"contract IFrax","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FXS","outputs":[{"internalType":"contract IFxs","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"amo_address","type":"address"},{"internalType":"bool","name":"sync_too","type":"bool"}],"name":"addAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allAMOAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allAMOsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"amos","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"amos_array","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"frax_amount","type":"uint256"}],"name":"burnFraxFromAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fxs_amount","type":"uint256"}],"name":"burnFxsFromAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"col_idx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatDollarBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatDollarBalanceStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collat_borrow_cap","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collat_borrowed_balances","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collat_borrowed_sum","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateral_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateral_token","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"correction_offsets_amos","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"custodian_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dollarBalances","outputs":[{"internalType":"uint256","name":"frax_val_e18","type":"uint256"},{"internalType":"uint256","name":"collat_val_e18","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"execute","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fraxDollarBalanceStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"amo_address","type":"address"}],"name":"fraxTrackedAMO","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxTrackedGlobal","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"frax_mint_balances","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"frax_mint_cap","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"frax_mint_sum","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"fxs_mint_balances","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxs_mint_cap","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxs_mint_sum","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_amo","type":"address"},{"internalType":"uint256","name":"collat_amount","type":"uint256"}],"name":"giveCollatToAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"min_cr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_amo","type":"address"},{"internalType":"uint256","name":"frax_amount","type":"uint256"}],"name":"mintFraxForAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_amo","type":"address"},{"internalType":"uint256","name":"fxs_amount","type":"uint256"}],"name":"mintFxsForAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"missing_decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_amo","type":"address"}],"name":"oldPoolCollectAndGive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"frax_amount","type":"uint256"}],"name":"oldPoolRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"old_pool","outputs":[{"internalType":"contract IFraxPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract FraxPoolV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdc_amount","type":"uint256"}],"name":"receiveCollatFromAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"amo_address","type":"address"},{"internalType":"bool","name":"sync_too","type":"bool"}],"name":"removeAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"amo_address","type":"address"},{"internalType":"int256","name":"frax_e18_correction","type":"int256"},{"internalType":"int256","name":"collat_e18_correction","type":"int256"}],"name":"setAMOCorrectionOffsets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collat_borrow_cap","type":"uint256"}],"name":"setCollatBorrowCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_custodian_address","type":"address"}],"name":"setCustodian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_frax_mint_cap","type":"uint256"}],"name":"setFraxMintCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool_address","type":"address"}],"name":"setFraxPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fxs_mint_cap","type":"uint256"}],"name":"setFxsMintCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_min_cr","type":"uint256"}],"name":"setMinimumCollateralRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"new_timelock","type":"address"}],"name":"setTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"syncDollarBalances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timelock_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

6080604052600280546001600160a01b031990811673853d955acef822db058eb8505911ed77f175b99e17909155600380548216733432b6a60d23ca0dfca7761b7ab56459d9c964d0179055600580548216732fe065e6ffef9ac95ab39e5042744d695f56072917905560068054909116731864ca3d47aab98ee78d11fc9dcc5e7badda1c0d1790556509184e72a000600d556a52b7d2dcc80cd2e4000000600e819055600f55620c5c1060105560006012819055601481905560168190556017819055601955348015620000d357600080fd5b506040516200431638038062004316833981016040819052620000f6916200033f565b846001600160a01b038116620001525760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a150600880546001600160a01b038681166001600160a01b0319928316179092556007805486841690831617905560058054848416908316811790915560098054938616939092168317909155604051636d8f2e4f60e11b815260048101929092529063db1e5c9e9060240160206040518083038186803b1580156200022d57600080fd5b505afa15801562000242573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002689190620003af565b600a55600480546001600160a01b03191673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890811782556040805163313ce56760e01b81529051919263313ce567928282019260209290829003018186803b158015620002c857600080fd5b505afa158015620002dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003039190620003c9565b620003139060ff166012620003f5565b601855506200041b9350505050565b80516001600160a01b03811681146200033a57600080fd5b919050565b600080600080600060a086880312156200035857600080fd5b620003638662000322565b9450620003736020870162000322565b9350620003836040870162000322565b9250620003936060870162000322565b9150620003a36080870162000322565b90509295509295909350565b600060208284031215620003c257600080fd5b5051919050565b600060208284031215620003dc57600080fd5b815160ff81168114620003ee57600080fd5b9392505050565b6000828210156200041657634e487b7160e01b600052601160045260246000fd5b500390565b613eeb806200042b6000396000f3fe608060405234801561001057600080fd5b50600436106103785760003560e01c8063725adbdd116101d3578063b61d27f611610104578063dc6663c7116100a2578063e97d85a51161007c578063e97d85a5146107ee578063eaff6bba146107f7578063f5158e0014610800578063f87d29331461080857600080fd5b8063dc6663c7146107a6578063e05261ec146107c6578063e5d47fe0146107db57600080fd5b8063c6428b5f116100de578063c6428b5f1461076f578063cd71678e14610782578063d819eab51461078a578063d8ad1eed1461079357600080fd5b8063b61d27f614610708578063bda767ab14610729578063bdacb3031461075c57600080fd5b806390c3a206116101715780639d7576761161014b5780639d757676146106a7578063a4c3e73c146106ba578063ae38b182146106d5578063b0e4556f146106e857600080fd5b806390c3a2061461066e57806394582327146106815780639aa776ce1461069457600080fd5b80638980f11f116101ad5780638980f11f146106295780638b4433961461063c5780638da5cb5b1461064557806390074a511461066557600080fd5b8063725adbdd146105ee57806379ba5097146106015780637ce6112b1461060957600080fd5b80633a6e2f07116102ad578063526b1dfb1161024b5780636325890d116102255780636325890d146105ac5780636c052939146105b557806370bef0af146105c857806370c59475146105db57600080fd5b8063526b1dfb1461057057806353a47bb71461057957806360fdf1751461059957600080fd5b8063403f373111610287578063403f37311461052157806349696b20146105345780634ed67d9b14610547578063504ab9121461055057600080fd5b80633a6e2f07146104ef5780633ed4e55c1461050f5780633f10ecbe1461051857600080fd5b80631eaa0e171161031a5780632621db2f116102f45780632621db2f146104a057806326d9fc86146104c057806336082ac0146104d357806337ae1b82146104dc57600080fd5b80631eaa0e171461044d578063200ea2221461046d5780632245904c1461048d57600080fd5b806310b5ed651161035657806310b5ed65146103fd5780631627540c1461041057806316f0115b1461042557806317284c941461044557600080fd5b8063052ed9751461037d5780630cf2cb55146103c75780630edcfbe9146103f5575b600080fd5b60065461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6103e76103d53660046137e7565b60156020526000908152604090205481565b6040519081526020016103be565b6103e761081b565b6103e761040b36600461386c565b610858565b61042361041e3660046137e7565b61087d565b005b60055461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103e76109a2565b60095461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b60035461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61042361049b36600461386c565b6109b9565b60045461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6104236104ce36600461393a565b610e39565b6103e760105481565b6104236104ea36600461393a565b610f2b565b6103e76104fd3660046137e7565b60136020526000908152604090205481565b6103e760185481565b6103e760125481565b61042361052f3660046137e7565b610fd3565b61039d61054236600461393a565b61113a565b6103e7600f5481565b6103e761055e3660046137e7565b60116020526000908152604090205481565b6103e760165481565b60015461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6104236105a73660046137e7565b611171565b6103e760195481565b6104236105c3366004613802565b61134f565b6104236105d636600461386c565b61167c565b6104236105e936600461393a565b611919565b6104236105fc3660046137e7565b611a55565b610423611d17565b60085461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61042361063736600461386c565b611e62565b6103e7600a5481565b60005461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103e760175481565b61042361067c36600461386c565b611f76565b61042361068f366004613802565b61222a565b6104236106a236600461393a565b612592565b6104236106b536600461393a565b612afd565b601754601954604080519283526020830191909152016103be565b6103e76106e33660046137e7565b612ba5565b60025461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61071b610716366004613896565b612cdd565b6040516103be929190613a16565b61074c6107373660046137e7565b600c6020526000908152604090205460ff1681565b60405190151581526020016103be565b61042361076a3660046137e7565b612e03565b61042361077d36600461393a565b612f6a565b600b546103e7565b6103e7600e5481565b6104236107a136600461393a565b613012565b60075461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6107ce6130ba565b6040516103be91906139bc565b6104236107e936600461393a565b613129565b6103e7600d5481565b6103e760145481565b610423613265565b610423610816366004613839565b6133d7565b6000601854600a61082c9190613b98565b6016546108399190613c60565b6012546017546108499190613d59565b6108539190613d59565b905090565b601a602052816000526040600020816002811061087457600080fd5b01549150829050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b6000806109b26017546019549091565b9392505050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806109f6575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610a5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff16610aed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600e54601254839190610b01908390613a70565b1315610b69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d696e74206361702072656163686564000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff841660009081526011602052604081208054839290610b9e908490613a70565b925050819055508060126000828254610bb79190613a70565b9091555050600254604080517fd2d97b06000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163d2d97b06916004808301926020929190829003018186803b158015610c2757600080fd5b505afa158015610c3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5f9190613953565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ccb57600080fd5b505afa158015610cdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d039190613953565b90506000610d118683613ae4565b9050600081610d23620f424086613d1c565b610d2d9190613afc565b9050601054811015610d9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f435220776f756c6420626520746f6f206c6f77000000000000000000000000006044820152606401610920565b6002546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a81166004830152602482018a90529091169063b4f56b2690604401600060405180830381600087803b158015610e0f57600080fd5b505af1158015610e23573d6000803e3d6000fd5b50505050610e2f613265565b5050505050505050565b336000818152600c602052604090205460ff16610eb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6009546005548391610ee09173ffffffffffffffffffffffffffffffffffffffff91821691339116846134b0565b3360009081526015602052604081208054839290610eff908490613d59565b925050819055508060166000828254610f189190613d59565b90915550610f269050613265565b505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480610f68575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600d55565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611010575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff81166110f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437573746f6469616e20616464726573732063616e6e6f7420626520300000006044820152606401610920565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600b818154811061114a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60075473ffffffffffffffffffffffffffffffffffffffff163314806111ae575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600a546009546040517fdb1e5c9e000000000000000000000000000000000000000000000000000000008152931660048401529163db1e5c9e9060240160206040518083038186803b1580156112ad57600080fd5b505afa1580156112c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e59190613953565b1461134c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f636f6c5f696478206d69736d61746368000000000000000000000000000000006044820152606401610920565b50565b60075473ffffffffffffffffffffffffffffffffffffffff1633148061138c575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6113f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff821661146f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c602052604090205460ff161515600114611503576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f41646472657373206e6f6e6578697374616e74000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600b5481101561161f578273ffffffffffffffffffffffffffffffffffffffff16600b828154811061158357611583613e78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561160d576000600b82815481106115c0576115c0613e78565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061161f565b8061161781613e10565b91505061154f565b50801561162e5761162e613265565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fcfdb9256a3d90cc6d479617ca43d8c8d264a9f5fe7f480029c4d918862c46db4906020015b60405180910390a15050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806116b9575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61171f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff166117b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600f546014548391906117c4908390613a70565b131561182c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d696e74206361702072656163686564000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604081208054839290611861908490613a70565b92505081905550806014600082825461187a9190613a70565b90915550506003546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690529091169063b4f56b2690604401600060405180830381600087803b1580156118f357600080fd5b505af1158015611907573d6000803e3d6000fd5b50505050611913613265565b50505050565b336000818152600c602052604090205460ff16611992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6002546040517fa8a778ae00000000000000000000000000000000000000000000000000000000815233600482015260248101849052839173ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b158015611a0457600080fd5b505af1158015611a18573d6000803e3d6000fd5b50503360009081526011602052604081208054859450909250611a3c908490613d59565b925050819055508060126000828254610f189190613d59565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611a92575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611af8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600c6020526040902054819060ff16611b89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6006546040517f08a7493d00000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906308a7493d90602401602060405180830381600087803b158015611bf557600080fd5b505af1158015611c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2d9190613953565b9050600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312ace5a26040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c9957600080fd5b505af1158015611cad573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff831660009081526015602052604081208054839290611ce6908490613a70565b9091555050600954611d0f9073ffffffffffffffffffffffffffffffffffffffff16848361364e565b610f26613265565b60015473ffffffffffffffffffffffffffffffffffffffff163314611dbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610920565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611e9f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611f05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600054611f2a90839073ffffffffffffffffffffffffffffffffffffffff168361364e565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa289101611670565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611fb3575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612019576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff166120aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600d546016548391906120be908390613a70565b1315612126576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f426f72726f7720636170000000000000000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601560205260408120805483929061215b908490613a70565b9250508190555080601660008282546121749190613a70565b90915550506005546040517f9aae55a70000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff90911690639aae55a790602401600060405180830381600087803b1580156121e557600080fd5b505af11580156121f9573d6000803e3d6000fd5b5050600954612222925073ffffffffffffffffffffffffffffffffffffffff169050858561364e565b611913613265565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612267575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6122cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff821661234a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610920565b6000808373ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b15801561239257600080fd5b505afa1580156123a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ca919061396c565b909250905073ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604090205460ff161561245f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4164647265737320616c726561647920657869737473000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155600b80548083019091557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180547fffffffffffffffffffffffff000000000000000000000000000000000000000016909517909455601182528083208390556013825280832083905560158252808320839055601a909152812081815590910155821561254357612543613265565b60405173ffffffffffffffffffffffffffffffffffffffff851681527faa5bd6bda335b0c74f281b4b10d444ed06cd74963d7d77daa9a274eb4a7b36399060200160405180910390a150505050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806125cf575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612635576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600654604080517fcb73999f000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cb73999f91600480830192602092919082900301818787803b1580156126a157600080fd5b505af11580156126b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d99190613953565b90506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f7683bbc6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561274757600080fd5b505af115801561275b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277f9190613953565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127eb57600080fd5b505afa1580156127ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128239190613953565b90506000601854600a6128369190613b98565b620f42406128448682613dcd565b61284e9088613d1c565b6128589190613afc565b6128629190613afc565b90506000620f42406128748484613d1c565b61287e9190613afc565b90508361288e82620f4240613d1c565b6128989190613afc565b9050600d54816016546128ab9190613a70565b1315612913576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f426f72726f7720636170000000000000000000000000000000000000000000006044820152606401610920565b80601660008282546129259190613a70565b90915550506002546040517fb4f56b260000000000000000000000000000000000000000000000000000000081523060048201526024810188905273ffffffffffffffffffffffffffffffffffffffff9091169063b4f56b2690604401600060405180830381600087803b15801561299c57600080fd5b505af11580156129b0573d6000803e3d6000fd5b50506002546006546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018b90529116925063095ea7b39150604401602060405180830381600087803b158015612a2a57600080fd5b505af1158015612a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a62919061391d565b506006546040517f7e108af900000000000000000000000000000000000000000000000000000000815260048101889052600060248201819052604482015273ffffffffffffffffffffffffffffffffffffffff90911690637e108af990606401600060405180830381600087803b158015612add57600080fd5b505af1158015612af1573d6000803e3d6000fd5b50505050505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612b3a575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612ba0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600f55565b6000808273ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b158015612bed57600080fd5b505afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c25919061396c565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601a602052604081205491925090612c5a9083613a70565b9050601854600a612c6b9190613b98565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260156020526040902054612c9b9190613c60565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260116020526040902054612ccb9083613d59565b612cd59190613d59565b949350505050565b60075460009060609073ffffffffffffffffffffffffffffffffffffffff16331480612d20575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612d86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b6000808773ffffffffffffffffffffffffffffffffffffffff16878787604051612db1929190613990565b60006040518083038185875af1925050503d8060008114612dee576040519150601f19603f3d011682016040523d82523d6000602084013e612df3565b606091505b5090999098509650505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612e40575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff8116612f23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f54696d656c6f636b20616464726573732063616e6e6f742062652030000000006044820152606401610920565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612fa7575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61300d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600e55565b60075473ffffffffffffffffffffffffffffffffffffffff1633148061304f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6130b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b601055565b6060600b80548060200260200160405190810160405280929190818152602001828054801561311f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116130f4575b5050505050905090565b336000818152600c602052604090205460ff166131a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6003546040517fa8a778ae00000000000000000000000000000000000000000000000000000000815233600482015260248101849052839173ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b15801561321457600080fd5b505af1158015613228573d6000803e3d6000fd5b5050336000908152601360205260408120805485945090925061324c908490613d59565b925050819055508060146000828254610f189190613d59565b60008060005b600b548110156133cb576000600b828154811061328a5761328a613e78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156133b8576000808273ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b1580156132fc57600080fd5b505afa158015613310573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613334919061396c565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601a602052604090205491935091506133699083613a70565b6133739087613ae4565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601a60205260409020909650600101546133a99082613a70565b6133b39086613ae4565b945050505b50806133c381613e10565b91505061326b565b50601791909155601955565b60075473ffffffffffffffffffffffffffffffffffffffff16331480613414575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61347a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601a60205260409020828155600101819055610f26613265565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161354f91906139a0565b6000604051808303816000865af19150503d806000811461358c576040519150601f19603f3d011682016040523d82523d6000602084013e613591565b606091505b50915091508180156135bb5750805115806135bb5750808060200190518101906135bb919061391d565b613646576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610920565b505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916136e591906139a0565b6000604051808303816000865af19150503d8060008114613722576040519150601f19603f3d011682016040523d82523d6000602084013e613727565b606091505b5091509150818015613751575080511580613751575080806020019051810190613751919061391d565b6137b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610920565b5050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146137e257600080fd5b919050565b6000602082840312156137f957600080fd5b6109b2826137be565b6000806040838503121561381557600080fd5b61381e836137be565b9150602083013561382e81613ea7565b809150509250929050565b60008060006060848603121561384e57600080fd5b613857846137be565b95602085013595506040909401359392505050565b6000806040838503121561387f57600080fd5b613888836137be565b946020939093013593505050565b600080600080606085870312156138ac57600080fd5b6138b5856137be565b935060208501359250604085013567ffffffffffffffff808211156138d957600080fd5b818701915087601f8301126138ed57600080fd5b8135818111156138fc57600080fd5b88602082850101111561390e57600080fd5b95989497505060200194505050565b60006020828403121561392f57600080fd5b81516109b281613ea7565b60006020828403121561394c57600080fd5b5035919050565b60006020828403121561396557600080fd5b5051919050565b6000806040838503121561397f57600080fd5b505080516020909101519092909150565b8183823760009101908152919050565b600082516139b2818460208701613de4565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015613a0a57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016139d8565b50909695505050505050565b82151581526040602082015260008251806040840152613a3d816060850160208701613de4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615613aaa57613aaa613e49565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615613ade57613ade613e49565b50500190565b60008219821115613af757613af7613e49565b500190565b600082613b32577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600181815b80851115613b9057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613b7657613b76613e49565b80851615613b8357918102915b93841c9390800290613b3c565b509250929050565b60006109b28383600082613bae57506001613c5a565b81613bbb57506000613c5a565b8160018114613bd15760028114613bdb57613bf7565b6001915050613c5a565b60ff841115613bec57613bec613e49565b50506001821b613c5a565b5060208310610133831016604e8410600b8410161715613c1a575081810a613c5a565b613c248383613b37565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613c5657613c56613e49565b0290505b92915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613ca157613ca1613e49565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615613cdc57613cdc613e49565b60008712925087820587128484161615613cf857613cf8613e49565b87850587128184161615613d0e57613d0e613e49565b505050929093029392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613d5457613d54613e49565b500290565b6000808312837f800000000000000000000000000000000000000000000000000000000000000001831281151615613d9357613d93613e49565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615613dc757613dc7613e49565b50500390565b600082821015613ddf57613ddf613e49565b500390565b60005b83811015613dff578181015183820152602001613de7565b838111156119135750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613e4257613e42613e49565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b801515811461134c57600080fdfea2646970667358221220d7505757b29efdbf7dd8a05f225e43d07f180164296d60d6c8815eede21ee64464736f6c63430008060033000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd20000000000000000000000005180db0237291a6449dda9ed33ad90a38787621c0000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000002fe065e6ffef9ac95ab39e5042744d695f560729

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103785760003560e01c8063725adbdd116101d3578063b61d27f611610104578063dc6663c7116100a2578063e97d85a51161007c578063e97d85a5146107ee578063eaff6bba146107f7578063f5158e0014610800578063f87d29331461080857600080fd5b8063dc6663c7146107a6578063e05261ec146107c6578063e5d47fe0146107db57600080fd5b8063c6428b5f116100de578063c6428b5f1461076f578063cd71678e14610782578063d819eab51461078a578063d8ad1eed1461079357600080fd5b8063b61d27f614610708578063bda767ab14610729578063bdacb3031461075c57600080fd5b806390c3a206116101715780639d7576761161014b5780639d757676146106a7578063a4c3e73c146106ba578063ae38b182146106d5578063b0e4556f146106e857600080fd5b806390c3a2061461066e57806394582327146106815780639aa776ce1461069457600080fd5b80638980f11f116101ad5780638980f11f146106295780638b4433961461063c5780638da5cb5b1461064557806390074a511461066557600080fd5b8063725adbdd146105ee57806379ba5097146106015780637ce6112b1461060957600080fd5b80633a6e2f07116102ad578063526b1dfb1161024b5780636325890d116102255780636325890d146105ac5780636c052939146105b557806370bef0af146105c857806370c59475146105db57600080fd5b8063526b1dfb1461057057806353a47bb71461057957806360fdf1751461059957600080fd5b8063403f373111610287578063403f37311461052157806349696b20146105345780634ed67d9b14610547578063504ab9121461055057600080fd5b80633a6e2f07146104ef5780633ed4e55c1461050f5780633f10ecbe1461051857600080fd5b80631eaa0e171161031a5780632621db2f116102f45780632621db2f146104a057806326d9fc86146104c057806336082ac0146104d357806337ae1b82146104dc57600080fd5b80631eaa0e171461044d578063200ea2221461046d5780632245904c1461048d57600080fd5b806310b5ed651161035657806310b5ed65146103fd5780631627540c1461041057806316f0115b1461042557806317284c941461044557600080fd5b8063052ed9751461037d5780630cf2cb55146103c75780630edcfbe9146103f5575b600080fd5b60065461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6103e76103d53660046137e7565b60156020526000908152604090205481565b6040519081526020016103be565b6103e761081b565b6103e761040b36600461386c565b610858565b61042361041e3660046137e7565b61087d565b005b60055461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103e76109a2565b60095461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b60035461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61042361049b36600461386c565b6109b9565b60045461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6104236104ce36600461393a565b610e39565b6103e760105481565b6104236104ea36600461393a565b610f2b565b6103e76104fd3660046137e7565b60136020526000908152604090205481565b6103e760185481565b6103e760125481565b61042361052f3660046137e7565b610fd3565b61039d61054236600461393a565b61113a565b6103e7600f5481565b6103e761055e3660046137e7565b60116020526000908152604090205481565b6103e760165481565b60015461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6104236105a73660046137e7565b611171565b6103e760195481565b6104236105c3366004613802565b61134f565b6104236105d636600461386c565b61167c565b6104236105e936600461393a565b611919565b6104236105fc3660046137e7565b611a55565b610423611d17565b60085461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61042361063736600461386c565b611e62565b6103e7600a5481565b60005461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103e760175481565b61042361067c36600461386c565b611f76565b61042361068f366004613802565b61222a565b6104236106a236600461393a565b612592565b6104236106b536600461393a565b612afd565b601754601954604080519283526020830191909152016103be565b6103e76106e33660046137e7565b612ba5565b60025461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61071b610716366004613896565b612cdd565b6040516103be929190613a16565b61074c6107373660046137e7565b600c6020526000908152604090205460ff1681565b60405190151581526020016103be565b61042361076a3660046137e7565b612e03565b61042361077d36600461393a565b612f6a565b600b546103e7565b6103e7600e5481565b6104236107a136600461393a565b613012565b60075461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6107ce6130ba565b6040516103be91906139bc565b6104236107e936600461393a565b613129565b6103e7600d5481565b6103e760145481565b610423613265565b610423610816366004613839565b6133d7565b6000601854600a61082c9190613b98565b6016546108399190613c60565b6012546017546108499190613d59565b6108539190613d59565b905090565b601a602052816000526040600020816002811061087457600080fd5b01549150829050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b6000806109b26017546019549091565b9392505050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806109f6575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610a5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff16610aed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600e54601254839190610b01908390613a70565b1315610b69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d696e74206361702072656163686564000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff841660009081526011602052604081208054839290610b9e908490613a70565b925050819055508060126000828254610bb79190613a70565b9091555050600254604080517fd2d97b06000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163d2d97b06916004808301926020929190829003018186803b158015610c2757600080fd5b505afa158015610c3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5f9190613953565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ccb57600080fd5b505afa158015610cdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d039190613953565b90506000610d118683613ae4565b9050600081610d23620f424086613d1c565b610d2d9190613afc565b9050601054811015610d9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f435220776f756c6420626520746f6f206c6f77000000000000000000000000006044820152606401610920565b6002546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a81166004830152602482018a90529091169063b4f56b2690604401600060405180830381600087803b158015610e0f57600080fd5b505af1158015610e23573d6000803e3d6000fd5b50505050610e2f613265565b5050505050505050565b336000818152600c602052604090205460ff16610eb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6009546005548391610ee09173ffffffffffffffffffffffffffffffffffffffff91821691339116846134b0565b3360009081526015602052604081208054839290610eff908490613d59565b925050819055508060166000828254610f189190613d59565b90915550610f269050613265565b505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480610f68575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600d55565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611010575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff81166110f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437573746f6469616e20616464726573732063616e6e6f7420626520300000006044820152606401610920565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600b818154811061114a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60075473ffffffffffffffffffffffffffffffffffffffff163314806111ae575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600a546009546040517fdb1e5c9e000000000000000000000000000000000000000000000000000000008152931660048401529163db1e5c9e9060240160206040518083038186803b1580156112ad57600080fd5b505afa1580156112c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e59190613953565b1461134c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f636f6c5f696478206d69736d61746368000000000000000000000000000000006044820152606401610920565b50565b60075473ffffffffffffffffffffffffffffffffffffffff1633148061138c575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6113f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff821661146f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c602052604090205460ff161515600114611503576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f41646472657373206e6f6e6578697374616e74000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600b5481101561161f578273ffffffffffffffffffffffffffffffffffffffff16600b828154811061158357611583613e78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561160d576000600b82815481106115c0576115c0613e78565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061161f565b8061161781613e10565b91505061154f565b50801561162e5761162e613265565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fcfdb9256a3d90cc6d479617ca43d8c8d264a9f5fe7f480029c4d918862c46db4906020015b60405180910390a15050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806116b9575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61171f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff166117b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600f546014548391906117c4908390613a70565b131561182c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d696e74206361702072656163686564000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604081208054839290611861908490613a70565b92505081905550806014600082825461187a9190613a70565b90915550506003546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690529091169063b4f56b2690604401600060405180830381600087803b1580156118f357600080fd5b505af1158015611907573d6000803e3d6000fd5b50505050611913613265565b50505050565b336000818152600c602052604090205460ff16611992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6002546040517fa8a778ae00000000000000000000000000000000000000000000000000000000815233600482015260248101849052839173ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b158015611a0457600080fd5b505af1158015611a18573d6000803e3d6000fd5b50503360009081526011602052604081208054859450909250611a3c908490613d59565b925050819055508060126000828254610f189190613d59565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611a92575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611af8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600c6020526040902054819060ff16611b89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6006546040517f08a7493d00000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906308a7493d90602401602060405180830381600087803b158015611bf557600080fd5b505af1158015611c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2d9190613953565b9050600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312ace5a26040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c9957600080fd5b505af1158015611cad573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff831660009081526015602052604081208054839290611ce6908490613a70565b9091555050600954611d0f9073ffffffffffffffffffffffffffffffffffffffff16848361364e565b610f26613265565b60015473ffffffffffffffffffffffffffffffffffffffff163314611dbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610920565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611e9f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611f05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600054611f2a90839073ffffffffffffffffffffffffffffffffffffffff168361364e565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa289101611670565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611fb3575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612019576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff166120aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600d546016548391906120be908390613a70565b1315612126576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f426f72726f7720636170000000000000000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601560205260408120805483929061215b908490613a70565b9250508190555080601660008282546121749190613a70565b90915550506005546040517f9aae55a70000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff90911690639aae55a790602401600060405180830381600087803b1580156121e557600080fd5b505af11580156121f9573d6000803e3d6000fd5b5050600954612222925073ffffffffffffffffffffffffffffffffffffffff169050858561364e565b611913613265565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612267575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6122cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff821661234a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610920565b6000808373ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b15801561239257600080fd5b505afa1580156123a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ca919061396c565b909250905073ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604090205460ff161561245f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4164647265737320616c726561647920657869737473000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155600b80548083019091557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180547fffffffffffffffffffffffff000000000000000000000000000000000000000016909517909455601182528083208390556013825280832083905560158252808320839055601a909152812081815590910155821561254357612543613265565b60405173ffffffffffffffffffffffffffffffffffffffff851681527faa5bd6bda335b0c74f281b4b10d444ed06cd74963d7d77daa9a274eb4a7b36399060200160405180910390a150505050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806125cf575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612635576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600654604080517fcb73999f000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cb73999f91600480830192602092919082900301818787803b1580156126a157600080fd5b505af11580156126b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d99190613953565b90506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f7683bbc6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561274757600080fd5b505af115801561275b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277f9190613953565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127eb57600080fd5b505afa1580156127ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128239190613953565b90506000601854600a6128369190613b98565b620f42406128448682613dcd565b61284e9088613d1c565b6128589190613afc565b6128629190613afc565b90506000620f42406128748484613d1c565b61287e9190613afc565b90508361288e82620f4240613d1c565b6128989190613afc565b9050600d54816016546128ab9190613a70565b1315612913576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f426f72726f7720636170000000000000000000000000000000000000000000006044820152606401610920565b80601660008282546129259190613a70565b90915550506002546040517fb4f56b260000000000000000000000000000000000000000000000000000000081523060048201526024810188905273ffffffffffffffffffffffffffffffffffffffff9091169063b4f56b2690604401600060405180830381600087803b15801561299c57600080fd5b505af11580156129b0573d6000803e3d6000fd5b50506002546006546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018b90529116925063095ea7b39150604401602060405180830381600087803b158015612a2a57600080fd5b505af1158015612a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a62919061391d565b506006546040517f7e108af900000000000000000000000000000000000000000000000000000000815260048101889052600060248201819052604482015273ffffffffffffffffffffffffffffffffffffffff90911690637e108af990606401600060405180830381600087803b158015612add57600080fd5b505af1158015612af1573d6000803e3d6000fd5b50505050505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612b3a575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612ba0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600f55565b6000808273ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b158015612bed57600080fd5b505afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c25919061396c565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601a602052604081205491925090612c5a9083613a70565b9050601854600a612c6b9190613b98565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260156020526040902054612c9b9190613c60565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260116020526040902054612ccb9083613d59565b612cd59190613d59565b949350505050565b60075460009060609073ffffffffffffffffffffffffffffffffffffffff16331480612d20575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612d86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b6000808773ffffffffffffffffffffffffffffffffffffffff16878787604051612db1929190613990565b60006040518083038185875af1925050503d8060008114612dee576040519150601f19603f3d011682016040523d82523d6000602084013e612df3565b606091505b5090999098509650505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612e40575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff8116612f23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f54696d656c6f636b20616464726573732063616e6e6f742062652030000000006044820152606401610920565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612fa7575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61300d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600e55565b60075473ffffffffffffffffffffffffffffffffffffffff1633148061304f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6130b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b601055565b6060600b80548060200260200160405190810160405280929190818152602001828054801561311f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116130f4575b5050505050905090565b336000818152600c602052604090205460ff166131a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6003546040517fa8a778ae00000000000000000000000000000000000000000000000000000000815233600482015260248101849052839173ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b15801561321457600080fd5b505af1158015613228573d6000803e3d6000fd5b5050336000908152601360205260408120805485945090925061324c908490613d59565b925050819055508060146000828254610f189190613d59565b60008060005b600b548110156133cb576000600b828154811061328a5761328a613e78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156133b8576000808273ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b1580156132fc57600080fd5b505afa158015613310573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613334919061396c565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601a602052604090205491935091506133699083613a70565b6133739087613ae4565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601a60205260409020909650600101546133a99082613a70565b6133b39086613ae4565b945050505b50806133c381613e10565b91505061326b565b50601791909155601955565b60075473ffffffffffffffffffffffffffffffffffffffff16331480613414575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61347a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601a60205260409020828155600101819055610f26613265565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161354f91906139a0565b6000604051808303816000865af19150503d806000811461358c576040519150601f19603f3d011682016040523d82523d6000602084013e613591565b606091505b50915091508180156135bb5750805115806135bb5750808060200190518101906135bb919061391d565b613646576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610920565b505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916136e591906139a0565b6000604051808303816000865af19150503d8060008114613722576040519150601f19603f3d011682016040523d82523d6000602084013e613727565b606091505b5091509150818015613751575080511580613751575080806020019051810190613751919061391d565b6137b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610920565b5050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146137e257600080fd5b919050565b6000602082840312156137f957600080fd5b6109b2826137be565b6000806040838503121561381557600080fd5b61381e836137be565b9150602083013561382e81613ea7565b809150509250929050565b60008060006060848603121561384e57600080fd5b613857846137be565b95602085013595506040909401359392505050565b6000806040838503121561387f57600080fd5b613888836137be565b946020939093013593505050565b600080600080606085870312156138ac57600080fd5b6138b5856137be565b935060208501359250604085013567ffffffffffffffff808211156138d957600080fd5b818701915087601f8301126138ed57600080fd5b8135818111156138fc57600080fd5b88602082850101111561390e57600080fd5b95989497505060200194505050565b60006020828403121561392f57600080fd5b81516109b281613ea7565b60006020828403121561394c57600080fd5b5035919050565b60006020828403121561396557600080fd5b5051919050565b6000806040838503121561397f57600080fd5b505080516020909101519092909150565b8183823760009101908152919050565b600082516139b2818460208701613de4565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015613a0a57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016139d8565b50909695505050505050565b82151581526040602082015260008251806040840152613a3d816060850160208701613de4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615613aaa57613aaa613e49565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615613ade57613ade613e49565b50500190565b60008219821115613af757613af7613e49565b500190565b600082613b32577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600181815b80851115613b9057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613b7657613b76613e49565b80851615613b8357918102915b93841c9390800290613b3c565b509250929050565b60006109b28383600082613bae57506001613c5a565b81613bbb57506000613c5a565b8160018114613bd15760028114613bdb57613bf7565b6001915050613c5a565b60ff841115613bec57613bec613e49565b50506001821b613c5a565b5060208310610133831016604e8410600b8410161715613c1a575081810a613c5a565b613c248383613b37565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613c5657613c56613e49565b0290505b92915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613ca157613ca1613e49565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615613cdc57613cdc613e49565b60008712925087820587128484161615613cf857613cf8613e49565b87850587128184161615613d0e57613d0e613e49565b505050929093029392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613d5457613d54613e49565b500290565b6000808312837f800000000000000000000000000000000000000000000000000000000000000001831281151615613d9357613d93613e49565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615613dc757613dc7613e49565b50500390565b600082821015613ddf57613ddf613e49565b500390565b60005b83811015613dff578181015183820152602001613de7565b838111156119135750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613e4257613e42613e49565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b801515811461134c57600080fdfea2646970667358221220d7505757b29efdbf7dd8a05f225e43d07f180164296d60d6c8815eede21ee64464736f6c63430008060033

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

000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd20000000000000000000000005180db0237291a6449dda9ed33ad90a38787621c0000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000002fe065e6ffef9ac95ab39e5042744d695f560729

-----Decoded View---------------
Arg [0] : _owner_address (address): 0x234D953a9404Bf9DbC3b526271d440cD2870bCd2
Arg [1] : _custodian_address (address): 0x5180db0237291A6449DdA9ed33aD90a38787621c
Arg [2] : _timelock_address (address): 0x8412ebf45bAC1B340BbE8F318b928C466c4E39CA
Arg [3] : _collateral_address (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [4] : _pool_address (address): 0x2fE065e6FFEf9ac95ab39E5042744d695F560729

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd2
Arg [1] : 0000000000000000000000005180db0237291a6449dda9ed33ad90a38787621c
Arg [2] : 0000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca
Arg [3] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [4] : 0000000000000000000000002fe065e6ffef9ac95ab39e5042744d695f560729


Deployed Bytecode Sourcemap

77664:15983:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78101:81;;;;;;;;;;;;3653:42:1;3641:55;;;3623:74;;3611:2;3596:18;78101:81:0;;;;;;;;79418:58;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;7524:25:1;;;7512:2;7497:18;79418:58:0;7479:76:1;81704:190:0;;;:::i;79840:60::-;;;;;;:::i;:::-;;:::i;15005:141::-;;;;;;:::i;:::-;;:::i;:::-;;78015:79;;;;;;;;;81106:159;;;:::i;78295:33::-;;;;;;;;;77906:66;;;;;;;;;85455:1057;;;;;;:::i;:::-;;:::i;77979:29::-;;;;;;;;;89079:480;;;;;;:::i;:::-;;:::i;78964:30::-;;;;;;91975:143;;;;;;:::i;:::-;;:::i;79220:51::-;;;;;;:::i;:::-;;;;;;;;;;;;;;79717:31;;;;;;79135;;;;;;91479:222;;;;;;:::i;:::-;;:::i;78388:27::-;;;;;;:::i;:::-;;:::i;78845:49::-;;;;;;79030:52;;;;;;:::i;:::-;;;;;;;;;;;;;;79537:37;;;;;;14773:29;;;;;;;;;92572:291;;;;;;:::i;:::-;;:::i;79755:44::-;;;;;;90543:727;;;;;;:::i;:::-;;:::i;87160:567::-;;;;;;:::i;:::-;;:::i;86520:405::-;;;;;;:::i;:::-;;:::i;84295:641::-;;;;;;:::i;:::-;;:::i;15154:271::-;;;:::i;78227:32::-;;;;;;;;;92871:286;;;;;;:::i;:::-;;:::i;78335:22::-;;;;;;14746:20;;;;;;;;;79631:42;;;;;;88365:706;;;;;;:::i;:::-;;:::i;89655:857::-;;;;;;:::i;:::-;;:::i;83316:971::-;;;;;;:::i;:::-;;:::i;91844:123::-;;;;;;:::i;:::-;;:::i;81273:203::-;81392:23;;81443:25;;81273:203;;;13690:25:1;;;13746:2;13731:18;;13724:34;;;;13663:18;81273:203:0;13645:119:1;81902:412:0;;;;;;:::i;:::-;;:::i;77830:69::-;;;;;;;;;93187:274;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;78422:36::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;5596:14:1;;5589:22;5571:41;;5559:2;5544:18;78422:36:0;5526:92:1;91278:193:0;;;;;;:::i;:::-;;:::i;91709:127::-;;;;;;:::i;:::-;;:::i;81596:100::-;81671:10;:17;81596:100;;78788:50;;;;;;92126:109;;;;;;:::i;:::-;;:::i;78189:31::-;;;;;;;;;81484:104;;;:::i;:::-;;;;;;;:::i;87735:395::-;;;;;;:::i;:::-;;:::i;78669:52::-;;;;;;79323:30;;;;;;82424:814;;;:::i;92243:321::-;;;;;;:::i;:::-;;:::i;81704:190::-;81756:6;81868:16;;81862:2;:22;;;;:::i;:::-;81833:19;;:52;;;;:::i;:::-;81816:13;;81789:23;;81782:47;;;;:::i;:::-;:104;;;;:::i;:::-;81775:111;;81704:190;:::o;79840:60::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;79840:60:0;;-1:-1:-1;79840:60:0:o;15005:141::-;15485:5;;;;15471:10;:19;15463:79;;;;;;;9941:2:1;15463:79:0;;;9923:21:1;9980:2;9960:18;;;9953:30;10019:34;9999:18;;;9992:62;10090:17;10070:18;;;10063:45;10125:19;;15463:79:0;;;;;;;;;15077:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;15116:22:::1;::::0;3623:74:1;;;15116:22:0::1;::::0;3611:2:1;3596:18;15116:22:0::1;;;;;;;15005:141:::0;:::o;81106:159::-;81160:7;81183:22;81209:16;81392:23;;81443:25;;81392:23;;81273:203;81209:16;81180:45;81106:159;-1:-1:-1;;;81106:159:0:o;85455:1057::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;81004:17:::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;85556:15;;81004:17:::1;;80996:41;;;::::0;::::1;::::0;;10357:2:1;80996:41:0::1;::::0;::::1;10339:21:1::0;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0::1;10329:161:1::0;80996:41:0::1;85746:13:::2;::::0;85712::::2;::::0;85614:11;;85746:13;85712:29:::2;::::0;85614:11;;85712:29:::2;:::i;:::-;85711:48;;85703:77;;;::::0;::::2;::::0;;11741:2:1;85703:77:0::2;::::0;::::2;11723:21:1::0;11780:2;11760:18;;;11753:30;11819:18;11799;;;11792:46;11855:18;;85703:77:0::2;11713:166:1::0;85703:77:0::2;85791:35;::::0;::::2;;::::0;;;:18:::2;:35;::::0;;;;:52;;85830:13;;85791:35;:52:::2;::::0;85830:13;;85791:52:::2;:::i;:::-;;;;;;;;85871:13;85854;;:30;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;86064:4:0::2;::::0;:28:::2;::::0;;;;;;;86031:30:::2;::::0;86064:4:::2;;::::0;:26:::2;::::0;:28:::2;::::0;;::::2;::::0;::::2;::::0;;;;;;;;:4;:28;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;86031:61;;86103:23;86129:4;;;;;;;;;;;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;86103:44:::0;-1:-1:-1;86158:23:0::2;86184:29;86202:11:::0;86103:44;86184:29:::2;:::i;:::-;86158:55:::0;-1:-1:-1;86224:14:0::2;86158:55:::0;86242:40:::2;78582:3;86242:22:::0;:40:::2;:::i;:::-;86241:60;;;;:::i;:::-;86224:77;;86330:6;;86320;:16;;86312:48;;;::::0;::::2;::::0;;12848:2:1;86312:48:0::2;::::0;::::2;12830:21:1::0;12887:2;12867:18;;;12860:30;12926:21;12906:18;;;12899:49;12965:18;;86312:48:0::2;12820:169:1::0;86312:48:0::2;86410:4;::::0;:44:::2;::::0;;;;:4:::2;4635:55:1::0;;;86410:44:0::2;::::0;::::2;4617:74:1::0;4707:18;;;4700:34;;;86410:4:0;;::::2;::::0;:14:::2;::::0;4590:18:1;;86410:44:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;86484:20;:18;:20::i;:::-;85573:939;;;;;80929:1:::1;85455:1057:::0;;:::o;89079:480::-;89148:10;81004:17;;;;:4;:17;;;;;;;;80996:41;;;;;;;10357:2:1;80996:41:0;;;10339:21:1;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0;10329:161:1;80996:41:0;89288:18:::1;::::0;89328:4:::1;::::0;89203:11;;89256:91:::1;::::0;89288:18:::1;::::0;;::::1;::::0;89308:10:::1;::::0;89328:4:::1;89203:11:::0;89256:31:::1;:91::i;:::-;89422:10;89397:36;::::0;;;:24:::1;:36;::::0;;;;:55;;89437:15;;89397:36;:55:::1;::::0;89437:15;;89397:55:::1;:::i;:::-;;;;;;;;89486:15;89463:19;;:38;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;89531:20:0::1;::::0;-1:-1:-1;89531:18:0::1;:20::i;:::-;89160:399;89079:480:::0;;:::o;91975:143::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;92064:17:::1;:46:::0;91975:143::o;91479:222::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;91570:32:::1;::::0;::::1;91562:74;;;::::0;::::1;::::0;;9244:2:1;91562:74:0::1;::::0;::::1;9226:21:1::0;9283:2;9263:18;;;9256:30;9322:31;9302:18;;;9295:59;9371:18;;91562:74:0::1;9216:179:1::0;91562:74:0::1;91655:17;:38:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;91479:222::o;78388:27::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78388:27:0;:::o;92572:291::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;92649:4:::1;:32:::0;;;::::1;;::::0;;::::1;::::0;;::::1;::::0;;;92827:7:::1;::::0;92804:18:::1;::::0;92779:44:::1;::::0;;;;92804:18;::::1;92779:44;::::0;::::1;3623:74:1::0;92827:7:0;92779:24:::1;::::0;3596:18:1;;92779:44:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;92771:84;;;::::0;::::1;::::0;;11396:2:1;92771:84:0::1;::::0;::::1;11378:21:1::0;11435:2;11415:18;;;11408:30;11474:18;11454;;;11447:46;11510:18;;92771:84:0::1;11368:166:1::0;92771:84:0::1;92572:291:::0;:::o;90543:727::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;90637:25:::1;::::0;::::1;90629:59;;;::::0;::::1;::::0;;8894:2:1;90629:59:0::1;::::0;::::1;8876:21:1::0;8933:2;8913:18;;;8906:30;8972:23;8952:18;;;8945:51;9013:18;;90629:59:0::1;8866:171:1::0;90629:59:0::1;90707:17;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;::::1;;:25;;:17:::0;:25:::1;90699:57;;;::::0;::::1;::::0;;11048:2:1;90699:57:0::1;::::0;::::1;11030:21:1::0;11087:2;11067:18;;;11060:30;11126:21;11106:18;;;11099:49;11165:18;;90699:57:0::1;11020:169:1::0;90699:57:0::1;90820:17;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;90813:24;;;::::1;::::0;;90916:259:::1;90937:10;:17:::0;90933:21;::::1;90916:259;;;90997:11;90980:28;;:10;90991:1;90980:13;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;::::1;;:28;90976:188;;;91053:1;91029:10;91040:1;91029:13;;;;;;;;:::i;:::-;;;;;;;;;:26;;;;;;;;;;;;;;;;;;91143:5;;90976:188;90956:3:::0;::::1;::::0;::::1;:::i;:::-;;;;90916:259;;;;91191:8;91187:34;;;91201:20;:18;:20::i;:::-;91239:23;::::0;3653:42:1;3641:55;;3623:74;;91239:23:0::1;::::0;3611:2:1;3596:18;91239:23:0::1;;;;;;;;90543:727:::0;;:::o;87160:567::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;81004:17:::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;87259:15;;81004:17:::1;;80996:41;;;::::0;::::1;::::0;;10357:2:1;80996:41:0::1;::::0;::::1;10339:21:1::0;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0::1;10329:161:1::0;80996:41:0::1;87445:12:::2;::::0;87413::::2;::::0;87316:10;;87445:12;87413:27:::2;::::0;87316:10;;87413:27:::2;:::i;:::-;87412:45;;87404:74;;;::::0;::::2;::::0;;11741:2:1;87404:74:0::2;::::0;::::2;11723:21:1::0;11780:2;11760:18;;;11753:30;11819:18;11799;;;11792:46;11855:18;;87404:74:0::2;11713:166:1::0;87404:74:0::2;87489:34;::::0;::::2;;::::0;;;:17:::2;:34;::::0;;;;:50;;87527:12;;87489:34;:50:::2;::::0;87527:12;;87489:50:::2;:::i;:::-;;;;;;;;87566:12;87550;;:28;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;87627:3:0::2;::::0;:42:::2;::::0;;;;:3:::2;4635:55:1::0;;;87627:42:0::2;::::0;::::2;4617:74:1::0;4707:18;;;4700:34;;;87627:3:0;;::::2;::::0;:13:::2;::::0;4590:18:1;;87627:42:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;87699:20;:18;:20::i;:::-;87276:451;80929:1:::1;87160:567:::0;;:::o;86520:405::-;86584:10;81004:17;;;;:4;:17;;;;;;;;80996:41;;;;;;;10357:2:1;80996:41:0;;;10339:21:1;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0;10329:161:1;80996:41:0;86685:4:::1;::::0;:44:::1;::::0;;;;86705:10:::1;86685:44;::::0;::::1;4617:74:1::0;4707:18;;;4700:34;;;86637:11:0;;86685:4:::1;;::::0;:19:::1;::::0;4590:18:1;;86685:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;86798:10:0::1;86779:30;::::0;;;:18:::1;:30;::::0;;;;:47;;86813:13;;-1:-1:-1;86779:30:0;;-1:-1:-1;86779:47:0::1;::::0;86813:13;;86779:47:::1;:::i;:::-;;;;;;;;86854:13;86837;;:30;;;;;;;:::i;84295:641::-:0;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;81004:17:::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;84382:15;;81004:17:::1;;80996:41;;;::::0;::::1;::::0;;10357:2:1;80996:41:0::1;::::0;::::1;10339:21:1::0;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0::1;10329:161:1::0;80996:41:0::1;84477:8:::2;::::0;:48:::2;::::0;;;;84519:4:::2;84477:48;::::0;::::2;3623:74:1::0;84453:21:0::2;::::0;84477:8:::2;;::::0;:33:::2;::::0;3596:18:1;;84477:48:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;84453:72;;84581:8;;;;;;;;;;;:26;;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;;;84677:41:0::2;::::0;::::2;;::::0;;;:24:::2;:41;::::0;;;;:66;;84729:13;;84677:41;:66:::2;::::0;84729:13;;84677:66:::2;:::i;:::-;::::0;;;-1:-1:-1;;84827:18:0::2;::::0;84799:79:::2;::::0;84827:18:::2;;84847:15:::0;84864:13;84799:27:::2;:79::i;:::-;84908:20;:18;:20::i;15154:271::-:0;15223:14;;;;15209:10;:28;15201:94;;;;;;;8122:2:1;15201:94:0;;;8104:21:1;8161:2;8141:18;;;8134:30;8200:34;8180:18;;;8173:62;8271:23;8251:18;;;8244:51;8312:19;;15201:94:0;8094:243:1;15201:94:0;15324:5;;;15331:14;15311:35;;;15324:5;;;;3943:34:1;;15331:14:0;;;;4008:2:1;3993:18;;3986:43;15311:35:0;;3855:18:1;15311:35:0;;;;;;;15365:14;;;;15357:22;;;;;;15365:14;;;15357:22;;;;15390:27;;;15154:271::o;92871:286::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;93068:5:::1;::::0;93026:61:::1;::::0;93054:12;;93068:5:::1;;93075:11:::0;93026:27:::1;:61::i;:::-;93113:36;::::0;;4647:42:1;4635:55;;4617:74;;4722:2;4707:18;;4700:34;;;93113:36:0::1;::::0;4590:18:1;93113:36:0::1;4572:168:1::0;88365:706:0;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;81004:17:::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;88494:15;;81004:17:::1;;80996:41;;;::::0;::::1;::::0;;10357:2:1;80996:41:0::1;::::0;::::1;10339:21:1::0;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0::1;10329:161:1::0;80996:41:0::1;88638:17:::2;::::0;88593:19:::2;::::0;88557:13;;88638:17;88593:40:::2;::::0;88557:13;;88593:40:::2;:::i;:::-;88592:63;;88584:86;;;::::0;::::2;::::0;;9602:2:1;88584:86:0::2;::::0;::::2;9584:21:1::0;9641:2;9621:18;;;9614:30;9680:12;9660:18;;;9653:40;9710:18;;88584:86:0::2;9574:160:1::0;88584:86:0::2;88681:41;::::0;::::2;;::::0;;;:24:::2;:41;::::0;;;;:63;;88726:18;;88681:41;:63:::2;::::0;88726:18;;88681:63:::2;:::i;:::-;;;;;;;;88778:18;88755:19;;:41;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;88843:4:0::2;::::0;:35:::2;::::0;;;;::::2;::::0;::::2;7524:25:1::0;;;88843:4:0::2;::::0;;::::2;::::0;:20:::2;::::0;7497:18:1;;88843:35:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;88962:18:0::2;::::0;88934:79:::2;::::0;-1:-1:-1;88962:18:0::2;;::::0;-1:-1:-1;88982:15:0;88999:13;88934:27:::2;:79::i;:::-;89043:20;:18;:20::i;89655:857::-:0;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;89746:25:::1;::::0;::::1;89738:59;;;::::0;::::1;::::0;;8894:2:1;89738:59:0::1;::::0;::::1;8876:21:1::0;8933:2;8913:18;;;8906:30;8972:23;8952:18;;;8945:51;9013:18;;89738:59:0::1;8866:171:1::0;89738:59:0::1;89811:20;89833:22:::0;89864:11:::1;89859:32;;;:34;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89810:83:::0;;-1:-1:-1;89810:83:0;-1:-1:-1;89989:17:0::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;::::1;;:26;89981:61;;;::::0;::::1;::::0;;10697:2:1;89981:61:0::1;::::0;::::1;10679:21:1::0;10736:2;10716:18;;;10709:30;10775:24;10755:18;;;10748:52;10817:18;;89981:61:0::1;10669:172:1::0;89981:61:0::1;90053:17;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;;;:24;;;::::1;90073:4;90053:24:::0;;::::1;::::0;;;90089:10:::1;:28:::0;;;;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;90156:18:::1;:31:::0;;;;;:35;;;90202:17:::1;:30:::0;;;;;:34;;;90247:24:::1;:37:::0;;;;;:41;;;90321:23:::1;:36:::0;;;;;:43;;;90375:39;;::::1;:43:::0;90431:34;::::1;;;90445:20;:18;:20::i;:::-;90483:21;::::0;3653:42:1;3641:55;;3623:74;;90483:21:0::1;::::0;3611:2:1;3596:18;90483:21:0::1;;;;;;;89727:785;;89655:857:::0;;:::o;83316:971::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;83418:8:::1;::::0;:25:::1;::::0;;;;;;;83393:22:::1;::::0;83418:8:::1;;::::0;:23:::1;::::0;:25:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;83393:22;83418:8;:25;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83393:50;;83454:21;83478:8;;;;;;;;;;;:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83454:53;;83518:31;83552:4;;;;;;;;;;;:28;;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83518:64;;83593:24;83685:16;;83679:2;:22;;;;:::i;:::-;83671:3;83637:29;83652:14:::0;83671:3;83637:29:::1;:::i;:::-;83622:45;::::0;:11;:45:::1;:::i;:::-;83621:53;;;;:::i;:::-;83620:82;;;;:::i;:::-;83593:109:::0;-1:-1:-1;83713:30:0::1;83793:3;83747:42;83766:23:::0;83593:109;83747:42:::1;:::i;:::-;83746:50;;;;:::i;:::-;83713:83:::0;-1:-1:-1;83865:13:0;83833:28:::1;83713:83:::0;83858:3:::1;83833:28;:::i;:::-;83832:46;;;;:::i;:::-;83807:71;;83957:17;;83929:22;83900:19;;:52;;;;:::i;:::-;83899:75;;83891:98;;;::::0;::::1;::::0;;9602:2:1;83891:98:0::1;::::0;::::1;9584:21:1::0;9641:2;9621:18;;;9614:30;9680:12;9660:18;;;9653:40;9710:18;;83891:98:0::1;9574:160:1::0;83891:98:0::1;84030:22;84000:19;;:53;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;84093:4:0::1;::::0;:42:::1;::::0;;;;84116:4:::1;84093:42;::::0;::::1;4617:74:1::0;4707:18;;;4700:34;;;84093:4:0::1;::::0;;::::1;::::0;:14:::1;::::0;4590:18:1;;84093:42:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;84176:4:0::1;::::0;84197:8:::1;::::0;84176:44:::1;::::0;;;;:4:::1;84197:8:::0;;::::1;84176:44;::::0;::::1;4617:74:1::0;4707:18;;;4700:34;;;84176:4:0;::::1;::::0;-1:-1:-1;84176:12:0::1;::::0;-1:-1:-1;4590:18:1;;84176:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;84231:8:0::1;::::0;:48:::1;::::0;;;;::::1;::::0;::::1;13394:25:1::0;;;84231:8:0::1;13435:18:1::0;;;13428:34;;;13478:18;;;13471:34;84231:8:0::1;::::0;;::::1;::::0;:29:::1;::::0;13367:18:1;;84231:48:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;83382:905;;;;;83316:971:::0;:::o;91844:123::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;91923:12:::1;:36:::0;91844:123::o;81902:412::-;81970:6;81990:20;82021:11;82016:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;82116:36:0;;;82061:29;82116:36;;;:23;:36;;;;;:39;81989:61;;-1:-1:-1;82061:29:0;82093:62;;81989:61;82093:62;:::i;:::-;82061:94;;82288:16;;82282:2;:22;;;;:::i;:::-;82234:37;;;;;;;:24;:37;;;;;;82233:72;;;;:::i;:::-;82198:31;;;;;;;:18;:31;;;;;;82173:56;;:22;:56;:::i;:::-;:133;;;;:::i;:::-;82166:140;81902:412;-1:-1:-1;;;;81902:412:0:o;93187:274::-;80853:16;;93320:4;;93326:12;;80853:16;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;93352:12:::1;93366:19:::0;93389:3:::1;:8;;93404:6;93412:5;;93389:29;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;93351:67:0;;;;-1:-1:-1;93187:274:0;-1:-1:-1;;;;;;;93187:274:0:o;91278:193::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;91362:26:::1;::::0;::::1;91354:67;;;::::0;::::1;::::0;;12086:2:1;91354:67:0::1;::::0;::::1;12068:21:1::0;12125:2;12105:18;;;12098:30;12164;12144:18;;;12137:58;12212:18;;91354:67:0::1;12058:178:1::0;91354:67:0::1;91432:16;:31:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;91278:193::o;91709:127::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;91790:13:::1;:38:::0;91709:127::o;92126:109::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;92211:6:::1;:16:::0;92126:109::o;81484:104::-;81534:16;81570:10;81563:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81484:104;:::o;87735:395::-;87797:10;81004:17;;;;:4;:17;;;;;;;;80996:41;;;;;;;10357:2:1;80996:41:0;;;10339:21:1;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0;10329:161:1;80996:41:0;87896:3:::1;::::0;:42:::1;::::0;;;;87915:10:::1;87896:42;::::0;::::1;4617:74:1::0;4707:18;;;4700:34;;;87849:10:0;;87896:3:::1;;::::0;:18:::1;::::0;4590::1;;87896:42:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;88006:10:0::1;87988:29;::::0;;;:17:::1;:29;::::0;;;;:45;;88021:12;;-1:-1:-1;87988:29:0;;-1:-1:-1;87988:45:0::1;::::0;88021:12;;87988:45:::1;:::i;:::-;;;;;;;;88060:12;88044;;:28;;;;;;;:::i;82424:814::-:0;82472:28;82515:34;82570:6;82565:544;82586:10;:17;82582:21;;82565:544;;;82664:19;82686:10;82697:1;82686:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;82718:25:0;;82714:384;;82764:20;82786:22;82817:11;82812:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;82920:36;;;;;;;:23;:36;;;;;:39;82763:83;;-1:-1:-1;82763:83:0;-1:-1:-1;82897:62:0;;82763:83;82897:62;:::i;:::-;82865:95;;;;:::i;:::-;83042:36;;;;;;;:23;:36;;;;;82865:95;;-1:-1:-1;83079:1:0;83042:39;;83017:64;;83024:14;83017:64;:::i;:::-;82979:103;;;;:::i;:::-;;;82744:354;;82714:384;-1:-1:-1;82605:3:0;;;;:::i;:::-;;;;82565:544;;;-1:-1:-1;83119:23:0;:46;;;;83176:25;:54;82424:814::o;92243:321::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;92388:36:::1;::::0;::::1;;::::0;;;:23:::1;:36;::::0;;;;:61;;;92497:1:::1;92460:39;:63:::0;;;92536:20:::1;:18;:20::i;14023:402::-:0;14248:51;;;14237:10;4321:15:1;;;14248:51:0;;;4303:34:1;4373:15;;;4353:18;;;4346:43;4405:18;;;;4398:34;;;14248:51:0;;;;;;;;;;4215:18:1;;;;14248:51:0;;;;;;;;;;;;;14237:63;;-1:-1:-1;;;;14237:10:0;;;;:63;;14248:51;14237:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14201:99;;;;14319:7;:57;;;;-1:-1:-1;14331:11:0;;:16;;:44;;;14362:4;14351:24;;;;;;;;;;;;:::i;:::-;14311:106;;;;;;;12443:2:1;14311:106:0;;;12425:21:1;12482:2;12462:18;;;12455:30;12521:34;12501:18;;;12494:62;12592:6;12572:18;;;12565:34;12616:19;;14311:106:0;12415:226:1;14311:106:0;14111:314;;14023:402;;;;:::o;13654:361::-;13849:45;;;13838:10;4635:55:1;;;13849:45:0;;;4617:74:1;4707:18;;;;4700:34;;;13849:45:0;;;;;;;;;;4590:18:1;;;;13849:45:0;;;;;;;;;;;;;13838:57;;-1:-1:-1;;;;13838:10:0;;;;:57;;13849:45;13838:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13802:93;;;;13914:7;:57;;;;-1:-1:-1;13926:11:0;;:16;;:44;;;13957:4;13946:24;;;;;;;;;;;;:::i;:::-;13906:101;;;;;;;7762:2:1;13906:101:0;;;7744:21:1;7801:2;7781:18;;;7774:30;7840:33;7820:18;;;7813:61;7891:18;;13906:101:0;7734:181:1;13906:101:0;13724:291;;13654:361;;;:::o;14:196:1:-;82:20;;142:42;131:54;;121:65;;111:2;;200:1;197;190:12;111:2;63:147;;;:::o;215:186::-;274:6;327:2;315:9;306:7;302:23;298:32;295:2;;;343:1;340;333:12;295:2;366:29;385:9;366:29;:::i;406:315::-;471:6;479;532:2;520:9;511:7;507:23;503:32;500:2;;;548:1;545;538:12;500:2;571:29;590:9;571:29;:::i;:::-;561:39;;650:2;639:9;635:18;622:32;663:28;685:5;663:28;:::i;:::-;710:5;700:15;;;490:231;;;;;:::o;726:320::-;801:6;809;817;870:2;858:9;849:7;845:23;841:32;838:2;;;886:1;883;876:12;838:2;909:29;928:9;909:29;:::i;:::-;899:39;985:2;970:18;;957:32;;-1:-1:-1;1036:2:1;1021:18;;;1008:32;;828:218;-1:-1:-1;;;828:218:1:o;1051:254::-;1119:6;1127;1180:2;1168:9;1159:7;1155:23;1151:32;1148:2;;;1196:1;1193;1186:12;1148:2;1219:29;1238:9;1219:29;:::i;:::-;1209:39;1295:2;1280:18;;;;1267:32;;-1:-1:-1;;;1138:167:1:o;1310:733::-;1398:6;1406;1414;1422;1475:2;1463:9;1454:7;1450:23;1446:32;1443:2;;;1491:1;1488;1481:12;1443:2;1514:29;1533:9;1514:29;:::i;:::-;1504:39;;1590:2;1579:9;1575:18;1562:32;1552:42;;1645:2;1634:9;1630:18;1617:32;1668:18;1709:2;1701:6;1698:14;1695:2;;;1725:1;1722;1715:12;1695:2;1763:6;1752:9;1748:22;1738:32;;1808:7;1801:4;1797:2;1793:13;1789:27;1779:2;;1830:1;1827;1820:12;1779:2;1870;1857:16;1896:2;1888:6;1885:14;1882:2;;;1912:1;1909;1902:12;1882:2;1957:7;1952:2;1943:6;1939:2;1935:15;1931:24;1928:37;1925:2;;;1978:1;1975;1968:12;1925:2;1433:610;;;;-1:-1:-1;;2009:2:1;2001:11;;-1:-1:-1;;;1433:610:1:o;2048:245::-;2115:6;2168:2;2156:9;2147:7;2143:23;2139:32;2136:2;;;2184:1;2181;2174:12;2136:2;2216:9;2210:16;2235:28;2257:5;2235:28;:::i;2298:180::-;2357:6;2410:2;2398:9;2389:7;2385:23;2381:32;2378:2;;;2426:1;2423;2416:12;2378:2;-1:-1:-1;2449:23:1;;2368:110;-1:-1:-1;2368:110:1:o;2483:184::-;2553:6;2606:2;2594:9;2585:7;2581:23;2577:32;2574:2;;;2622:1;2619;2612:12;2574:2;-1:-1:-1;2645:16:1;;2564:103;-1:-1:-1;2564:103:1:o;2672:245::-;2751:6;2759;2812:2;2800:9;2791:7;2787:23;2783:32;2780:2;;;2828:1;2825;2818:12;2780:2;-1:-1:-1;;2851:16:1;;2907:2;2892:18;;;2886:25;2851:16;;2886:25;;-1:-1:-1;2770:147:1:o;2922:271::-;3105:6;3097;3092:3;3079:33;3061:3;3131:16;;3156:13;;;3131:16;3069:124;-1:-1:-1;3069:124:1:o;3198:274::-;3327:3;3365:6;3359:13;3381:53;3427:6;3422:3;3415:4;3407:6;3403:17;3381:53;:::i;:::-;3450:16;;;;;3335:137;-1:-1:-1;;3335:137:1:o;4745:681::-;4916:2;4968:21;;;5038:13;;4941:18;;;5060:22;;;4887:4;;4916:2;5139:15;;;;5113:2;5098:18;;;4887:4;5182:218;5196:6;5193:1;5190:13;5182:218;;;5261:13;;5276:42;5257:62;5245:75;;5375:15;;;;5340:12;;;;5218:1;5211:9;5182:218;;;-1:-1:-1;5417:3:1;;4896:530;-1:-1:-1;;;;;;4896:530:1:o;5623:521::-;5806:6;5799:14;5792:22;5781:9;5774:41;5851:2;5846;5835:9;5831:18;5824:30;5755:4;5883:6;5877:13;5926:6;5921:2;5910:9;5906:18;5899:34;5942:66;6001:6;5996:2;5985:9;5981:18;5976:2;5968:6;5964:15;5942:66;:::i;:::-;6060:2;6048:15;6065:66;6044:88;6029:104;;;;6135:2;6025:113;;5764:380;-1:-1:-1;;;5764:380:1:o;13769:367::-;13808:3;13843:1;13840;13836:9;13952:1;13884:66;13880:74;13877:1;13873:82;13868:2;13861:10;13857:99;13854:2;;;13959:18;;:::i;:::-;14078:1;14010:66;14006:74;14003:1;13999:82;13995:2;13991:91;13988:2;;;14085:18;;:::i;:::-;-1:-1:-1;;14121:9:1;;13816:320::o;14141:128::-;14181:3;14212:1;14208:6;14205:1;14202:13;14199:2;;;14218:18;;:::i;:::-;-1:-1:-1;14254:9:1;;14189:80::o;14274:274::-;14314:1;14340;14330:2;;14375:77;14372:1;14365:88;14476:4;14473:1;14466:15;14504:4;14501:1;14494:15;14330:2;-1:-1:-1;14533:9:1;;14320:228::o;14553:482::-;14642:1;14685:5;14642:1;14699:330;14720:7;14710:8;14707:21;14699:330;;;14839:4;14771:66;14767:77;14761:4;14758:87;14755:2;;;14848:18;;:::i;:::-;14898:7;14888:8;14884:22;14881:2;;;14918:16;;;;14881:2;14997:22;;;;14957:15;;;;14699:330;;;14703:3;14617:418;;;;;:::o;15040:131::-;15100:5;15129:36;15156:8;15150:4;15225:5;15255:8;15245:2;;-1:-1:-1;15296:1:1;15310:5;;15245:2;15344:4;15334:2;;-1:-1:-1;15381:1:1;15395:5;;15334:2;15426:4;15444:1;15439:59;;;;15512:1;15507:130;;;;15419:218;;15439:59;15469:1;15460:10;;15483:5;;;15507:130;15544:3;15534:8;15531:17;15528:2;;;15551:18;;:::i;:::-;-1:-1:-1;;15607:1:1;15593:16;;15622:5;;15419:218;;15721:2;15711:8;15708:16;15702:3;15696:4;15693:13;15689:36;15683:2;15673:8;15670:16;15665:2;15659:4;15656:12;15652:35;15649:77;15646:2;;;-1:-1:-1;15758:19:1;;;15790:5;;15646:2;15837:34;15862:8;15856:4;15837:34;:::i;:::-;15967:6;15899:66;15895:79;15886:7;15883:92;15880:2;;;15978:18;;:::i;:::-;16016:20;;-1:-1:-1;15235:807:1;;;;;:::o;16047:655::-;16086:7;16118:66;16210:1;16207;16203:9;16238:1;16235;16231:9;16283:1;16279:2;16275:10;16272:1;16269:17;16264:2;16260;16256:11;16252:35;16249:2;;;16290:18;;:::i;:::-;16329:66;16421:1;16418;16414:9;16468:1;16464:2;16459:11;16456:1;16452:19;16447:2;16443;16439:11;16435:37;16432:2;;;16475:18;;:::i;:::-;16521:1;16518;16514:9;16504:19;;16568:1;16564:2;16559:11;16556:1;16552:19;16547:2;16543;16539:11;16535:37;16532:2;;;16575:18;;:::i;:::-;16640:1;16636:2;16631:11;16628:1;16624:19;16619:2;16615;16611:11;16607:37;16604:2;;;16647:18;;:::i;:::-;-1:-1:-1;;;16687:9:1;;;;;16098:604;-1:-1:-1;;;16098:604:1:o;16707:228::-;16747:7;16873:1;16805:66;16801:74;16798:1;16795:81;16790:1;16783:9;16776:17;16772:105;16769:2;;;16880:18;;:::i;:::-;-1:-1:-1;16920:9:1;;16759:176::o;16940:369::-;16979:4;17015:1;17012;17008:9;17124:1;17056:66;17052:74;17049:1;17045:82;17040:2;17033:10;17029:99;17026:2;;;17131:18;;:::i;:::-;17250:1;17182:66;17178:74;17175:1;17171:82;17167:2;17163:91;17160:2;;;17257:18;;:::i;:::-;-1:-1:-1;;17294:9:1;;16988:321::o;17314:125::-;17354:4;17382:1;17379;17376:8;17373:2;;;17387:18;;:::i;:::-;-1:-1:-1;17424:9:1;;17363:76::o;17444:258::-;17516:1;17526:113;17540:6;17537:1;17534:13;17526:113;;;17616:11;;;17610:18;17597:11;;;17590:39;17562:2;17555:10;17526:113;;;17657:6;17654:1;17651:13;17648:2;;;-1:-1:-1;;17692:1:1;17674:16;;17667:27;17497:205::o;17707:195::-;17746:3;17777:66;17770:5;17767:77;17764:2;;;17847:18;;:::i;:::-;-1:-1:-1;17894:1:1;17883:13;;17754:148::o;17907:184::-;17959:77;17956:1;17949:88;18056:4;18053:1;18046:15;18080:4;18077:1;18070:15;18096:184;18148:77;18145:1;18138:88;18245:4;18242:1;18235:15;18269:4;18266:1;18259:15;18285:118;18371:5;18364:13;18357:21;18350:5;18347:32;18337:2;;18393:1;18390;18383:12

Swarm Source

ipfs://d7505757b29efdbf7dd8a05f225e43d07f180164296d60d6c8815eede21ee644

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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