{"file_path":"FraxPoolV3.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\r\npragma solidity >=0.8.0;\r\n\r\n// Sources flattened with hardhat v2.6.2 https://hardhat.org\r\n\r\n// File contracts/Math/SafeMath.sol\r\n\r\n\r\n/**\r\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\r\n * checks.\r\n *\r\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\r\n * in bugs, because programmers usually assume that an overflow raises an\r\n * error, which is the standard behavior in high level programming languages.\r\n * `SafeMath` restores this intuition by reverting the transaction when an\r\n * operation overflows.\r\n *\r\n * Using this library instead of the unchecked operations eliminates an entire\r\n * class of bugs, so it's recommended to use it always.\r\n */\r\nlibrary SafeMath {\r\n    /**\r\n     * @dev Returns the addition of two unsigned integers, reverting on\r\n     * overflow.\r\n     *\r\n     * Counterpart to Solidity's `+` operator.\r\n     *\r\n     * Requirements:\r\n     * - Addition cannot overflow.\r\n     */\r\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        uint256 c = a + b;\r\n        require(c >= a, \"SafeMath: addition overflow\");\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the subtraction of two unsigned integers, reverting on\r\n     * overflow (when the result is negative).\r\n     *\r\n     * Counterpart to Solidity's `-` operator.\r\n     *\r\n     * Requirements:\r\n     * - Subtraction cannot overflow.\r\n     */\r\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return sub(a, b, \"SafeMath: subtraction overflow\");\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\r\n     * overflow (when the result is negative).\r\n     *\r\n     * Counterpart to Solidity's `-` operator.\r\n     *\r\n     * Requirements:\r\n     * - Subtraction cannot overflow.\r\n     *\r\n     * _Available since v2.4.0._\r\n     */\r\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\r\n        require(b <= a, errorMessage);\r\n        uint256 c = a - b;\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the multiplication of two unsigned integers, reverting on\r\n     * overflow.\r\n     *\r\n     * Counterpart to Solidity's `*` operator.\r\n     *\r\n     * Requirements:\r\n     * - Multiplication cannot overflow.\r\n     */\r\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\r\n        // benefit is lost if 'b' is also tested.\r\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\r\n        if (a == 0) {\r\n            return 0;\r\n        }\r\n\r\n        uint256 c = a * b;\r\n        require(c / a == b, \"SafeMath: multiplication overflow\");\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the integer division of two unsigned integers. Reverts on\r\n     * division by zero. The result is rounded towards zero.\r\n     *\r\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\r\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\r\n     * uses an invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     */\r\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return div(a, b, \"SafeMath: division by zero\");\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\r\n     * division by zero. The result is rounded towards zero.\r\n     *\r\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\r\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\r\n     * uses an invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     *\r\n     * _Available since v2.4.0._\r\n     */\r\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\r\n        // Solidity only automatically asserts when dividing by 0\r\n        require(b > 0, errorMessage);\r\n        uint256 c = a / b;\r\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\r\n\r\n        return c;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\r\n     * Reverts when dividing by zero.\r\n     *\r\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\r\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\r\n     * invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     */\r\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return mod(a, b, \"SafeMath: modulo by zero\");\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\r\n     * Reverts with custom message when dividing by zero.\r\n     *\r\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\r\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\r\n     * invalid opcode to revert (consuming all remaining gas).\r\n     *\r\n     * Requirements:\r\n     * - The divisor cannot be zero.\r\n     *\r\n     * _Available since v2.4.0._\r\n     */\r\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\r\n        require(b != 0, errorMessage);\r\n        return a % b;\r\n    }\r\n}\r\n\r\n\r\n// File contracts/Uniswap/TransferHelper.sol\r\n\r\n\r\n// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false\r\nlibrary TransferHelper {\r\n    function safeApprove(address token, address to, uint value) internal {\r\n        // bytes4(keccak256(bytes('approve(address,uint256)')));\r\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));\r\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');\r\n    }\r\n\r\n    function safeTransfer(address token, address to, uint value) internal {\r\n        // bytes4(keccak256(bytes('transfer(address,uint256)')));\r\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));\r\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');\r\n    }\r\n\r\n    function safeTransferFrom(address token, address from, address to, uint value) internal {\r\n        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));\r\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));\r\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');\r\n    }\r\n\r\n    function safeTransferETH(address to, uint value) internal {\r\n        (bool success,) = to.call{value:value}(new bytes(0));\r\n        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');\r\n    }\r\n}\r\n\r\n\r\n// File contracts/Staking/Owned.sol\r\n\r\n\r\n// https://docs.synthetix.io/contracts/Owned\r\ncontract Owned {\r\n    address public owner;\r\n    address public nominatedOwner;\r\n\r\n    constructor (address _owner) public {\r\n        require(_owner != address(0), \"Owner address cannot be 0\");\r\n        owner = _owner;\r\n        emit OwnerChanged(address(0), _owner);\r\n    }\r\n\r\n    function nominateNewOwner(address _owner) external onlyOwner {\r\n        nominatedOwner = _owner;\r\n        emit OwnerNominated(_owner);\r\n    }\r\n\r\n    function acceptOwnership() external {\r\n        require(msg.sender == nominatedOwner, \"You must be nominated before you can accept ownership\");\r\n        emit OwnerChanged(owner, nominatedOwner);\r\n        owner = nominatedOwner;\r\n        nominatedOwner = address(0);\r\n    }\r\n\r\n    modifier onlyOwner {\r\n        require(msg.sender == owner, \"Only the contract owner may perform this action\");\r\n        _;\r\n    }\r\n\r\n    event OwnerNominated(address newOwner);\r\n    event OwnerChanged(address oldOwner, address newOwner);\r\n}\r\n\r\n\r\n// File contracts/FXS/IFxs.sol\r\n\r\n\r\ninterface IFxs {\r\n  function DEFAULT_ADMIN_ROLE() external view returns(bytes32);\r\n  function FRAXStablecoinAdd() external view returns(address);\r\n  function FXS_DAO_min() external view returns(uint256);\r\n  function allowance(address owner, address spender) external view returns(uint256);\r\n  function approve(address spender, uint256 amount) external returns(bool);\r\n  function balanceOf(address account) external view returns(uint256);\r\n  function burn(uint256 amount) external;\r\n  function burnFrom(address account, uint256 amount) external;\r\n  function checkpoints(address, uint32) external view returns(uint32 fromBlock, uint96 votes);\r\n  function decimals() external view returns(uint8);\r\n  function decreaseAllowance(address spender, uint256 subtractedValue) external returns(bool);\r\n  function genesis_supply() external view returns(uint256);\r\n  function getCurrentVotes(address account) external view returns(uint96);\r\n  function getPriorVotes(address account, uint256 blockNumber) external view returns(uint96);\r\n  function getRoleAdmin(bytes32 role) external view returns(bytes32);\r\n  function getRoleMember(bytes32 role, uint256 index) external view returns(address);\r\n  function getRoleMemberCount(bytes32 role) external view returns(uint256);\r\n  function grantRole(bytes32 role, address account) external;\r\n  function hasRole(bytes32 role, address account) external view returns(bool);\r\n  function increaseAllowance(address spender, uint256 addedValue) external returns(bool);\r\n  function mint(address to, uint256 amount) external;\r\n  function name() external view returns(string memory);\r\n  function numCheckpoints(address) external view returns(uint32);\r\n  function oracle_address() external view returns(address);\r\n  function owner_address() external view returns(address);\r\n  function pool_burn_from(address b_address, uint256 b_amount) external;\r\n  function pool_mint(address m_address, uint256 m_amount) external;\r\n  function renounceRole(bytes32 role, address account) external;\r\n  function revokeRole(bytes32 role, address account) external;\r\n  function setFRAXAddress(address frax_contract_address) external;\r\n  function setFXSMinDAO(uint256 min_FXS) external;\r\n  function setOracle(address new_oracle) external;\r\n  function setOwner(address _owner_address) external;\r\n  function setTimelock(address new_timelock) external;\r\n  function symbol() external view returns(string memory);\r\n  function timelock_address() external view returns(address);\r\n  function toggleVotes() external;\r\n  function totalSupply() external view returns(uint256);\r\n  function trackingVotes() external view returns(bool);\r\n  function transfer(address recipient, uint256 amount) external returns(bool);\r\n  function transferFrom(address sender, address recipient, uint256 amount) external returns(bool);\r\n}\r\n\r\n\r\n// File contracts/Frax/IFrax.sol\r\n\r\n\r\ninterface IFrax {\r\n  function COLLATERAL_RATIO_PAUSER() external view returns (bytes32);\r\n  function DEFAULT_ADMIN_ADDRESS() external view returns (address);\r\n  function DEFAULT_ADMIN_ROLE() external view returns (bytes32);\r\n  function addPool(address pool_address ) external;\r\n  function allowance(address owner, address spender ) external view returns (uint256);\r\n  function approve(address spender, uint256 amount ) external returns (bool);\r\n  function balanceOf(address account ) external view returns (uint256);\r\n  function burn(uint256 amount ) external;\r\n  function burnFrom(address account, uint256 amount ) external;\r\n  function collateral_ratio_paused() external view returns (bool);\r\n  function controller_address() external view returns (address);\r\n  function creator_address() external view returns (address);\r\n  function decimals() external view returns (uint8);\r\n  function decreaseAllowance(address spender, uint256 subtractedValue ) external returns (bool);\r\n  function eth_usd_consumer_address() external view returns (address);\r\n  function eth_usd_price() external view returns (uint256);\r\n  function frax_eth_oracle_address() external view returns (address);\r\n  function frax_info() external view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256);\r\n  function frax_pools(address ) external view returns (bool);\r\n  function frax_pools_array(uint256 ) external view returns (address);\r\n  function frax_price() external view returns (uint256);\r\n  function frax_step() external view returns (uint256);\r\n  function fxs_address() external view returns (address);\r\n  function fxs_eth_oracle_address() external view returns (address);\r\n  function fxs_price() external view returns (uint256);\r\n  function genesis_supply() external view returns (uint256);\r\n  function getRoleAdmin(bytes32 role ) external view returns (bytes32);\r\n  function getRoleMember(bytes32 role, uint256 index ) external view returns (address);\r\n  function getRoleMemberCount(bytes32 role ) external view returns (uint256);\r\n  function globalCollateralValue() external view returns (uint256);\r\n  function global_collateral_ratio() external view returns (uint256);\r\n  function grantRole(bytes32 role, address account ) external;\r\n  function hasRole(bytes32 role, address account ) external view returns (bool);\r\n  function increaseAllowance(address spender, uint256 addedValue ) external returns (bool);\r\n  function last_call_time() external view returns (uint256);\r\n  function minting_fee() external view returns (uint256);\r\n  function name() external view returns (string memory);\r\n  function owner_address() external view returns (address);\r\n  function pool_burn_from(address b_address, uint256 b_amount ) external;\r\n  function pool_mint(address m_address, uint256 m_amount ) external;\r\n  function price_band() external view returns (uint256);\r\n  function price_target() external view returns (uint256);\r\n  function redemption_fee() external view returns (uint256);\r\n  function refreshCollateralRatio() external;\r\n  function refresh_cooldown() external view returns (uint256);\r\n  function removePool(address pool_address ) external;\r\n  function renounceRole(bytes32 role, address account ) external;\r\n  function revokeRole(bytes32 role, address account ) external;\r\n  function setController(address _controller_address ) external;\r\n  function setETHUSDOracle(address _eth_usd_consumer_address ) external;\r\n  function setFRAXEthOracle(address _frax_oracle_addr, address _weth_address ) external;\r\n  function setFXSAddress(address _fxs_address ) external;\r\n  function setFXSEthOracle(address _fxs_oracle_addr, address _weth_address ) external;\r\n  function setFraxStep(uint256 _new_step ) external;\r\n  function setMintingFee(uint256 min_fee ) external;\r\n  function setOwner(address _owner_address ) external;\r\n  function setPriceBand(uint256 _price_band ) external;\r\n  function setPriceTarget(uint256 _new_price_target ) external;\r\n  function setRedemptionFee(uint256 red_fee ) external;\r\n  function setRefreshCooldown(uint256 _new_cooldown ) external;\r\n  function setTimelock(address new_timelock ) external;\r\n  function symbol() external view returns (string memory);\r\n  function timelock_address() external view returns (address);\r\n  function toggleCollateralRatio() external;\r\n  function totalSupply() external view returns (uint256);\r\n  function transfer(address recipient, uint256 amount ) external returns (bool);\r\n  function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool);\r\n  function weth_address() external view returns (address);\r\n}\r\n\r\n\r\n// File contracts/Oracle/AggregatorV3Interface.sol\r\n\r\n\r\ninterface AggregatorV3Interface {\r\n\r\n  function decimals() external view returns (uint8);\r\n  function description() external view returns (string memory);\r\n  function version() external view returns (uint256);\r\n\r\n  // getRoundData and latestRoundData should both raise \"No data present\"\r\n  // if they do not have data to report, instead of returning unset values\r\n  // which could be misinterpreted as actual reported values.\r\n  function getRoundData(uint80 _roundId)\r\n    external\r\n    view\r\n    returns (\r\n      uint80 roundId,\r\n      int256 answer,\r\n      uint256 startedAt,\r\n      uint256 updatedAt,\r\n      uint80 answeredInRound\r\n    );\r\n  function latestRoundData()\r\n    external\r\n    view\r\n    returns (\r\n      uint80 roundId,\r\n      int256 answer,\r\n      uint256 startedAt,\r\n      uint256 updatedAt,\r\n      uint80 answeredInRound\r\n    );\r\n\r\n}\r\n\r\n\r\n// File contracts/Frax/IFraxAMOMinter.sol\r\n\r\n\r\ninterface IFraxAMOMinter {\r\n  function FRAX() external view returns(address);\r\n  function FXS() external view returns(address);\r\n  function acceptOwnership() external;\r\n  function addAMO(address amo_address, bool sync_too) external;\r\n  function allAMOAddresses() external view returns(address[] memory);\r\n  function allAMOsLength() external view returns(uint256);\r\n  function amoProfit(address amo_address) external view returns(int256);\r\n  function amos(address) external view returns(bool);\r\n  function amos_array(uint256) external view returns(address);\r\n  function burnFXS(uint256 amount) external;\r\n  function burnFraxFromAMO(uint256 frax_amount) external;\r\n  function burnFxsFromAMO(uint256 fxs_amount) external;\r\n  function col_idx() external view returns(uint256);\r\n  function collatDollarBalance() external view returns(uint256);\r\n  function collatDollarBalanceStored() external view returns(uint256);\r\n  function collat_borrow_cap() external view returns(int256);\r\n  function collat_borrowed_balances(address) external view returns(int256);\r\n  function collat_borrowed_sum() external view returns(int256);\r\n  function collateral_address() external view returns(address);\r\n  function collateral_token() external view returns(address);\r\n  function custodian_address() external view returns(address);\r\n  function fraxDollarBalanceStored() external view returns(uint256);\r\n  function giveCollatToAMO(address destination_amo, uint256 collat_amount) external;\r\n  function min_cr() external view returns(uint256);\r\n  function mintFraxForAMO(address destination_amo, uint256 frax_amount) external;\r\n  function mint_balances(address) external view returns(int256);\r\n  function mint_cap() external view returns(int256);\r\n  function mint_sum() external view returns(int256);\r\n  function missing_decimals() external view returns(uint256);\r\n  function nominateNewOwner(address _owner) external;\r\n  function nominatedOwner() external view returns(address);\r\n  function override_collat_balance() external view returns(bool);\r\n  function override_collat_balance_amount() external view returns(uint256);\r\n  function owner() external view returns(address);\r\n  function pool() external view returns(address);\r\n  function receiveCollatFromAMO(uint256 usdc_amount) external;\r\n  function recoverERC20(address tokenAddress, uint256 tokenAmount) external;\r\n  function removeAMO(address amo_address, bool sync_too) external;\r\n  function setCustodian(address _custodian_address) external;\r\n  function setFraxPool(address _pool_address) external;\r\n  function setMinimumCollateralRatio(uint256 _min_cr) external;\r\n  function setMintCap(uint256 _mint_cap) external;\r\n  function setOverrideCollatBalance(bool _state, uint256 _balance) external;\r\n  function setTimelock(address new_timelock) external;\r\n  function syncDollarBalances() external;\r\n  function timelock_address() external view returns(address);\r\n  function unspentProfitGlobal() external view returns(int256);\r\n}\r\n\r\n\r\n// File contracts/Common/Context.sol\r\n\r\n\r\n/*\r\n * @dev Provides information about the current execution context, including the\r\n * sender of the transaction and its data. While these are generally available\r\n * via msg.sender and msg.data, they should not be accessed in such a direct\r\n * manner, since when dealing with GSN meta-transactions the account sending and\r\n * paying for execution may not be the actual sender (as far as an application\r\n * is concerned).\r\n *\r\n * This contract is only required for intermediate, library-like contracts.\r\n */\r\nabstract contract Context {\r\n    function _msgSender() internal view virtual returns (address payable) {\r\n        return payable(msg.sender);\r\n    }\r\n\r\n    function _msgData() internal view virtual returns (bytes memory) {\r\n        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\r\n        return msg.data;\r\n    }\r\n}\r\n\r\n\r\n// File contracts/ERC20/IERC20.sol\r\n\r\n\r\n\r\n/**\r\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\r\n * the optional functions; to access them see {ERC20Detailed}.\r\n */\r\ninterface IERC20 {\r\n    /**\r\n     * @dev Returns the amount of tokens in existence.\r\n     */\r\n    function totalSupply() external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Returns the amount of tokens owned by `account`.\r\n     */\r\n    function balanceOf(address account) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transfer(address recipient, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Returns the remaining number of tokens that `spender` will be\r\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\r\n     * zero by default.\r\n     *\r\n     * This value changes when {approve} or {transferFrom} are called.\r\n     */\r\n    function allowance(address owner, address spender) external view returns (uint256);\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\r\n     * that someone may use both the old and the new allowance by unfortunate\r\n     * transaction ordering. One possible solution to mitigate this race\r\n     * condition is to first reduce the spender's allowance to 0 and set the\r\n     * desired value afterwards:\r\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\r\n     *\r\n     * Emits an {Approval} event.\r\n     */\r\n    function approve(address spender, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\r\n     * allowance mechanism. `amount` is then deducted from the caller's\r\n     * allowance.\r\n     *\r\n     * Returns a boolean value indicating whether the operation succeeded.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     */\r\n    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\r\n\r\n    /**\r\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\r\n     * another (`to`).\r\n     *\r\n     * Note that `value` may be zero.\r\n     */\r\n    event Transfer(address indexed from, address indexed to, uint256 value);\r\n\r\n    /**\r\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\r\n     * a call to {approve}. `value` is the new allowance.\r\n     */\r\n    event Approval(address indexed owner, address indexed spender, uint256 value);\r\n}\r\n\r\n\r\n// File contracts/Utils/Address.sol\r\n\r\n\r\n/**\r\n * @dev Collection of functions related to the address type\r\n */\r\nlibrary Address {\r\n    /**\r\n     * @dev Returns true if `account` is a contract.\r\n     *\r\n     * [IMPORTANT]\r\n     * ====\r\n     * It is unsafe to assume that an address for which this function returns\r\n     * false is an externally-owned account (EOA) and not a contract.\r\n     *\r\n     * Among others, `isContract` will return false for the following\r\n     * types of addresses:\r\n     *\r\n     *  - an externally-owned account\r\n     *  - a contract in construction\r\n     *  - an address where a contract will be created\r\n     *  - an address where a contract lived, but was destroyed\r\n     * ====\r\n     */\r\n    function isContract(address account) internal view returns (bool) {\r\n        // This method relies on extcodesize, which returns 0 for contracts in\r\n        // construction, since the code is only stored at the end of the\r\n        // constructor execution.\r\n\r\n        uint256 size;\r\n        // solhint-disable-next-line no-inline-assembly\r\n        assembly { size := extcodesize(account) }\r\n        return size > 0;\r\n    }\r\n\r\n    /**\r\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\r\n     * `recipient`, forwarding all available gas and reverting on errors.\r\n     *\r\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\r\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\r\n     * imposed by `transfer`, making them unable to receive funds via\r\n     * `transfer`. {sendValue} removes this limitation.\r\n     *\r\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\r\n     *\r\n     * IMPORTANT: because control is transferred to `recipient`, care must be\r\n     * taken to not create reentrancy vulnerabilities. Consider using\r\n     * {ReentrancyGuard} or the\r\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\r\n     */\r\n    function sendValue(address payable recipient, uint256 amount) internal {\r\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\r\n\r\n        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\r\n        (bool success, ) = recipient.call{ value: amount }(\"\");\r\n        require(success, \"Address: unable to send value, recipient may have reverted\");\r\n    }\r\n\r\n    /**\r\n     * @dev Performs a Solidity function call using a low level `call`. A\r\n     * plain`call` is an unsafe replacement for a function call: use this\r\n     * function instead.\r\n     *\r\n     * If `target` reverts with a revert reason, it is bubbled up by this\r\n     * function (like regular Solidity function calls).\r\n     *\r\n     * Returns the raw returned data. To convert to the expected return value,\r\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `target` must be a contract.\r\n     * - calling `target` with `data` must not revert.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\r\n      return functionCall(target, data, \"Address: low-level call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\r\n     * `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, 0, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but also transferring `value` wei to `target`.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the calling contract must have an ETH balance of at least `value`.\r\n     * - the called Solidity function must be `payable`.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\r\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\r\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\r\n     *\r\n     * _Available since v3.1._\r\n     */\r\n    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\r\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\r\n        require(isContract(target), \"Address: call to non-contract\");\r\n\r\n        // solhint-disable-next-line avoid-low-level-calls\r\n        (bool success, bytes memory returndata) = target.call{ value: value }(data);\r\n        return _verifyCallResult(success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\r\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a static call.\r\n     *\r\n     * _Available since v3.3._\r\n     */\r\n    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\r\n        require(isContract(target), \"Address: static call to non-contract\");\r\n\r\n        // solhint-disable-next-line avoid-low-level-calls\r\n        (bool success, bytes memory returndata) = target.staticcall(data);\r\n        return _verifyCallResult(success, returndata, errorMessage);\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\r\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\r\n    }\r\n\r\n    /**\r\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\r\n     * but performing a delegate call.\r\n     *\r\n     * _Available since v3.4._\r\n     */\r\n    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\r\n        require(isContract(target), \"Address: delegate call to non-contract\");\r\n\r\n        // solhint-disable-next-line avoid-low-level-calls\r\n        (bool success, bytes memory returndata) = target.delegatecall(data);\r\n        return _verifyCallResult(success, returndata, errorMessage);\r\n    }\r\n\r\n    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\r\n        if (success) {\r\n            return returndata;\r\n        } else {\r\n            // Look for revert reason and bubble it up if present\r\n            if (returndata.length > 0) {\r\n                // The easiest way to bubble the revert reason is using memory via assembly\r\n\r\n                // solhint-disable-next-line no-inline-assembly\r\n                assembly {\r\n                    let returndata_size := mload(returndata)\r\n                    revert(add(32, returndata), returndata_size)\r\n                }\r\n            } else {\r\n                revert(errorMessage);\r\n            }\r\n        }\r\n    }\r\n}\r\n\r\n\r\n// File contracts/ERC20/ERC20.sol\r\n\r\n\r\n\r\n\r\n\r\n/**\r\n * @dev Implementation of the {IERC20} interface.\r\n *\r\n * This implementation is agnostic to the way tokens are created. This means\r\n * that a supply mechanism has to be added in a derived contract using {_mint}.\r\n * For a generic mechanism see {ERC20Mintable}.\r\n *\r\n * TIP: For a detailed writeup see our guide\r\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\r\n * to implement supply mechanisms].\r\n *\r\n * We have followed general OpenZeppelin guidelines: functions revert instead\r\n * of returning `false` on failure. This behavior is nonetheless conventional\r\n * and does not conflict with the expectations of ERC20 applications.\r\n *\r\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\r\n * This allows applications to reconstruct the allowance for all accounts just\r\n * by listening to said events. Other implementations of the EIP may not emit\r\n * these events, as it isn't required by the specification.\r\n *\r\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\r\n * functions have been added to mitigate the well-known issues around setting\r\n * allowances. See {IERC20-approve}.\r\n */\r\n \r\ncontract ERC20 is Context, IERC20 {\r\n    using SafeMath for uint256;\r\n\r\n    mapping (address => uint256) private _balances;\r\n\r\n    mapping (address => mapping (address => uint256)) private _allowances;\r\n\r\n    uint256 private _totalSupply;\r\n\r\n    string private _name;\r\n    string private _symbol;\r\n    uint8 private _decimals;\r\n    \r\n    /**\r\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\r\n     * a default value of 18.\r\n     *\r\n     * To select a different value for {decimals}, use {_setupDecimals}.\r\n     *\r\n     * All three of these values are immutable: they can only be set once during\r\n     * construction.\r\n     */\r\n    constructor (string memory __name, string memory __symbol) public {\r\n        _name = __name;\r\n        _symbol = __symbol;\r\n        _decimals = 18;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the name of the token.\r\n     */\r\n    function name() public view returns (string memory) {\r\n        return _name;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the symbol of the token, usually a shorter version of the\r\n     * name.\r\n     */\r\n    function symbol() public view returns (string memory) {\r\n        return _symbol;\r\n    }\r\n\r\n    /**\r\n     * @dev Returns the number of decimals used to get its user representation.\r\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\r\n     * be displayed to a user as `5,05` (`505 / 10 ** 2`).\r\n     *\r\n     * Tokens usually opt for a value of 18, imitating the relationship between\r\n     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\r\n     * called.\r\n     *\r\n     * NOTE: This information is only used for _display_ purposes: it in\r\n     * no way affects any of the arithmetic of the contract, including\r\n     * {IERC20-balanceOf} and {IERC20-transfer}.\r\n     */\r\n    function decimals() public view returns (uint8) {\r\n        return _decimals;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-totalSupply}.\r\n     */\r\n    function totalSupply() public view override returns (uint256) {\r\n        return _totalSupply;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-balanceOf}.\r\n     */\r\n    function balanceOf(address account) public view override returns (uint256) {\r\n        return _balances[account];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-transfer}.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `recipient` cannot be the zero address.\r\n     * - the caller must have a balance of at least `amount`.\r\n     */\r\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\r\n        _transfer(_msgSender(), recipient, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-allowance}.\r\n     */\r\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\r\n        return _allowances[owner][spender];\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-approve}.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.approve(address spender, uint256 amount)\r\n     */\r\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\r\n        _approve(_msgSender(), spender, amount);\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev See {IERC20-transferFrom}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance. This is not\r\n     * required by the EIP. See the note at the beginning of {ERC20};\r\n     *\r\n     * Requirements:\r\n     * - `sender` and `recipient` cannot be the zero address.\r\n     * - `sender` must have a balance of at least `amount`.\r\n     * - the caller must have allowance for `sender`'s tokens of at least\r\n     * `amount`.\r\n     */\r\n    function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\r\n        _transfer(sender, recipient, amount);\r\n        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\r\n     *\r\n     * This is an alternative to {approve} that can be used as a mitigation for\r\n     * problems described in {IERC20-approve}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\r\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\r\n     *\r\n     * This is an alternative to {approve} that can be used as a mitigation for\r\n     * problems described in {IERC20-approve}.\r\n     *\r\n     * Emits an {Approval} event indicating the updated allowance.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `spender` cannot be the zero address.\r\n     * - `spender` must have allowance for the caller of at least\r\n     * `subtractedValue`.\r\n     */\r\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\r\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\r\n     *\r\n     * This is internal function is equivalent to {transfer}, and can be used to\r\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\r\n     *\r\n     * Emits a {Transfer} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `sender` cannot be the zero address.\r\n     * - `recipient` cannot be the zero address.\r\n     * - `sender` must have a balance of at least `amount`.\r\n     */\r\n    function _transfer(address sender, address recipient, uint256 amount) internal virtual {\r\n        require(sender != address(0), \"ERC20: transfer from the zero address\");\r\n        require(recipient != address(0), \"ERC20: transfer to the zero address\");\r\n\r\n        _beforeTokenTransfer(sender, recipient, amount);\r\n\r\n        _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\r\n        _balances[recipient] = _balances[recipient].add(amount);\r\n        emit Transfer(sender, recipient, amount);\r\n    }\r\n\r\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\r\n     * the total supply.\r\n     *\r\n     * Emits a {Transfer} event with `from` set to the zero address.\r\n     *\r\n     * Requirements\r\n     *\r\n     * - `to` cannot be the zero address.\r\n     */\r\n    function _mint(address account, uint256 amount) internal virtual {\r\n        require(account != address(0), \"ERC20: mint to the zero address\");\r\n\r\n        _beforeTokenTransfer(address(0), account, amount);\r\n\r\n        _totalSupply = _totalSupply.add(amount);\r\n        _balances[account] = _balances[account].add(amount);\r\n        emit Transfer(address(0), account, amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Destroys `amount` tokens from the caller.\r\n     *\r\n     * See {ERC20-_burn}.\r\n     */\r\n    function burn(uint256 amount) public virtual {\r\n        _burn(_msgSender(), amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Destroys `amount` tokens from `account`, deducting from the caller's\r\n     * allowance.\r\n     *\r\n     * See {ERC20-_burn} and {ERC20-allowance}.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - the caller must have allowance for `accounts`'s tokens of at least\r\n     * `amount`.\r\n     */\r\n    function burnFrom(address account, uint256 amount) public virtual {\r\n        uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, \"ERC20: burn amount exceeds allowance\");\r\n\r\n        _approve(account, _msgSender(), decreasedAllowance);\r\n        _burn(account, amount);\r\n    }\r\n\r\n\r\n    /**\r\n     * @dev Destroys `amount` tokens from `account`, reducing the\r\n     * total supply.\r\n     *\r\n     * Emits a {Transfer} event with `to` set to the zero address.\r\n     *\r\n     * Requirements\r\n     *\r\n     * - `account` cannot be the zero address.\r\n     * - `account` must have at least `amount` tokens.\r\n     */\r\n    function _burn(address account, uint256 amount) internal virtual {\r\n        require(account != address(0), \"ERC20: burn from the zero address\");\r\n\r\n        _beforeTokenTransfer(account, address(0), amount);\r\n\r\n        _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\r\n        _totalSupply = _totalSupply.sub(amount);\r\n        emit Transfer(account, address(0), amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.\r\n     *\r\n     * This is internal function is equivalent to `approve`, and can be used to\r\n     * e.g. set automatic allowances for certain subsystems, etc.\r\n     *\r\n     * Emits an {Approval} event.\r\n     *\r\n     * Requirements:\r\n     *\r\n     * - `owner` cannot be the zero address.\r\n     * - `spender` cannot be the zero address.\r\n     */\r\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\r\n        require(owner != address(0), \"ERC20: approve from the zero address\");\r\n        require(spender != address(0), \"ERC20: approve to the zero address\");\r\n\r\n        _allowances[owner][spender] = amount;\r\n        emit Approval(owner, spender, amount);\r\n    }\r\n\r\n    /**\r\n     * @dev Destroys `amount` tokens from `account`.`amount` is then deducted\r\n     * from the caller's allowance.\r\n     *\r\n     * See {_burn} and {_approve}.\r\n     */\r\n    function _burnFrom(address account, uint256 amount) internal virtual {\r\n        _burn(account, amount);\r\n        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, \"ERC20: burn amount exceeds allowance\"));\r\n    }\r\n\r\n    /**\r\n     * @dev Hook that is called before any transfer of tokens. This includes\r\n     * minting and burning.\r\n     *\r\n     * Calling conditions:\r\n     *\r\n     * - when `from` and `to` are both non-zero, `amount` of `from`'s tokens\r\n     * will be to transferred to `to`.\r\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\r\n     * - when `to` is zero, `amount` of `from`'s tokens will be burned.\r\n     * - `from` and `to` are never both zero.\r\n     *\r\n     * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks].\r\n     */\r\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\r\n}\r\n\r\n\r\n// File contracts/Frax/Pools/FraxPoolV3.sol\r\n\r\n\r\n// ====================================================================\r\n// |     ______                   _______                             |\r\n// |    / _____________ __  __   / ____(_____  ____ _____  ________   |\r\n// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \\/ __ `/ __ \\/ ___/ _ \\  |\r\n// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |\r\n// | /_/   /_/   \\__,_/_/|_|  /_/   /_/_/ /_/\\__,_/_/ /_/\\___/\\___/   |\r\n// |                                                                  |\r\n// ====================================================================\r\n// ============================ FraxPoolV3 ============================\r\n// ====================================================================\r\n// Allows multiple stablecoins (fixed amount at initialization) as collateral\r\n// LUSD, sUSD, USDP, Wrapped UST, and FEI initially\r\n// For this pool, the goal is to accept crypto-backed / overcollateralized stablecoins to limit\r\n// government / regulatory risk (e.g. USDC blacklisting until holders KYC)\r\n\r\n// Frax Finance: https://github.com/FraxFinance\r\n\r\n// Primary Author(s)\r\n// Travis Moore: https://github.com/FortisFortuna\r\n\r\n// Reviewer(s) / Contributor(s)\r\n// Jason Huan: https://github.com/jasonhuan\r\n// Sam Kazemian: https://github.com/samkazemian\r\n// Dennis: github.com/denett\r\n// Hameed\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\ncontract FraxPoolV3 is Owned {\r\n    using SafeMath for uint256;\r\n    // SafeMath automatically included in Solidity >= 8.0.0\r\n\r\n    /* ========== STATE VARIABLES ========== */\r\n\r\n    // Core\r\n    address public timelock_address;\r\n    address public custodian_address; // Custodian is an EOA (or msig) with pausing privileges only, in case of an emergency\r\n    IFrax private FRAX = IFrax(0x853d955aCEf822Db058eb8505911ED77F175b99e);\r\n    IFxs private FXS = IFxs(0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0);\r\n    mapping(address => bool) public amo_minter_addresses; // minter address -> is it enabled\r\n    AggregatorV3Interface public priceFeedFRAXUSD = AggregatorV3Interface(0xB9E1E3A9feFf48998E45Fa90847ed4D467E8BcfD);\r\n    AggregatorV3Interface public priceFeedFXSUSD = AggregatorV3Interface(0x6Ebc52C8C1089be9eB3945C4350B68B8E4C2233f);\r\n    uint256 private chainlink_frax_usd_decimals;\r\n    uint256 private chainlink_fxs_usd_decimals;\r\n\r\n    // Collateral\r\n    address[] public collateral_addresses;\r\n    string[] public collateral_symbols;\r\n    uint256[] public missing_decimals; // Number of decimals needed to get to E18. collateral index -> missing_decimals\r\n    uint256[] public pool_ceilings; // Total across all collaterals. Accounts for missing_decimals\r\n    uint256[] public collateral_prices; // Stores price of the collateral, if price is paused\r\n    mapping(address => uint256) public collateralAddrToIdx; // collateral addr -> collateral index\r\n    mapping(address => bool) public enabled_collaterals; // collateral address -> is it enabled\r\n    \r\n    // Redeem related\r\n    mapping (address => uint256) public redeemFXSBalances;\r\n    mapping (address => mapping(uint256 => uint256)) public redeemCollateralBalances; // Address -> collateral index -> balance\r\n    uint256[] public unclaimedPoolCollateral; // collateral index -> balance\r\n    uint256 public unclaimedPoolFXS;\r\n    mapping (address => uint256) public lastRedeemed; // Collateral independent\r\n    uint256 public redemption_delay = 2; // Number of blocks to wait before being able to collectRedemption()\r\n    uint256 public redeem_price_threshold = 990000; // $0.99\r\n    uint256 public mint_price_threshold = 1010000; // $1.01\r\n    \r\n    // Buyback related\r\n    mapping(uint256 => uint256) public bbkHourlyCum; // Epoch hour ->  Collat out in that hour (E18)\r\n    uint256 public bbkMaxColE18OutPerHour = 1000e18;\r\n\r\n    // Recollat related\r\n    mapping(uint256 => uint256) public rctHourlyCum; // Epoch hour ->  FXS out in that hour\r\n    uint256 public rctMaxFxsOutPerHour = 1000e18;\r\n\r\n    // Fees and rates\r\n    // getters are in collateral_information()\r\n    uint256[] private minting_fee;\r\n    uint256[] private redemption_fee;\r\n    uint256[] private buyback_fee;\r\n    uint256[] private recollat_fee;\r\n    uint256 public bonus_rate; // Bonus rate on FXS minted during recollateralize(); 6 decimals of precision, set to 0.75% on genesis\r\n    \r\n    // Constants for various precisions\r\n    uint256 private constant PRICE_PRECISION = 1e6;\r\n\r\n    // Pause variables\r\n    // getters are in collateral_information()\r\n    bool[] private mintPaused; // Collateral-specific\r\n    bool[] private redeemPaused; // Collateral-specific\r\n    bool[] private recollateralizePaused; // Collateral-specific\r\n    bool[] private buyBackPaused; // Collateral-specific\r\n\r\n    /* ========== MODIFIERS ========== */\r\n\r\n    modifier onlyByOwnGov() {\r\n        require(msg.sender == timelock_address || msg.sender == owner, \"Not owner or timelock\");\r\n        _;\r\n    }\r\n\r\n    modifier onlyByOwnGovCust() {\r\n        require(msg.sender == timelock_address || msg.sender == owner || msg.sender == custodian_address, \"Not owner, tlck, or custd\");\r\n        _;\r\n    }\r\n\r\n    modifier onlyAMOMinters() {\r\n        require(amo_minter_addresses[msg.sender], \"Not an AMO Minter\");\r\n        _;\r\n    }\r\n\r\n    modifier collateralEnabled(uint256 col_idx) {\r\n        require(enabled_collaterals[collateral_addresses[col_idx]], \"Collateral disabled\");\r\n        _;\r\n    }\r\n \r\n    /* ========== CONSTRUCTOR ========== */\r\n    \r\n    constructor (\r\n        address _pool_manager_address,\r\n        address _custodian_address,\r\n        address _timelock_address,\r\n        address[] memory _collateral_addresses,\r\n        uint256[] memory _pool_ceilings,\r\n        uint256[] memory _initial_fees\r\n    ) Owned(_pool_manager_address){\r\n        // Core\r\n        timelock_address = _timelock_address;\r\n        custodian_address = _custodian_address;\r\n\r\n        // Fill collateral info\r\n        collateral_addresses = _collateral_addresses;\r\n        for (uint256 i = 0; i < _collateral_addresses.length; i++){ \r\n            // For fast collateral address -> collateral idx lookups later\r\n            collateralAddrToIdx[_collateral_addresses[i]] = i;\r\n\r\n            // Set all of the collaterals initially to disabled\r\n            enabled_collaterals[_collateral_addresses[i]] = false;\r\n\r\n            // Add in the missing decimals\r\n            missing_decimals.push(uint256(18).sub(ERC20(_collateral_addresses[i]).decimals()));\r\n\r\n            // Add in the collateral symbols\r\n            collateral_symbols.push(ERC20(_collateral_addresses[i]).symbol());\r\n\r\n            // Initialize unclaimed pool collateral\r\n            unclaimedPoolCollateral.push(0);\r\n\r\n            // Initialize paused prices to $1 as a backup\r\n            collateral_prices.push(PRICE_PRECISION);\r\n\r\n            // Handle the fees\r\n            minting_fee.push(_initial_fees[0]);\r\n            redemption_fee.push(_initial_fees[1]);\r\n            buyback_fee.push(_initial_fees[2]);\r\n            recollat_fee.push(_initial_fees[3]);\r\n\r\n            // Handle the pauses\r\n            mintPaused.push(false);\r\n            redeemPaused.push(false);\r\n            recollateralizePaused.push(false);\r\n            buyBackPaused.push(false);\r\n        }\r\n\r\n        // Pool ceiling\r\n        pool_ceilings = _pool_ceilings;\r\n\r\n        // Set the decimals\r\n        chainlink_frax_usd_decimals = priceFeedFRAXUSD.decimals();\r\n        chainlink_fxs_usd_decimals = priceFeedFXSUSD.decimals();\r\n    }\r\n\r\n    /* ========== STRUCTS ========== */\r\n    \r\n    struct CollateralInformation {\r\n        uint256 index;\r\n        string symbol;\r\n        address col_addr;\r\n        bool is_enabled;\r\n        uint256 missing_decs;\r\n        uint256 price;\r\n        uint256 pool_ceiling;\r\n        bool mint_paused;\r\n        bool redeem_paused;\r\n        bool recollat_paused;\r\n        bool buyback_paused;\r\n        uint256 minting_fee;\r\n        uint256 redemption_fee;\r\n        uint256 buyback_fee;\r\n        uint256 recollat_fee;\r\n    }\r\n\r\n    /* ========== VIEWS ========== */\r\n\r\n    // Helpful for UIs\r\n    function collateral_information(address collat_address) external view returns (CollateralInformation memory return_data){\r\n        require(enabled_collaterals[collat_address], \"Invalid collateral\");\r\n\r\n        // Get the index\r\n        uint256 idx = collateralAddrToIdx[collat_address];\r\n        \r\n        return_data = CollateralInformation(\r\n            idx, // [0]\r\n            collateral_symbols[idx], // [1]\r\n            collat_address, // [2]\r\n            enabled_collaterals[collat_address], // [3]\r\n            missing_decimals[idx], // [4]\r\n            collateral_prices[idx], // [5]\r\n            pool_ceilings[idx], // [6]\r\n            mintPaused[idx], // [7]\r\n            redeemPaused[idx], // [8]\r\n            recollateralizePaused[idx], // [9]\r\n            buyBackPaused[idx], // [10]\r\n            minting_fee[idx], // [11]\r\n            redemption_fee[idx], // [12]\r\n            buyback_fee[idx], // [13]\r\n            recollat_fee[idx] // [14]\r\n        );\r\n    }\r\n\r\n    function allCollaterals() external view returns (address[] memory) {\r\n        return collateral_addresses;\r\n    }\r\n\r\n    function getFRAXPrice() public view returns (uint256) {\r\n        ( , int price, , , ) = priceFeedFRAXUSD.latestRoundData();\r\n        return uint256(price).mul(PRICE_PRECISION).div(10 ** chainlink_frax_usd_decimals);\r\n    }\r\n\r\n    function getFXSPrice() public view returns (uint256) {\r\n        ( , int price, , , ) = priceFeedFXSUSD.latestRoundData();\r\n        return uint256(price).mul(PRICE_PRECISION).div(10 ** chainlink_fxs_usd_decimals);\r\n    }\r\n\r\n    // Returns the FRAX value in collateral tokens\r\n    function getFRAXInCollateral(uint256 col_idx, uint256 frax_amount) public view returns (uint256) {\r\n        return frax_amount.mul(PRICE_PRECISION).div(10 ** missing_decimals[col_idx]).div(collateral_prices[col_idx]);\r\n    }\r\n\r\n    // Used by some functions.\r\n    function freeCollatBalance(uint256 col_idx) public view returns (uint256) {\r\n        return ERC20(collateral_addresses[col_idx]).balanceOf(address(this)).sub(unclaimedPoolCollateral[col_idx]);\r\n    }\r\n\r\n    // Returns dollar value of collateral held in this Frax pool, in E18\r\n    function collatDollarBalance() external view returns (uint256 balance_tally) {\r\n        balance_tally = 0;\r\n\r\n        // Test 1\r\n        for (uint256 i = 0; i < collateral_addresses.length; i++){ \r\n            balance_tally += freeCollatBalance(i).mul(10 ** missing_decimals[i]).mul(collateral_prices[i]).div(PRICE_PRECISION);\r\n        }\r\n\r\n    }\r\n\r\n    function comboCalcBbkRct(uint256 cur, uint256 max, uint256 theo) internal pure returns (uint256) {\r\n        if (cur >= max) {\r\n            // If the hourly limit has already been reached, return 0;\r\n            return 0;\r\n        }\r\n        else {\r\n            // Get the available amount\r\n            uint256 available = max.sub(cur);\r\n\r\n            if (theo >= available) {\r\n                // If the the theoretical is more than the available, return the available\r\n                return available;\r\n            }\r\n            else {\r\n                // Otherwise, return the theoretical amount\r\n                return theo;\r\n            }\r\n        } \r\n    }\r\n\r\n    // Returns the value of excess collateral (in E18) held globally, compared to what is needed to maintain the global collateral ratio\r\n    // Also has throttling to avoid dumps during large price movements\r\n    function buybackAvailableCollat() public view returns (uint256) {\r\n        uint256 total_supply = FRAX.totalSupply();\r\n        uint256 global_collateral_ratio = FRAX.global_collateral_ratio();\r\n        uint256 global_collat_value = FRAX.globalCollateralValue();\r\n\r\n        if (global_collateral_ratio > PRICE_PRECISION) global_collateral_ratio = PRICE_PRECISION; // Handles an overcollateralized contract with CR > 1\r\n        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\r\n        \r\n        if (global_collat_value > required_collat_dollar_value_d18) {\r\n            // Get the theoretical buyback amount\r\n            uint256 theoretical_bbk_amt = global_collat_value.sub(required_collat_dollar_value_d18);\r\n\r\n            // See how much has collateral has been issued this hour\r\n            uint256 current_hr_bbk = bbkHourlyCum[curEpochHr()];\r\n\r\n            // Account for the throttling\r\n            return comboCalcBbkRct(current_hr_bbk, bbkMaxColE18OutPerHour, theoretical_bbk_amt);\r\n        }\r\n        else return 0;\r\n    }\r\n\r\n    // Returns the missing amount of collateral (in E18) needed to maintain the collateral ratio\r\n    function recollatTheoColAvailableE18() public view returns (uint256) {\r\n        uint256 frax_total_supply = FRAX.totalSupply();\r\n        uint256 effective_collateral_ratio = FRAX.globalCollateralValue().mul(PRICE_PRECISION).div(frax_total_supply); // Returns it in 1e6\r\n        \r\n        uint256 desired_collat_e24 = (FRAX.global_collateral_ratio()).mul(frax_total_supply);\r\n        uint256 effective_collat_e24 = effective_collateral_ratio.mul(frax_total_supply);\r\n\r\n        // Return 0 if already overcollateralized\r\n        // Otherwise, return the deficiency\r\n        if (effective_collat_e24 >= desired_collat_e24) return 0;\r\n        else {\r\n            return (desired_collat_e24.sub(effective_collat_e24)).div(PRICE_PRECISION);\r\n        }\r\n    }\r\n\r\n    // Returns the value of FXS available to be used for recollats\r\n    // Also has throttling to avoid dumps during large price movements\r\n    function recollatAvailableFxs() public view returns (uint256) {\r\n        uint256 fxs_price = getFXSPrice();\r\n\r\n        // Get the amount of collateral theoretically available\r\n        uint256 recollat_theo_available_e18 = recollatTheoColAvailableE18();\r\n\r\n        // Get the amount of FXS theoretically outputtable\r\n        uint256 fxs_theo_out = recollat_theo_available_e18.mul(PRICE_PRECISION).div(fxs_price);\r\n\r\n        // See how much FXS has been issued this hour\r\n        uint256 current_hr_rct = rctHourlyCum[curEpochHr()];\r\n\r\n        // Account for the throttling\r\n        return comboCalcBbkRct(current_hr_rct, rctMaxFxsOutPerHour, fxs_theo_out);\r\n    }\r\n\r\n    // Returns the current epoch hour\r\n    function curEpochHr() public view returns (uint256) {\r\n        return (block.timestamp / 3600); // Truncation desired\r\n    }\r\n\r\n    /* ========== PUBLIC FUNCTIONS ========== */\r\n\r\n     function mintFrax(\r\n        uint256 col_idx, \r\n        uint256 frax_amt,\r\n        uint256 frax_out_min,\r\n        bool one_to_one_override\r\n    ) external collateralEnabled(col_idx) returns (\r\n        uint256 total_frax_mint, \r\n        uint256 collat_needed, \r\n        uint256 fxs_needed\r\n    ) {\r\n        require(mintPaused[col_idx] == false, \"Minting is paused\");\r\n\r\n        // Prevent unneccessary mints\r\n        require(getFRAXPrice() >= mint_price_threshold, \"Frax price too low\");\r\n\r\n        uint256 global_collateral_ratio = FRAX.global_collateral_ratio();\r\n\r\n        if (one_to_one_override || global_collateral_ratio >= PRICE_PRECISION) { \r\n            // 1-to-1, overcollateralized, or user selects override\r\n            collat_needed = getFRAXInCollateral(col_idx, frax_amt);\r\n            fxs_needed = 0;\r\n        } else if (global_collateral_ratio == 0) { \r\n            // Algorithmic\r\n            collat_needed = 0;\r\n            fxs_needed = frax_amt.mul(PRICE_PRECISION).div(getFXSPrice());\r\n        } else { \r\n            // Fractional\r\n            uint256 frax_for_collat = frax_amt.mul(global_collateral_ratio).div(PRICE_PRECISION);\r\n            uint256 frax_for_fxs = frax_amt.sub(frax_for_collat);\r\n            collat_needed = getFRAXInCollateral(col_idx, frax_for_collat);\r\n            fxs_needed = frax_for_fxs.mul(PRICE_PRECISION).div(getFXSPrice());\r\n        }\r\n\r\n        // Subtract the minting fee\r\n        total_frax_mint = (frax_amt.mul(PRICE_PRECISION.sub(minting_fee[col_idx]))).div(PRICE_PRECISION);\r\n\r\n        // Checks\r\n        require((frax_out_min <= total_frax_mint), \"FRAX slippage\");\r\n        require(freeCollatBalance(col_idx).add(collat_needed) <= pool_ceilings[col_idx], \"Pool ceiling\");\r\n\r\n        // Take the FXS and collateral first\r\n        FXS.pool_burn_from(msg.sender, fxs_needed);\r\n        TransferHelper.safeTransferFrom(collateral_addresses[col_idx], msg.sender, address(this), collat_needed);\r\n\r\n        // Mint the FRAX\r\n        FRAX.pool_mint(msg.sender, total_frax_mint);\r\n    }\r\n\r\n    function redeemFrax(\r\n        uint256 col_idx, \r\n        uint256 frax_amount, \r\n        uint256 fxs_out_min, \r\n        uint256 col_out_min\r\n    ) external collateralEnabled(col_idx) returns (\r\n        uint256 collat_out, \r\n        uint256 fxs_out\r\n    ) {\r\n        require(redeemPaused[col_idx] == false, \"Redeeming is paused\");\r\n\r\n        // Prevent unneccessary redemptions that could adversely affect the FXS price\r\n        require(getFRAXPrice() <= redeem_price_threshold, \"Frax price too high\");\r\n\r\n        uint256 global_collateral_ratio = FRAX.global_collateral_ratio();\r\n        uint256 frax_after_fee = (frax_amount.mul(PRICE_PRECISION.sub(redemption_fee[col_idx]))).div(PRICE_PRECISION);\r\n\r\n        // Assumes $1 FRAX in all cases\r\n        if(global_collateral_ratio >= PRICE_PRECISION) { \r\n            // 1-to-1 or overcollateralized\r\n            collat_out = frax_after_fee\r\n                            .mul(collateral_prices[col_idx])\r\n                            .div(10 ** (6 + missing_decimals[col_idx])); // PRICE_PRECISION + missing decimals\r\n            fxs_out = 0;\r\n        } else if (global_collateral_ratio == 0) { \r\n            // Algorithmic\r\n            fxs_out = frax_after_fee\r\n                            .mul(PRICE_PRECISION)\r\n                            .div(getFXSPrice());\r\n            collat_out = 0;\r\n        } else { \r\n            // Fractional\r\n            collat_out = frax_after_fee\r\n                            .mul(global_collateral_ratio)\r\n                            .mul(collateral_prices[col_idx])\r\n                            .div(10 ** (12 + missing_decimals[col_idx])); // PRICE_PRECISION ^2 + missing decimals\r\n            fxs_out = frax_after_fee\r\n                            .mul(PRICE_PRECISION.sub(global_collateral_ratio))\r\n                            .div(getFXSPrice()); // PRICE_PRECISIONS CANCEL OUT\r\n        }\r\n\r\n        // Checks\r\n        require(collat_out <= (ERC20(collateral_addresses[col_idx])).balanceOf(address(this)).sub(unclaimedPoolCollateral[col_idx]), \"Insufficient pool collateral\");\r\n        require(collat_out >= col_out_min, \"Collateral slippage\");\r\n        require(fxs_out >= fxs_out_min, \"FXS slippage\");\r\n\r\n        // Account for the redeem delay\r\n        redeemCollateralBalances[msg.sender][col_idx] = redeemCollateralBalances[msg.sender][col_idx].add(collat_out);\r\n        unclaimedPoolCollateral[col_idx] = unclaimedPoolCollateral[col_idx].add(collat_out);\r\n\r\n        redeemFXSBalances[msg.sender] = redeemFXSBalances[msg.sender].add(fxs_out);\r\n        unclaimedPoolFXS = unclaimedPoolFXS.add(fxs_out);\r\n\r\n        lastRedeemed[msg.sender] = block.number;\r\n\r\n        FRAX.pool_burn_from(msg.sender, frax_amount);\r\n        FXS.pool_mint(address(this), fxs_out);\r\n    }\r\n\r\n    // After a redemption happens, transfer the newly minted FXS and owed collateral from this pool\r\n    // contract to the user. Redemption is split into two functions to prevent flash loans from being able\r\n    // to take out FRAX/collateral from the system, use an AMM to trade the new price, and then mint back into the system.\r\n    function collectRedemption(uint256 col_idx) external returns (uint256 fxs_amount, uint256 collateral_amount) {\r\n        require(redeemPaused[col_idx] == false, \"Redeeming is paused\");\r\n        require((lastRedeemed[msg.sender].add(redemption_delay)) <= block.number, \"Too soon\");\r\n        bool sendFXS = false;\r\n        bool sendCollateral = false;\r\n\r\n        // Use Checks-Effects-Interactions pattern\r\n        if(redeemFXSBalances[msg.sender] > 0){\r\n            fxs_amount = redeemFXSBalances[msg.sender];\r\n            redeemFXSBalances[msg.sender] = 0;\r\n            unclaimedPoolFXS = unclaimedPoolFXS.sub(fxs_amount);\r\n            sendFXS = true;\r\n        }\r\n        \r\n        if(redeemCollateralBalances[msg.sender][col_idx] > 0){\r\n            collateral_amount = redeemCollateralBalances[msg.sender][col_idx];\r\n            redeemCollateralBalances[msg.sender][col_idx] = 0;\r\n            unclaimedPoolCollateral[col_idx] = unclaimedPoolCollateral[col_idx].sub(collateral_amount);\r\n            sendCollateral = true;\r\n        }\r\n\r\n        // Send out the tokens\r\n        if(sendFXS){\r\n            TransferHelper.safeTransfer(address(FXS), msg.sender, fxs_amount);\r\n        }\r\n        if(sendCollateral){\r\n            TransferHelper.safeTransfer(collateral_addresses[col_idx], msg.sender, collateral_amount);\r\n        }\r\n    }\r\n\r\n    // Function can be called by an FXS holder to have the protocol buy back FXS with excess collateral value from a desired collateral pool\r\n    // This can also happen if the collateral ratio > 1\r\n    function buyBackFxs(uint256 col_idx, uint256 fxs_amount, uint256 col_out_min) external collateralEnabled(col_idx) returns (uint256 col_out) {\r\n        require(buyBackPaused[col_idx] == false, \"Buyback is paused\");\r\n        uint256 fxs_price = getFXSPrice();\r\n        uint256 available_excess_collat_dv = buybackAvailableCollat();\r\n\r\n        // 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\r\n        require(available_excess_collat_dv > 0, \"Insuf Collat Avail For BBK\");\r\n\r\n        // Make sure not to take more than is available\r\n        uint256 fxs_dollar_value_d18 = fxs_amount.mul(fxs_price).div(PRICE_PRECISION);\r\n        require(fxs_dollar_value_d18 <= available_excess_collat_dv, \"Insuf Collat Avail For BBK\");\r\n\r\n        // Get the equivalent amount of collateral based on the market value of FXS provided \r\n        uint256 collateral_equivalent_d18 = fxs_dollar_value_d18.mul(PRICE_PRECISION).div(collateral_prices[col_idx]);\r\n        col_out = collateral_equivalent_d18.div(10 ** missing_decimals[col_idx]); // In its natural decimals()\r\n\r\n        // Subtract the buyback fee\r\n        col_out = (col_out.mul(PRICE_PRECISION.sub(buyback_fee[col_idx]))).div(PRICE_PRECISION);\r\n\r\n        // Check for slippage\r\n        require(col_out >= col_out_min, \"Collateral slippage\");\r\n\r\n        // Take in and burn the FXS, then send out the collateral\r\n        FXS.pool_burn_from(msg.sender, fxs_amount);\r\n        TransferHelper.safeTransfer(collateral_addresses[col_idx], msg.sender, col_out);\r\n\r\n        // Increment the outbound collateral, in E18, for that hour\r\n        // Used for buyback throttling\r\n        bbkHourlyCum[curEpochHr()] += collateral_equivalent_d18;\r\n    }\r\n\r\n    // When the protocol is recollateralizing, we need to give a discount of FXS to hit the new CR target\r\n    // Thus, if the target collateral ratio is higher than the actual value of collateral, minters get FXS for adding collateral\r\n    // This function simply rewards anyone that sends collateral to a pool with the same amount of FXS + the bonus rate\r\n    // Anyone can call this function to recollateralize the protocol and take the extra FXS value from the bonus rate as an arb opportunity\r\n    function recollateralize(uint256 col_idx, uint256 collateral_amount, uint256 fxs_out_min) external collateralEnabled(col_idx) returns (uint256 fxs_out) {\r\n        require(recollateralizePaused[col_idx] == false, \"Recollat is paused\");\r\n        uint256 collateral_amount_d18 = collateral_amount * (10 ** missing_decimals[col_idx]);\r\n        uint256 fxs_price = getFXSPrice();\r\n\r\n        // Get the amount of FXS actually available (accounts for throttling)\r\n        uint256 fxs_actually_available = recollatAvailableFxs();\r\n\r\n        // Calculated the attempted amount of FXS\r\n        fxs_out = collateral_amount_d18.mul(PRICE_PRECISION.add(bonus_rate).sub(recollat_fee[col_idx])).div(fxs_price);\r\n\r\n        // Make sure there is FXS available\r\n        require(fxs_out <= fxs_actually_available, \"Insuf FXS Avail For RCT\");\r\n\r\n        // Check slippage\r\n        require(fxs_out >= fxs_out_min, \"FXS slippage\");\r\n\r\n        // Don't take in more collateral than the pool ceiling for this token allows\r\n        require(freeCollatBalance(col_idx).add(collateral_amount) <= pool_ceilings[col_idx], \"Pool ceiling\");\r\n\r\n        // Take in the collateral and pay out the FXS\r\n        TransferHelper.safeTransferFrom(collateral_addresses[col_idx], msg.sender, address(this), collateral_amount);\r\n        FXS.pool_mint(msg.sender, fxs_out);\r\n\r\n        // Increment the outbound FXS, in E18\r\n        // Used for recollat throttling\r\n        rctHourlyCum[curEpochHr()] += fxs_out;\r\n    }\r\n\r\n    // Bypasses the gassy mint->redeem cycle for AMOs to borrow collateral\r\n    function amoMinterBorrow(uint256 collateral_amount) external onlyAMOMinters {\r\n        // Checks the col_idx of the minter as an additional safety check\r\n        uint256 minter_col_idx = IFraxAMOMinter(msg.sender).col_idx();\r\n\r\n        // Transfer\r\n        TransferHelper.safeTransfer(collateral_addresses[minter_col_idx], msg.sender, collateral_amount);\r\n    }\r\n\r\n    /* ========== RESTRICTED FUNCTIONS, CUSTODIAN CAN CALL TOO ========== */\r\n\r\n    function toggleMRBR(uint256 col_idx, uint8 tog_idx) external onlyByOwnGovCust {\r\n        if (tog_idx == 0) mintPaused[col_idx] = !mintPaused[col_idx];\r\n        else if (tog_idx == 1) redeemPaused[col_idx] = !redeemPaused[col_idx];\r\n        else if (tog_idx == 2) buyBackPaused[col_idx] = !buyBackPaused[col_idx];\r\n        else if (tog_idx == 3) recollateralizePaused[col_idx] = !recollateralizePaused[col_idx];\r\n\r\n        emit MRBRToggled(col_idx, tog_idx);\r\n    }\r\n\r\n    /* ========== RESTRICTED FUNCTIONS, GOVERNANCE ONLY ========== */\r\n\r\n    // Add an AMO Minter\r\n    function addAMOMinter(address amo_minter_addr) external onlyByOwnGov {\r\n        require(amo_minter_addr != address(0), \"Zero address detected\");\r\n\r\n        // Make sure the AMO Minter has collatDollarBalance()\r\n        uint256 collat_val_e18 = IFraxAMOMinter(amo_minter_addr).collatDollarBalance();\r\n        require(collat_val_e18 >= 0, \"Invalid AMO\");\r\n\r\n        amo_minter_addresses[amo_minter_addr] = true;\r\n\r\n        emit AMOMinterAdded(amo_minter_addr);\r\n    }\r\n\r\n    // Remove an AMO Minter \r\n    function removeAMOMinter(address amo_minter_addr) external onlyByOwnGov {\r\n        amo_minter_addresses[amo_minter_addr] = false;\r\n        \r\n        emit AMOMinterRemoved(amo_minter_addr);\r\n    }\r\n\r\n    function setCollateralPrice(uint256 col_idx, uint256 _new_price) external onlyByOwnGov {\r\n        collateral_prices[col_idx] = _new_price;\r\n\r\n        emit CollateralPriceSet(col_idx, _new_price);\r\n    }\r\n\r\n    // Could also be called toggleCollateral\r\n    function toggleCollateral(uint256 col_idx) external onlyByOwnGov {\r\n        address col_address = collateral_addresses[col_idx];\r\n        enabled_collaterals[col_address] = !enabled_collaterals[col_address];\r\n\r\n        emit CollateralToggled(col_idx, enabled_collaterals[col_address]);\r\n    }\r\n\r\n    function setPoolCeiling(uint256 col_idx, uint256 new_ceiling) external onlyByOwnGov {\r\n        pool_ceilings[col_idx] = new_ceiling;\r\n\r\n        emit PoolCeilingSet(col_idx, new_ceiling);\r\n    }\r\n\r\n    function setFees(uint256 col_idx, uint256 new_mint_fee, uint256 new_redeem_fee, uint256 new_buyback_fee, uint256 new_recollat_fee) external onlyByOwnGov {\r\n        minting_fee[col_idx] = new_mint_fee;\r\n        redemption_fee[col_idx] = new_redeem_fee;\r\n        buyback_fee[col_idx] = new_buyback_fee;\r\n        recollat_fee[col_idx] = new_recollat_fee;\r\n\r\n        emit FeesSet(col_idx, new_mint_fee, new_redeem_fee, new_buyback_fee, new_recollat_fee);\r\n    }\r\n\r\n    function setPoolParameters(uint256 new_bonus_rate, uint256 new_redemption_delay) external onlyByOwnGov {\r\n        bonus_rate = new_bonus_rate;\r\n        redemption_delay = new_redemption_delay;\r\n        emit PoolParametersSet(new_bonus_rate, new_redemption_delay);\r\n    }\r\n\r\n    function setPriceThresholds(uint256 new_mint_price_threshold, uint256 new_redeem_price_threshold) external onlyByOwnGov {\r\n        mint_price_threshold = new_mint_price_threshold;\r\n        redeem_price_threshold = new_redeem_price_threshold;\r\n        emit PriceThresholdsSet(new_mint_price_threshold, new_redeem_price_threshold);\r\n    }\r\n\r\n    function setBbkRctPerHour(uint256 _bbkMaxColE18OutPerHour, uint256 _rctMaxFxsOutPerHour) external onlyByOwnGov {\r\n        bbkMaxColE18OutPerHour = _bbkMaxColE18OutPerHour;\r\n        rctMaxFxsOutPerHour = _rctMaxFxsOutPerHour;\r\n        emit BbkRctPerHourSet(_bbkMaxColE18OutPerHour, _rctMaxFxsOutPerHour);\r\n    }\r\n\r\n    // Set the Chainlink oracles\r\n    function setOracles(address _frax_usd_chainlink_addr, address _fxs_usd_chainlink_addr) external onlyByOwnGov {\r\n        // Set the instances\r\n        priceFeedFRAXUSD = AggregatorV3Interface(_frax_usd_chainlink_addr);\r\n        priceFeedFXSUSD = AggregatorV3Interface(_fxs_usd_chainlink_addr);\r\n\r\n        // Set the decimals\r\n        chainlink_frax_usd_decimals = priceFeedFRAXUSD.decimals();\r\n        chainlink_fxs_usd_decimals = priceFeedFXSUSD.decimals();\r\n        \r\n        emit OraclesSet(_frax_usd_chainlink_addr, _fxs_usd_chainlink_addr);\r\n    }\r\n\r\n    function setCustodian(address new_custodian) external onlyByOwnGov {\r\n        custodian_address = new_custodian;\r\n\r\n        emit CustodianSet(new_custodian);\r\n    }\r\n\r\n    function setTimelock(address new_timelock) external onlyByOwnGov {\r\n        timelock_address = new_timelock;\r\n\r\n        emit TimelockSet(new_timelock);\r\n    }\r\n\r\n    /* ========== EVENTS ========== */\r\n    event CollateralToggled(uint256 col_idx, bool new_state);\r\n    event PoolCeilingSet(uint256 col_idx, uint256 new_ceiling);\r\n    event FeesSet(uint256 col_idx, uint256 new_mint_fee, uint256 new_redeem_fee, uint256 new_buyback_fee, uint256 new_recollat_fee);\r\n    event PoolParametersSet(uint256 new_bonus_rate, uint256 new_redemption_delay);\r\n    event PriceThresholdsSet(uint256 new_bonus_rate, uint256 new_redemption_delay);\r\n    event BbkRctPerHourSet(uint256 bbkMaxColE18OutPerHour, uint256 rctMaxFxsOutPerHour);\r\n    event AMOMinterAdded(address amo_minter_addr);\r\n    event AMOMinterRemoved(address amo_minter_addr);\r\n    event OraclesSet(address frax_usd_chainlink_addr, address fxs_usd_chainlink_addr);\r\n    event CustodianSet(address new_custodian);\r\n    event TimelockSet(address new_timelock);\r\n    event MRBRToggled(uint256 col_idx, uint8 tog_idx);\r\n    event CollateralPriceSet(uint256 col_idx, uint256 new_price);\r\n}","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106103995760003560e01c806379ba5097116101e9578063be3449d41161010f578063e1d35b7a116100ad578063edb493e51161007c578063edb493e51461089c578063ee88fc91146108a4578063f4d93085146108ac578063ff9f4fb5146108b557600080fd5b8063e1d35b7a14610840578063e714df3114610860578063eb99aff814610869578063ecfd1a9e1461088957600080fd5b8063db1e5c9e116100e9578063db1e5c9e146107da578063dc6663c7146107fa578063dd7def731461081a578063df95c3a71461082d57600080fd5b8063be3449d414610794578063c76417d7146107a7578063cb668d02146107c757600080fd5b80639d202bf811610187578063b7db648211610156578063b7db648214610748578063b938af741461075b578063bbfadd6c1461076e578063bdacb3031461078157600080fd5b80639d202bf8146106da578063abae2c4c14610702578063aeaf4f0414610722578063af77bcbf1461073557600080fd5b806381f17467116101c357806381f174671461068a57806388e5a4911461069f5780638da5cb5b146106a75780639aae55a7146106c757600080fd5b806379ba50971461063f5780637ce6112b1461064757806380e74d971461066757600080fd5b8063403f3731116102ce57806353a47bb71161026c5780636283d27e1161023b5780636283d27e146105cb578063694677d3146105de5780637071dcb9146105fe5780637853c8881461062c57600080fd5b806353a47bb714610565578063572a93021461058557806358f45c3c146105985780635d447b31146105b857600080fd5b80634c26203c116102a85780634c26203c146105205780634c6349341461052957806350e82c7d14610532578063510641eb1461054557600080fd5b8063403f3731146104c7578063444f17dc146104da5780634bb4a7301461050d57600080fd5b80631fc9a9c21161033b578063310149da11610315578063310149da1461043b5780633323db1714610444578063350b5c64146104575780633a2b17a61461048257600080fd5b80631fc9a9c21461040d57806327803dce14610415578063308e31571461042857600080fd5b80631627540c116103775780631627540c146103d757806317284c94146103ea57806319949182146103f25780631b3fb85c1461040557600080fd5b806301728b5d1461039e57806304a66b48146103b957806315128425146103ce575b600080fd5b6103a66108be565b6040519081526020015b60405180910390f35b6103cc6103c73660046155e9565b6108d1565b005b6103a660175481565b6103cc6103e536600461546b565b610af3565b6103a6610c14565b6103cc61040036600461552c565b610cfc565b6103a6610de7565b6103a6610fe5565b6103a66104233660046154fc565b611250565b6103a66104363660046154fc565b611271565b6103a6601d5481565b6103cc61045236600461546b565b6113ab565b6103a66104653660046154b7565b601360209081526000928352604080842090915290825290205481565b6008546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103b0565b6103cc6104d536600461546b565b6114ca565b6104fd6104e836600461546b565b60066020526000908152604090205460ff1681565b60405190151581526020016103b0565b6104a261051b3660046154fc565b6115e0565b6103a660155481565b6103a660225481565b6103a661054036600461554d565b611617565b6103a66105533660046154fc565b601a6020526000908152604090205481565b6001546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6103cc610593366004615485565b611b5b565b6105ab6105a63660046154fc565b611dd4565b6040516103b0919061577d565b6103a66105c636600461552c565b611e80565b6103a66105d93660046154fc565b611f32565b6105f16105ec36600461546b565b611f42565b6040516103b09190615790565b61061161060c366004615578565b61255f565b604080519384526020840192909252908201526060016103b0565b6103cc61063a36600461552c565b612bcc565b6103cc612caf565b6003546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6104fd61067536600461546b565b60116020526000908152604090205460ff1681565b610692612dfa565b6040516103b09190615723565b6103a6612e69565b6000546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6103cc6106d53660046154fc565b612f2a565b6106ed6106e83660046154fc565b61308f565b604080519283526020830191909152016103b0565b6103a661071036600461546b565b60166020526000908152604090205481565b6103cc6107303660046154fc565b6133a1565b6103cc61074336600461552c565b61351d565b6106ed6107563660046155b8565b613643565b6103a66107693660046154fc565b613f10565b6103cc61077c366004615623565b613f20565b6103cc61078f36600461546b565b6142f5565b6103a66107a236600461554d565b61440b565b6103a66107b536600461546b565b60126020526000908152604090205481565b6103cc6107d536600461546b565b614946565b6103a66107e836600461546b565b60106020526000908152604090205481565b6002546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6103a66108283660046154fc565b614b68565b6103cc61083b36600461552c565b614b78565b6103a661084e3660046154fc565b601c6020526000908152604090205481565b6103a660195481565b6007546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6103cc61089736600461552c565b614c5b565b6103a6614d81565b6103a6614ddb565b6103a6601b5481565b6103a660185481565b60006108cc610e10426158b2565b905090565b60025473ffffffffffffffffffffffffffffffffffffffff1633148061090e575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610979576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b000000000000000000000060448201526064015b60405180910390fd5b83601e86815481106109b4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020018190555082601f86815481106109fd577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508160208681548110610a46577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508060218681548110610a8f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000918252602091829020019190915560408051878152918201869052810184905260608101839052608081018290527f8a2460aa8ca12123c8d9fb3e2835543ba312bc12b99cc8a934c213f17cc23ba09060a00160405180910390a15050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610970565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020015b60405180910390a150565b6000805b600b54811015610cf857610cda620f4240610cd4600f8481548110610c66577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154610cce600d8681548110610cae577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600a610cc5919061594c565b610cce87611271565b90614ed8565b90614f8d565b610ce4908361589a565b915080610cf081615aea565b915050610c18565b5090565b60025473ffffffffffffffffffffffffffffffffffffffff16331480610d39575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610d9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b601b829055601d81905560408051838152602081018390527f78814d12e3d8697f77c618abed8124ead9c9ec6d16952ee98a11c8dc2968d3c491015b60405180910390a15050565b60048054604080517f18160ddd0000000000000000000000000000000000000000000000000000000081529051600093849373ffffffffffffffffffffffffffffffffffffffff16926318160ddd9281830192602092829003018186803b158015610e5157600080fd5b505afa158015610e65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e899190615514565b90506000610f3882610cd4620f4240600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d2d97b066040518163ffffffff1660e01b815260040160206040518083038186803b158015610f0057600080fd5b505afa158015610f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cce9190615514565b60048054604080517f2eb9771b0000000000000000000000000000000000000000000000000000000081529051939450600093610fa993879373ffffffffffffffffffffffffffffffffffffffff1692632eb9771b9281830192602092829003018186803b158015610f0057600080fd5b90506000610fb78385614ed8565b9050818110610fcb57600094505050505090565b610fdc620f4240610cd48484614e96565b94505050505090565b60048054604080517f18160ddd0000000000000000000000000000000000000000000000000000000081529051600093849373ffffffffffffffffffffffffffffffffffffffff16926318160ddd9281830192602092829003018186803b15801561104f57600080fd5b505afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110879190615514565b90506000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110f357600080fd5b505afa158015611107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112b9190615514565b90506000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d2d97b066040518163ffffffff1660e01b815260040160206040518083038186803b15801561119757600080fd5b505afa1580156111ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111cf9190615514565b9050620f42408211156111e357620f424091505b60006111f6620f4240610cd48686614ed8565b90508082111561124557600061120c8383614e96565b90506000601a600061121c6108be565b815260200190815260200160002054905061123a81601b5484614fcf565b965050505050505090565b600094505050505090565b600e818154811061126057600080fd5b600091825260209091200154905081565b60006113a5601483815481106112b0577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600b84815481106112f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a082319060240160206040518083038186803b15801561136757600080fd5b505afa15801561137b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139f9190615514565b90614e96565b92915050565b60025473ffffffffffffffffffffffffffffffffffffffff163314806113e8575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61144e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b73ffffffffffffffffffffffffffffffffffffffff811660008181526006602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905590519182527f441e2ac704708a511e1dccaf842773b65f3928094ff084b1c90e0572db4352609101610c09565b60025473ffffffffffffffffffffffffffffffffffffffff16331480611507575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61156d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fb88c20a211c5d7677ba2a26c317d8ae6b25aa492016dc8ceca2469761d063d8090602001610c09565b600b81815481106115f057600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60008360116000600b8381548110611658577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff166116f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610970565b6025858154811061172d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a900416156117b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5265636f6c6c61742069732070617573656400000000000000000000000000006044820152606401610970565b6000600d86815481106117f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600a611807919061594c565b6118119086615a12565b9050600061181d612e69565b90506000611829614d81565b905061189982610cd461189260218c8154811061186f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015461139f602254620f424061500590919063ffffffff16565b8690614ed8565b945080851115611905576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e7375662046585320417661696c20466f72205243540000000000000000006044820152606401610970565b8585101561196f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f46585320736c69707061676500000000000000000000000000000000000000006044820152606401610970565b600e88815481106119a9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001546119c7886119c18b611271565b90615005565b1115611a2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f506f6f6c206365696c696e6700000000000000000000000000000000000000006044820152606401610970565b611a96600b8981548110611a6c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633308a61507e565b6005546040517fb4f56b260000000000000000000000000000000000000000000000000000000081523360048201526024810187905273ffffffffffffffffffffffffffffffffffffffff9091169063b4f56b2690604401600060405180830381600087803b158015611b0857600080fd5b505af1158015611b1c573d6000803e3d6000fd5b5050505084601c6000611b2d6108be565b81526020019081526020016000206000828254611b4a919061589a565b909155509498975050505050505050565b60025473ffffffffffffffffffffffffffffffffffffffff16331480611b98575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611bfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b6007805473ffffffffffffffffffffffffffffffffffffffff8085167fffffffffffffffffffffffff000000000000000000000000000000000000000092831681179093556008805491851691909216179055604080517f313ce567000000000000000000000000000000000000000000000000000000008152905163313ce56791600480820192602092909190829003018186803b158015611ca057600080fd5b505afa158015611cb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd891906156a1565b60ff16600955600854604080517f313ce567000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163313ce56791600480820192602092909190829003018186803b158015611d4957600080fd5b505afa158015611d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8191906156a1565b60ff16600a556040805173ffffffffffffffffffffffffffffffffffffffff8085168252831660208201527f4073b32a832187a54e475fc8fff20266eedffb63596adf4c0b8a2966e2b0025d9101610ddb565b600c8181548110611de457600080fd5b906000526020600020016000915090508054611dff90615a96565b80601f0160208091040260200160405190810160405280929190818152602001828054611e2b90615a96565b8015611e785780601f10611e4d57610100808354040283529160200191611e78565b820191906000526020600020905b815481529060010190602001808311611e5b57829003601f168201915b505050505081565b6000611f2b600f8481548110611ebf577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154610cd4600d8681548110611f07577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600a611f1e919061594c565b610cd486620f4240614ed8565b9392505050565b600d818154811061126057600080fd5b611fdb604051806101e001604052806000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001600081526020016000815260200160008152602001600015158152602001600015158152602001600015158152602001600015158152602001600081526020016000815260200160008152602001600081525090565b73ffffffffffffffffffffffffffffffffffffffff821660009081526011602052604090205460ff1661206a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e76616c696420636f6c6c61746572616c00000000000000000000000000006044820152606401610970565b6000601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050604051806101e00160405280828152602001600c83815481106120fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001805461210f90615a96565b80601f016020809104026020016040519081016040528092919081815260200182805461213b90615a96565b80156121885780601f1061215d57610100808354040283529160200191612188565b820191906000526020600020905b81548152906001019060200180831161216b57829003601f168201915b505050918352505073ffffffffffffffffffffffffffffffffffffffff851660208083018290526000918252601190526040908190205460ff16151590820152600d805460609092019184908110612209577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001600f8381548110612253577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001600e838154811061229d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001602383815481106122e7577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161515815260200160248381548110612348577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff1615158152602001602583815481106123a9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff16151581526020016026838154811061240a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff1615158152602001601e838154811061246b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001601f83815481106124b5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001602083815481106124ff577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154815260200160218381548110612549577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154815250915050919050565b60008060008660116000600b83815481106125a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff1661263e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610970565b60238881548110612678577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a900416156126ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4d696e74696e67206973207061757365640000000000000000000000000000006044820152606401610970565b60195461270a614ddb565b1015612772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4672617820707269636520746f6f206c6f7700000000000000000000000000006044820152606401610970565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127dc57600080fd5b505afa1580156127f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128149190615514565b905085806128255750620f42408110155b1561283f576128348989611e80565b9350600092506128b3565b806128675760009350612860612853612e69565b610cd48a620f4240614ed8565b92506128b3565b600061287a620f4240610cd48b85614ed8565b905060006128888a83614e96565b90506128948b83611e80565b95506128ae6128a1612e69565b610cd483620f4240614ed8565b945050505b61291e620f4240610cd4612917601e8d815481106128fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154620f4240614e9690919063ffffffff16565b8b90614ed8565b94508487111561298a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4652415820736c697070616765000000000000000000000000000000000000006044820152606401610970565b600e89815481106129c4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001546129dc856119c18c611271565b1115612a44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f506f6f6c206365696c696e6700000000000000000000000000000000000000006044820152606401610970565b6005546040517fa8a778ae0000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff9091169063a8a778ae90604401600060405180830381600087803b158015612ab657600080fd5b505af1158015612aca573d6000803e3d6000fd5b50505050612b35600b8a81548110612b0b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633308761507e565b600480546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815233928101929092526024820187905273ffffffffffffffffffffffffffffffffffffffff169063b4f56b2690604401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b5050505050509450945094915050565b60025473ffffffffffffffffffffffffffffffffffffffff16331480612c09575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612c6f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b6019829055601881905560408051838152602081018390527f08f944f25b910c541435bcde52d233072e903b37afc29bc8b5787b6e74d82c1a9101610ddb565b60015473ffffffffffffffffffffffffffffffffffffffff163314612d56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610970565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6060600b805480602002602001604051908101604052809291908181526020018280548015612e5f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612e34575b5050505050905090565b600080600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015612ed457600080fd5b505afa158015612ee8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f0c9190615652565b505050915050612f24600a54600a6128a1919061594c565b91505090565b3360009081526006602052604090205460ff16612fa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e6f7420616e20414d4f204d696e7465720000000000000000000000000000006044820152606401610970565b60003373ffffffffffffffffffffffffffffffffffffffff16638b4433966040518163ffffffff1660e01b815260040160206040518083038186803b158015612feb57600080fd5b505afa158015612fff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130239190615514565b905061308b600b8281548110613062577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16338461521c565b5050565b600080602483815481106130cc577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a90041615613153576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f52656465656d696e6720697320706175736564000000000000000000000000006044820152606401610970565b6017543360009081526016602052604090205443916131729190615005565b11156131da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f546f6f20736f6f6e0000000000000000000000000000000000000000000000006044820152606401610970565b3360009081526012602052604081205481901561321d5733600090815260126020526040812080549190556015549094506132159085614e96565b601555600191505b336000908152601360209081526040808320888452909152902054156133045733600090815260136020908152604080832088845290915281208054919055601480549194506132ba91859190889081106132a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154614e9690919063ffffffff16565b601486815481106132f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000918252602090912001555060015b811561332e5760055461332e9073ffffffffffffffffffffffffffffffffffffffff16338661521c565b801561339a5761339a600b8681548110613371577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16338561521c565b5050915091565b60025473ffffffffffffffffffffffffffffffffffffffff163314806133de575060005473ffffffffffffffffffffffffffffffffffffffff1633145b613444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b6000600b8281548110613480577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff1680835260118252604092839020805460ff808216157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921682179092558451878152911615159281019290925292507f088e9476d8b4139e22c8e66b078291edda3cd924ce0b0e7193f2a38e293e70ee9101610ddb565b60025473ffffffffffffffffffffffffffffffffffffffff1633148061355a575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6135c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b80600f83815481106135fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055507f16374e3dc228b497b5a9b2dff5883c395120625fbe7e794fdcc5d305ce13ed078282604051610ddb929190918252602082015260400190565b6000808560116000600b8381548110613685577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff16613720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610970565b6024878154811061375a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a900416156137e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f52656465656d696e6720697320706175736564000000000000000000000000006044820152606401610970565b6018546137ec614ddb565b1115613854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4672617820707269636520746f6f2068696768000000000000000000000000006044820152606401610970565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156138be57600080fd5b505afa1580156138d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f69190615514565b90506000613941620f4240610cd4612917601f8d815481106128fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9050620f42408210613a0e57613a03600d8a8154811061398a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015460066139a1919061589a565b6139ac90600a61594c565b610cd4600f8c815481106139e9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015484614ed890919063ffffffff16565b945060009350613b02565b81613a2957613a1e6128a1612e69565b935060009450613b02565b613adb600d8a81548110613a66577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600c613a7d919061589a565b613a8890600a61594c565b610cd4600f8c81548110613ac5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260209091200154610cce8587614ed8565b9450613aff613ae8612e69565b610cd4613af8620f424086614e96565b8490614ed8565b93505b613b8460148a81548110613b3f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600b8b815481106112f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b851115613bed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f496e73756666696369656e7420706f6f6c20636f6c6c61746572616c000000006044820152606401610970565b85851015613c57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c20736c697070616765000000000000000000000000006044820152606401610970565b86841015613cc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f46585320736c69707061676500000000000000000000000000000000000000006044820152606401610970565b3360009081526013602090815260408083208c8452909152902054613ce69086615005565b3360009081526013602090815260408083208d845290915290205560148054613d5b9187918c908110613d42577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015461500590919063ffffffff16565b60148a81548110613d95577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091019290925533815260129091526040902054613dbd9085615005565b33600090815260126020526040902055601554613dda9085615005565b60155533600081815260166020526040908190204390556004805491517fa8a778ae00000000000000000000000000000000000000000000000000000000815290810192909252602482018a905273ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b158015613e6257600080fd5b505af1158015613e76573d6000803e3d6000fd5b50506005546040517fb4f56b260000000000000000000000000000000000000000000000000000000081523060048201526024810188905273ffffffffffffffffffffffffffffffffffffffff909116925063b4f56b269150604401600060405180830381600087803b158015613eec57600080fd5b505af1158015613f00573d6000803e3d6000fd5b5050505050505094509492505050565b6014818154811061126057600080fd5b60025473ffffffffffffffffffffffffffffffffffffffff16331480613f5d575060005473ffffffffffffffffffffffffffffffffffffffff1633145b80613f7f575060035473ffffffffffffffffffffffffffffffffffffffff1633145b613fe5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4e6f74206f776e65722c20746c636b2c206f72206375737464000000000000006044820152606401610970565b60ff81166140b05760238281548110614027577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161560238381548110614082577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190066101000a81548160ff0219169083151502179055506142bd565b8060ff166001141561415157602482815481106140f6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161560248381548110614082577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8060ff16600214156141f25760268281548110614197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161560268381548110614082577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8060ff16600314156142bd5760258281548110614238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161560258381548110614293577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190066101000a81548160ff0219169083151502179055505b6040805183815260ff831660208201527f3dbf640f58ea22aec5eb07b21b1a899b95d63fffcf6050292ee91a1ad5576a2e9101610ddb565b60025473ffffffffffffffffffffffffffffffffffffffff16331480614332575060005473ffffffffffffffffffffffffffffffffffffffff1633145b614398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f7e7ee4175d63f671fac3401d5f401ed18d1f48a586e756f404d5696fc77a705890602001610c09565b60008360116000600b838154811061444c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff166144e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610970565b60268581548110614521577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a900416156145a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4275796261636b206973207061757365640000000000000000000000000000006044820152606401610970565b60006145b2612e69565b905060006145be610fe5565b90506000811161462a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e73756620436f6c6c617420417661696c20466f722042424b0000000000006044820152606401610970565b600061463d620f4240610cd48986614ed8565b9050818111156146a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e73756620436f6c6c617420417661696c20466f722042424b0000000000006044820152606401610970565b6000614701600f8a815481106146e8577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260209091200154610cd484620f4240614ed8565b905061475e600d8a81548110614740577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600a614757919061594c565b8290614f8d565b95506147ae620f4240610cd46147a760208d815481106128fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8990614ed8565b95508686101561481a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c20736c697070616765000000000000000000000000006044820152606401610970565b6005546040517fa8a778ae000000000000000000000000000000000000000000000000000000008152336004820152602481018a905273ffffffffffffffffffffffffffffffffffffffff9091169063a8a778ae90604401600060405180830381600087803b15801561488c57600080fd5b505af11580156148a0573d6000803e3d6000fd5b5050505061490a600b8a815481106148e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16338861521c565b80601a60006149176108be565b81526020019081526020016000206000828254614934919061589a565b90915550959998505050505050505050565b60025473ffffffffffffffffffffffffffffffffffffffff16331480614983575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6149e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b73ffffffffffffffffffffffffffffffffffffffff8116614a66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610970565b60008173ffffffffffffffffffffffffffffffffffffffff166317284c946040518163ffffffff1660e01b815260040160206040518083038186803b158015614aae57600080fd5b505afa158015614ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ae69190615514565b73ffffffffffffffffffffffffffffffffffffffff831660008181526006602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590519182529192507f15db44a176b13a69368dde2d5ada5960b7025d8946d346c14e6ec5e5ce3fdba49101610ddb565b600f818154811061126057600080fd5b60025473ffffffffffffffffffffffffffffffffffffffff16331480614bb5575060005473ffffffffffffffffffffffffffffffffffffffff1633145b614c1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b6022829055601781905560408051838152602081018390527f03cd02afb025e556dd4cb5ab56c7de3b05bb254aa76ee6bd499f6d8a011a14489101610ddb565b60025473ffffffffffffffffffffffffffffffffffffffff16331480614c98575060005473ffffffffffffffffffffffffffffffffffffffff1633145b614cfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b80600e8381548110614d39577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055507f4cb99f07bf9ab5f864d81d791709058819f4188481fb3c70b90a1765e003b16e8282604051610ddb929190918252602082015260400190565b600080614d8c612e69565b90506000614d98610de7565b90506000614dad83610cd484620f4240614ed8565b90506000601c6000614dbd6108be565b8152602001908152602001600020549050610fdc81601d5484614fcf565b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015614e4657600080fd5b505afa158015614e5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e7e9190615652565b505050915050612f24600954600a6128a1919061594c565b6000611f2b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061538c565b600082614ee7575060006113a5565b6000614ef38385615a12565b905082614f0085836158b2565b14611f2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60448201527f77000000000000000000000000000000000000000000000000000000000000006064820152608401610970565b6000611f2b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506153e0565b6000828410614fe057506000611f2b565b6000614fec8486614e96565b9050808310614ffc579050611f2b565b50909392505050565b600080615012838561589a565b905083811015611f2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610970565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161511d9190615707565b6000604051808303816000865af19150503d806000811461515a576040519150601f19603f3d011682016040523d82523d6000602084013e61515f565b606091505b509150915081801561518957508051158061518957508080602001905181019061518991906154e0565b615214576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610970565b505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916152b39190615707565b6000604051808303816000865af19150503d80600081146152f0576040519150601f19603f3d011682016040523d82523d6000602084013e6152f5565b606091505b509150915081801561531f57508051158061531f57508080602001905181019061531f91906154e0565b615385576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610970565b5050505050565b600081848411156153ca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610970919061577d565b5060006153d78486615a4f565b95945050505050565b6000818361541b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610970919061577d565b5060006153d784866158b2565b803573ffffffffffffffffffffffffffffffffffffffff8116811461544c57600080fd5b919050565b805169ffffffffffffffffffff8116811461544c57600080fd5b60006020828403121561547c578081fd5b611f2b82615428565b60008060408385031215615497578081fd5b6154a083615428565b91506154ae60208401615428565b90509250929050565b600080604083850312156154c9578182fd5b6154d283615428565b946020939093013593505050565b6000602082840312156154f1578081fd5b8151611f2b81615b52565b60006020828403121561550d578081fd5b5035919050565b600060208284031215615525578081fd5b5051919050565b6000806040838503121561553e578182fd5b50508035926020909101359150565b600080600060608486031215615561578081fd5b505081359360208301359350604090920135919050565b6000806000806080858703121561558d578081fd5b84359350602085013592506040850135915060608501356155ad81615b52565b939692955090935050565b600080600080608085870312156155cd578384fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a08688031215615600578081fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215615635578182fd5b82359150602083013561564781615b63565b809150509250929050565b600080600080600060a08688031215615669578283fd5b61567286615451565b945060208601519350604086015192506060860151915061569560808701615451565b90509295509295909350565b6000602082840312156156b2578081fd5b8151611f2b81615b63565b600081518084526156d5816020860160208601615a66565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008251615719818460208701615a66565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b8181101561577157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161573f565b50909695505050505050565b602081526000611f2b60208301846156bd565b6020815281516020820152600060208301516101e08060408501526157b96102008501836156bd565b915060408501516157e2606086018273ffffffffffffffffffffffffffffffffffffffff169052565b506060850151801515608086015250608085015160a085015260a085015160c085015260c085015160e085015260e08501516101006158248187018315159052565b86015190506101206158398682018315159052565b860151905061014061584e8682018315159052565b86015190506101606158638682018315159052565b860151610180868101919091528601516101a0808701919091528601516101c0808701919091529095015193019290925250919050565b600082198211156158ad576158ad615b23565b500190565b6000826158e6577f4e487b710000000000000000000000000000000000000000000000000000000081526012600452602481fd5b500490565b600181815b8085111561594457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561592a5761592a615b23565b8085161561593757918102915b93841c93908002906158f0565b509250929050565b6000611f2b8383600082615962575060016113a5565b8161596f575060006113a5565b8160018114615985576002811461598f576159ab565b60019150506113a5565b60ff8411156159a0576159a0615b23565b50506001821b6113a5565b5060208310610133831016604e8410600b84101617156159ce575081810a6113a5565b6159d883836158eb565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a0a57615a0a615b23565b029392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a4a57615a4a615b23565b500290565b600082821015615a6157615a61615b23565b500390565b60005b83811015615a81578181015183820152602001615a69565b83811115615a90576000848401525b50505050565b600181811c90821680615aaa57607f821691505b60208210811415615ae4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615b1c57615b1c615b23565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8015158114615b6057600080fd5b50565b60ff81168114615b6057600080fdfea264697066735822122093a59cf8fdd8f1ed30f01182bb6491821d023dbe30666b3076cad1c38014a72c64736f6c63430008040033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":100000},"remappings":[]},"optimization_runs":100000,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/partial_match/1/0x2fE065e6FFEf9ac95ab39E5042744d695F560729/","decoded_constructor_args":[["0xb39e2041b042f39b8572B6F84dEba99BbB589c8d",{"internalType":"address","name":"_pool_manager_address","type":"address"}],["0x234D953a9404Bf9DbC3b526271d440cD2870bCd2",{"internalType":"address","name":"_custodian_address","type":"address"}],["0x8412ebf45bAC1B340BbE8F318b928C466c4E39CA",{"internalType":"address","name":"_timelock_address","type":"address"}],[["0x5f98805A4E8be255a32880FDeC7F6728C6568bA0","0x57Ab1ec28D129707052df4dF418D58a2D46d5f51","0x1456688345527bE1f37E9e627DA0837D6f08C925","0x6B175474E89094C44Da98b954EedeAC495271d0F","0x956F47F50A910163D8BF957Cf5846D573E7f87CA","0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"],{"internalType":"address[]","name":"_collateral_addresses","type":"address[]"}],[["50000000000000000000000","50000000000000000000000","50000000000000000000000","50000000000000000000000","50000000000000000000000","50000000000"],{"internalType":"uint256[]","name":"_pool_ceilings","type":"uint256[]"}],[["3000","5500","6000","6000"],{"internalType":"uint256[]","name":"_initial_fees","type":"uint256[]"}]],"compiler_version":"0.8.4+commit.c7e474f2","is_verified_via_verifier_alliance":false,"verified_at":"2024-08-06T19:00:40.201790Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6080604052600480546001600160a01b031990811673853d955acef822db058eb8505911ed77f175b99e17909155600580548216733432b6a60d23ca0dfca7761b7ab56459d9c964d017905560078054821673b9e1e3a9feff48998e45fa90847ed4d467e8bcfd17905560088054909116736ebc52c8c1089be9eb3945c4350b68b8e4c2233f1790556002601755620f1b30601855620f6950601955683635c9adc5dea00000601b819055601d55348015620000ba57600080fd5b506040516200697f3803806200697f833981016040819052620000dd9162000a79565b856001600160a01b0381166200013a5760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f7420626520300000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a150600280546001600160a01b038087166001600160a01b03199283161790925560038054928816929091169190911790558251620001d790600b906020860190620008aa565b5060005b8351811015620006df5780601060008684815181106200020b57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055506000601160008684815181106200025e57634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff021916908315150217905550600d62000359858381518110620002c457634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156200030557600080fd5b505afa1580156200031a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000340919062000c42565b60ff1660126200081a60201b62004e961790919060201c565b815460018101835560009283526020909220909101558351600c908590839081106200039557634e487b7160e01b600052603260045260246000fd5b60200260200101516001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015620003d657600080fd5b505afa158015620003eb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000415919081019062000ba8565b8154600181018355600092835260209283902082516200043c949190920192019062000914565b5060148054600181810190925560007fce6d7b5282bd9a3661ae061feed1dbda4e52ab073b1f9285be6e155d9c38d4ec909101819055600f805492830181558152620f42407f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac802909201919091558251601e918491620004cb57634e487b7160e01b600052603260045260246000fd5b602090810291909101810151825460018181018555600094855292909320909201919091558251601f91849181106200051457634e487b7160e01b600052603260045260246000fd5b6020908102919091018101518254600181018455600093845292829020909201919091558251839060029081106200055c57634e487b7160e01b600052603260045260246000fd5b60209081029190910181015182546001810184556000938452919092200155815160219083906003908110620005a257634e487b7160e01b600052603260045260246000fd5b602090810291909101810151825460018181018555600094855283852090910191909155602380548083019091558281047fd57b2b5166478fd4318d2acc6cc2c704584312bdd8781b32d5d06abda57f423001805460ff601f93841661010090810a820219909216909255602480548086019091558581047f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec4018054918516830a8402199091169055602580548086019091558581047f401968ff42a154441da5f6c4c935ac46b8671f0e062baaa62a7545ba53bb6e4c018054918516830a84021990911690556026805494850181559095529282047f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a35940180549290911690930a9091021916905580620006d68162000d7d565b915050620001db565b508151620006f590600e90602085019062000991565b50600760009054906101000a90046001600160a01b03166001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156200074557600080fd5b505afa1580156200075a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000780919062000c42565b60ff166009556008546040805163313ce56760e01b815290516001600160a01b039092169163313ce56791600480820192602092909190829003018186803b158015620007cc57600080fd5b505afa158015620007e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000807919062000c42565b60ff16600a555062000dc7945050505050565b60006200086483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506200086b60201b60201c565b9392505050565b60008184841115620008925760405162461bcd60e51b815260040162000131919062000c65565b506000620008a1848662000cf3565b95945050505050565b82805482825590600052602060002090810192821562000902579160200282015b828111156200090257825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190620008cb565b5062000910929150620009ce565b5090565b828054620009229062000d40565b90600052602060002090601f01602090048101928262000946576000855562000902565b82601f106200096157805160ff191683800117855562000902565b8280016001018555821562000902579182015b828111156200090257825182559160200191906001019062000974565b8280548282559060005260206000209081019282156200090257916020028201828111156200090257825182559160200191906001019062000974565b5b80821115620009105760008155600101620009cf565b80516001600160a01b0381168114620009fd57600080fd5b919050565b600082601f83011262000a13578081fd5b8151602062000a2c62000a268362000ccd565b62000c9a565b80838252828201915082860187848660051b890101111562000a4c578586fd5b855b8581101562000a6c5781518452928401929084019060010162000a4e565b5090979650505050505050565b60008060008060008060c0878903121562000a92578182fd5b62000a9d87620009e5565b9550602062000aae818901620009e5565b955062000abe60408901620009e5565b60608901519095506001600160401b038082111562000adb578485fd5b818a0191508a601f83011262000aef578485fd5b815162000b0062000a268262000ccd565b8082825285820191508585018e878560051b880101111562000b20578889fd5b8895505b8386101562000b4d5762000b3881620009e5565b83526001959095019491860191860162000b24565b5060808d0151909850945050508083111562000b67578485fd5b62000b758b848c0162000a02565b945060a08a015192508083111562000b8b578384fd5b505062000b9b89828a0162000a02565b9150509295509295509295565b60006020828403121562000bba578081fd5b81516001600160401b038082111562000bd1578283fd5b818401915084601f83011262000be5578283fd5b81518181111562000bfa5762000bfa62000db1565b62000c0f601f8201601f191660200162000c9a565b915080825285602082850101111562000c26578384fd5b62000c3981602084016020860162000d0d565b50949350505050565b60006020828403121562000c54578081fd5b815160ff8116811462000864578182fd5b602081526000825180602084015262000c8681604085016020870162000d0d565b601f01601f19169190910160400192915050565b604051601f8201601f191681016001600160401b038111828210171562000cc55762000cc562000db1565b604052919050565b60006001600160401b0382111562000ce95762000ce962000db1565b5060051b60200190565b60008282101562000d085762000d0862000d9b565b500390565b60005b8381101562000d2a57818101518382015260200162000d10565b8381111562000d3a576000848401525b50505050565b600181811c9082168062000d5557607f821691505b6020821081141562000d7757634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141562000d945762000d9462000d9b565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b615ba88062000dd76000396000f3fe608060405234801561001057600080fd5b50600436106103995760003560e01c806379ba5097116101e9578063be3449d41161010f578063e1d35b7a116100ad578063edb493e51161007c578063edb493e51461089c578063ee88fc91146108a4578063f4d93085146108ac578063ff9f4fb5146108b557600080fd5b8063e1d35b7a14610840578063e714df3114610860578063eb99aff814610869578063ecfd1a9e1461088957600080fd5b8063db1e5c9e116100e9578063db1e5c9e146107da578063dc6663c7146107fa578063dd7def731461081a578063df95c3a71461082d57600080fd5b8063be3449d414610794578063c76417d7146107a7578063cb668d02146107c757600080fd5b80639d202bf811610187578063b7db648211610156578063b7db648214610748578063b938af741461075b578063bbfadd6c1461076e578063bdacb3031461078157600080fd5b80639d202bf8146106da578063abae2c4c14610702578063aeaf4f0414610722578063af77bcbf1461073557600080fd5b806381f17467116101c357806381f174671461068a57806388e5a4911461069f5780638da5cb5b146106a75780639aae55a7146106c757600080fd5b806379ba50971461063f5780637ce6112b1461064757806380e74d971461066757600080fd5b8063403f3731116102ce57806353a47bb71161026c5780636283d27e1161023b5780636283d27e146105cb578063694677d3146105de5780637071dcb9146105fe5780637853c8881461062c57600080fd5b806353a47bb714610565578063572a93021461058557806358f45c3c146105985780635d447b31146105b857600080fd5b80634c26203c116102a85780634c26203c146105205780634c6349341461052957806350e82c7d14610532578063510641eb1461054557600080fd5b8063403f3731146104c7578063444f17dc146104da5780634bb4a7301461050d57600080fd5b80631fc9a9c21161033b578063310149da11610315578063310149da1461043b5780633323db1714610444578063350b5c64146104575780633a2b17a61461048257600080fd5b80631fc9a9c21461040d57806327803dce14610415578063308e31571461042857600080fd5b80631627540c116103775780631627540c146103d757806317284c94146103ea57806319949182146103f25780631b3fb85c1461040557600080fd5b806301728b5d1461039e57806304a66b48146103b957806315128425146103ce575b600080fd5b6103a66108be565b6040519081526020015b60405180910390f35b6103cc6103c73660046155e9565b6108d1565b005b6103a660175481565b6103cc6103e536600461546b565b610af3565b6103a6610c14565b6103cc61040036600461552c565b610cfc565b6103a6610de7565b6103a6610fe5565b6103a66104233660046154fc565b611250565b6103a66104363660046154fc565b611271565b6103a6601d5481565b6103cc61045236600461546b565b6113ab565b6103a66104653660046154b7565b601360209081526000928352604080842090915290825290205481565b6008546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103b0565b6103cc6104d536600461546b565b6114ca565b6104fd6104e836600461546b565b60066020526000908152604090205460ff1681565b60405190151581526020016103b0565b6104a261051b3660046154fc565b6115e0565b6103a660155481565b6103a660225481565b6103a661054036600461554d565b611617565b6103a66105533660046154fc565b601a6020526000908152604090205481565b6001546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6103cc610593366004615485565b611b5b565b6105ab6105a63660046154fc565b611dd4565b6040516103b0919061577d565b6103a66105c636600461552c565b611e80565b6103a66105d93660046154fc565b611f32565b6105f16105ec36600461546b565b611f42565b6040516103b09190615790565b61061161060c366004615578565b61255f565b604080519384526020840192909252908201526060016103b0565b6103cc61063a36600461552c565b612bcc565b6103cc612caf565b6003546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6104fd61067536600461546b565b60116020526000908152604090205460ff1681565b610692612dfa565b6040516103b09190615723565b6103a6612e69565b6000546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6103cc6106d53660046154fc565b612f2a565b6106ed6106e83660046154fc565b61308f565b604080519283526020830191909152016103b0565b6103a661071036600461546b565b60166020526000908152604090205481565b6103cc6107303660046154fc565b6133a1565b6103cc61074336600461552c565b61351d565b6106ed6107563660046155b8565b613643565b6103a66107693660046154fc565b613f10565b6103cc61077c366004615623565b613f20565b6103cc61078f36600461546b565b6142f5565b6103a66107a236600461554d565b61440b565b6103a66107b536600461546b565b60126020526000908152604090205481565b6103cc6107d536600461546b565b614946565b6103a66107e836600461546b565b60106020526000908152604090205481565b6002546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6103a66108283660046154fc565b614b68565b6103cc61083b36600461552c565b614b78565b6103a661084e3660046154fc565b601c6020526000908152604090205481565b6103a660195481565b6007546104a29073ffffffffffffffffffffffffffffffffffffffff1681565b6103cc61089736600461552c565b614c5b565b6103a6614d81565b6103a6614ddb565b6103a6601b5481565b6103a660185481565b60006108cc610e10426158b2565b905090565b60025473ffffffffffffffffffffffffffffffffffffffff1633148061090e575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610979576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b000000000000000000000060448201526064015b60405180910390fd5b83601e86815481106109b4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020018190555082601f86815481106109fd577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508160208681548110610a46577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508060218681548110610a8f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000918252602091829020019190915560408051878152918201869052810184905260608101839052608081018290527f8a2460aa8ca12123c8d9fb3e2835543ba312bc12b99cc8a934c213f17cc23ba09060a00160405180910390a15050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e00000000000000000000000000000000006064820152608401610970565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22906020015b60405180910390a150565b6000805b600b54811015610cf857610cda620f4240610cd4600f8481548110610c66577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154610cce600d8681548110610cae577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600a610cc5919061594c565b610cce87611271565b90614ed8565b90614f8d565b610ce4908361589a565b915080610cf081615aea565b915050610c18565b5090565b60025473ffffffffffffffffffffffffffffffffffffffff16331480610d39575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610d9f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b601b829055601d81905560408051838152602081018390527f78814d12e3d8697f77c618abed8124ead9c9ec6d16952ee98a11c8dc2968d3c491015b60405180910390a15050565b60048054604080517f18160ddd0000000000000000000000000000000000000000000000000000000081529051600093849373ffffffffffffffffffffffffffffffffffffffff16926318160ddd9281830192602092829003018186803b158015610e5157600080fd5b505afa158015610e65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e899190615514565b90506000610f3882610cd4620f4240600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d2d97b066040518163ffffffff1660e01b815260040160206040518083038186803b158015610f0057600080fd5b505afa158015610f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cce9190615514565b60048054604080517f2eb9771b0000000000000000000000000000000000000000000000000000000081529051939450600093610fa993879373ffffffffffffffffffffffffffffffffffffffff1692632eb9771b9281830192602092829003018186803b158015610f0057600080fd5b90506000610fb78385614ed8565b9050818110610fcb57600094505050505090565b610fdc620f4240610cd48484614e96565b94505050505090565b60048054604080517f18160ddd0000000000000000000000000000000000000000000000000000000081529051600093849373ffffffffffffffffffffffffffffffffffffffff16926318160ddd9281830192602092829003018186803b15801561104f57600080fd5b505afa158015611063573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110879190615514565b90506000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110f357600080fd5b505afa158015611107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061112b9190615514565b90506000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d2d97b066040518163ffffffff1660e01b815260040160206040518083038186803b15801561119757600080fd5b505afa1580156111ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111cf9190615514565b9050620f42408211156111e357620f424091505b60006111f6620f4240610cd48686614ed8565b90508082111561124557600061120c8383614e96565b90506000601a600061121c6108be565b815260200190815260200160002054905061123a81601b5484614fcf565b965050505050505090565b600094505050505090565b600e818154811061126057600080fd5b600091825260209091200154905081565b60006113a5601483815481106112b0577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600b84815481106112f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000918252602090912001546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff909116906370a082319060240160206040518083038186803b15801561136757600080fd5b505afa15801561137b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139f9190615514565b90614e96565b92915050565b60025473ffffffffffffffffffffffffffffffffffffffff163314806113e8575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61144e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b73ffffffffffffffffffffffffffffffffffffffff811660008181526006602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905590519182527f441e2ac704708a511e1dccaf842773b65f3928094ff084b1c90e0572db4352609101610c09565b60025473ffffffffffffffffffffffffffffffffffffffff16331480611507575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61156d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b600380547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fb88c20a211c5d7677ba2a26c317d8ae6b25aa492016dc8ceca2469761d063d8090602001610c09565b600b81815481106115f057600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60008360116000600b8381548110611658577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff166116f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610970565b6025858154811061172d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a900416156117b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f5265636f6c6c61742069732070617573656400000000000000000000000000006044820152606401610970565b6000600d86815481106117f0577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600a611807919061594c565b6118119086615a12565b9050600061181d612e69565b90506000611829614d81565b905061189982610cd461189260218c8154811061186f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015461139f602254620f424061500590919063ffffffff16565b8690614ed8565b945080851115611905576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e7375662046585320417661696c20466f72205243540000000000000000006044820152606401610970565b8585101561196f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f46585320736c69707061676500000000000000000000000000000000000000006044820152606401610970565b600e88815481106119a9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001546119c7886119c18b611271565b90615005565b1115611a2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f506f6f6c206365696c696e6700000000000000000000000000000000000000006044820152606401610970565b611a96600b8981548110611a6c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633308a61507e565b6005546040517fb4f56b260000000000000000000000000000000000000000000000000000000081523360048201526024810187905273ffffffffffffffffffffffffffffffffffffffff9091169063b4f56b2690604401600060405180830381600087803b158015611b0857600080fd5b505af1158015611b1c573d6000803e3d6000fd5b5050505084601c6000611b2d6108be565b81526020019081526020016000206000828254611b4a919061589a565b909155509498975050505050505050565b60025473ffffffffffffffffffffffffffffffffffffffff16331480611b98575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611bfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b6007805473ffffffffffffffffffffffffffffffffffffffff8085167fffffffffffffffffffffffff000000000000000000000000000000000000000092831681179093556008805491851691909216179055604080517f313ce567000000000000000000000000000000000000000000000000000000008152905163313ce56791600480820192602092909190829003018186803b158015611ca057600080fd5b505afa158015611cb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cd891906156a1565b60ff16600955600854604080517f313ce567000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163313ce56791600480820192602092909190829003018186803b158015611d4957600080fd5b505afa158015611d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8191906156a1565b60ff16600a556040805173ffffffffffffffffffffffffffffffffffffffff8085168252831660208201527f4073b32a832187a54e475fc8fff20266eedffb63596adf4c0b8a2966e2b0025d9101610ddb565b600c8181548110611de457600080fd5b906000526020600020016000915090508054611dff90615a96565b80601f0160208091040260200160405190810160405280929190818152602001828054611e2b90615a96565b8015611e785780601f10611e4d57610100808354040283529160200191611e78565b820191906000526020600020905b815481529060010190602001808311611e5b57829003601f168201915b505050505081565b6000611f2b600f8481548110611ebf577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154610cd4600d8681548110611f07577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600a611f1e919061594c565b610cd486620f4240614ed8565b9392505050565b600d818154811061126057600080fd5b611fdb604051806101e001604052806000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600015158152602001600081526020016000815260200160008152602001600015158152602001600015158152602001600015158152602001600015158152602001600081526020016000815260200160008152602001600081525090565b73ffffffffffffffffffffffffffffffffffffffff821660009081526011602052604090205460ff1661206a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f496e76616c696420636f6c6c61746572616c00000000000000000000000000006044820152606401610970565b6000601060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050604051806101e00160405280828152602001600c83815481106120fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001805461210f90615a96565b80601f016020809104026020016040519081016040528092919081815260200182805461213b90615a96565b80156121885780601f1061215d57610100808354040283529160200191612188565b820191906000526020600020905b81548152906001019060200180831161216b57829003601f168201915b505050918352505073ffffffffffffffffffffffffffffffffffffffff851660208083018290526000918252601190526040908190205460ff16151590820152600d805460609092019184908110612209577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001600f8381548110612253577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001600e838154811061229d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001602383815481106122e7577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161515815260200160248381548110612348577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff1615158152602001602583815481106123a9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff16151581526020016026838154811061240a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff1615158152602001601e838154811061246b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001601f83815481106124b5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001548152602001602083815481106124ff577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154815260200160218381548110612549577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154815250915050919050565b60008060008660116000600b83815481106125a3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff1661263e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610970565b60238881548110612678577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a900416156126ff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4d696e74696e67206973207061757365640000000000000000000000000000006044820152606401610970565b60195461270a614ddb565b1015612772576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4672617820707269636520746f6f206c6f7700000000000000000000000000006044820152606401610970565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127dc57600080fd5b505afa1580156127f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128149190615514565b905085806128255750620f42408110155b1561283f576128348989611e80565b9350600092506128b3565b806128675760009350612860612853612e69565b610cd48a620f4240614ed8565b92506128b3565b600061287a620f4240610cd48b85614ed8565b905060006128888a83614e96565b90506128948b83611e80565b95506128ae6128a1612e69565b610cd483620f4240614ed8565b945050505b61291e620f4240610cd4612917601e8d815481106128fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154620f4240614e9690919063ffffffff16565b8b90614ed8565b94508487111561298a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4652415820736c697070616765000000000000000000000000000000000000006044820152606401610970565b600e89815481106129c4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001546129dc856119c18c611271565b1115612a44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f506f6f6c206365696c696e6700000000000000000000000000000000000000006044820152606401610970565b6005546040517fa8a778ae0000000000000000000000000000000000000000000000000000000081523360048201526024810185905273ffffffffffffffffffffffffffffffffffffffff9091169063a8a778ae90604401600060405180830381600087803b158015612ab657600080fd5b505af1158015612aca573d6000803e3d6000fd5b50505050612b35600b8a81548110612b0b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633308761507e565b600480546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815233928101929092526024820187905273ffffffffffffffffffffffffffffffffffffffff169063b4f56b2690604401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b5050505050509450945094915050565b60025473ffffffffffffffffffffffffffffffffffffffff16331480612c09575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612c6f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b6019829055601881905560408051838152602081018390527f08f944f25b910c541435bcde52d233072e903b37afc29bc8b5787b6e74d82c1a9101610ddb565b60015473ffffffffffffffffffffffffffffffffffffffff163314612d56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610970565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b6060600b805480602002602001604051908101604052809291908181526020018280548015612e5f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311612e34575b5050505050905090565b600080600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015612ed457600080fd5b505afa158015612ee8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f0c9190615652565b505050915050612f24600a54600a6128a1919061594c565b91505090565b3360009081526006602052604090205460ff16612fa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e6f7420616e20414d4f204d696e7465720000000000000000000000000000006044820152606401610970565b60003373ffffffffffffffffffffffffffffffffffffffff16638b4433966040518163ffffffff1660e01b815260040160206040518083038186803b158015612feb57600080fd5b505afa158015612fff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130239190615514565b905061308b600b8281548110613062577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16338461521c565b5050565b600080602483815481106130cc577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a90041615613153576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f52656465656d696e6720697320706175736564000000000000000000000000006044820152606401610970565b6017543360009081526016602052604090205443916131729190615005565b11156131da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f546f6f20736f6f6e0000000000000000000000000000000000000000000000006044820152606401610970565b3360009081526012602052604081205481901561321d5733600090815260126020526040812080549190556015549094506132159085614e96565b601555600191505b336000908152601360209081526040808320888452909152902054156133045733600090815260136020908152604080832088845290915281208054919055601480549194506132ba91859190889081106132a1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154614e9690919063ffffffff16565b601486815481106132f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000918252602090912001555060015b811561332e5760055461332e9073ffffffffffffffffffffffffffffffffffffffff16338661521c565b801561339a5761339a600b8681548110613371577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16338561521c565b5050915091565b60025473ffffffffffffffffffffffffffffffffffffffff163314806133de575060005473ffffffffffffffffffffffffffffffffffffffff1633145b613444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b6000600b8281548110613480577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff1680835260118252604092839020805460ff808216157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090921682179092558451878152911615159281019290925292507f088e9476d8b4139e22c8e66b078291edda3cd924ce0b0e7193f2a38e293e70ee9101610ddb565b60025473ffffffffffffffffffffffffffffffffffffffff1633148061355a575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6135c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b80600f83815481106135fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055507f16374e3dc228b497b5a9b2dff5883c395120625fbe7e794fdcc5d305ce13ed078282604051610ddb929190918252602082015260400190565b6000808560116000600b8381548110613685577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff16613720576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610970565b6024878154811061375a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a900416156137e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f52656465656d696e6720697320706175736564000000000000000000000000006044820152606401610970565b6018546137ec614ddb565b1115613854576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4672617820707269636520746f6f2068696768000000000000000000000000006044820152606401610970565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156138be57600080fd5b505afa1580156138d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f69190615514565b90506000613941620f4240610cd4612917601f8d815481106128fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9050620f42408210613a0e57613a03600d8a8154811061398a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015460066139a1919061589a565b6139ac90600a61594c565b610cd4600f8c815481106139e9577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015484614ed890919063ffffffff16565b945060009350613b02565b81613a2957613a1e6128a1612e69565b935060009450613b02565b613adb600d8a81548110613a66577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600c613a7d919061589a565b613a8890600a61594c565b610cd4600f8c81548110613ac5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260209091200154610cce8587614ed8565b9450613aff613ae8612e69565b610cd4613af8620f424086614e96565b8490614ed8565b93505b613b8460148a81548110613b3f577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600b8b815481106112f5577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b851115613bed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f496e73756666696369656e7420706f6f6c20636f6c6c61746572616c000000006044820152606401610970565b85851015613c57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c20736c697070616765000000000000000000000000006044820152606401610970565b86841015613cc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f46585320736c69707061676500000000000000000000000000000000000000006044820152606401610970565b3360009081526013602090815260408083208c8452909152902054613ce69086615005565b3360009081526013602090815260408083208d845290915290205560148054613d5b9187918c908110613d42577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b906000526020600020015461500590919063ffffffff16565b60148a81548110613d95577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091019290925533815260129091526040902054613dbd9085615005565b33600090815260126020526040902055601554613dda9085615005565b60155533600081815260166020526040908190204390556004805491517fa8a778ae00000000000000000000000000000000000000000000000000000000815290810192909252602482018a905273ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b158015613e6257600080fd5b505af1158015613e76573d6000803e3d6000fd5b50506005546040517fb4f56b260000000000000000000000000000000000000000000000000000000081523060048201526024810188905273ffffffffffffffffffffffffffffffffffffffff909116925063b4f56b269150604401600060405180830381600087803b158015613eec57600080fd5b505af1158015613f00573d6000803e3d6000fd5b5050505050505094509492505050565b6014818154811061126057600080fd5b60025473ffffffffffffffffffffffffffffffffffffffff16331480613f5d575060005473ffffffffffffffffffffffffffffffffffffffff1633145b80613f7f575060035473ffffffffffffffffffffffffffffffffffffffff1633145b613fe5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f4e6f74206f776e65722c20746c636b2c206f72206375737464000000000000006044820152606401610970565b60ff81166140b05760238281548110614027577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161560238381548110614082577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190066101000a81548160ff0219169083151502179055506142bd565b8060ff166001141561415157602482815481106140f6577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161560248381548110614082577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8060ff16600214156141f25760268281548110614197577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161560268381548110614082577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8060ff16600314156142bd5760258281548110614238577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190069054906101000a900460ff161560258381548110614293577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002090602091828204019190066101000a81548160ff0219169083151502179055505b6040805183815260ff831660208201527f3dbf640f58ea22aec5eb07b21b1a899b95d63fffcf6050292ee91a1ad5576a2e9101610ddb565b60025473ffffffffffffffffffffffffffffffffffffffff16331480614332575060005473ffffffffffffffffffffffffffffffffffffffff1633145b614398576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f7e7ee4175d63f671fac3401d5f401ed18d1f48a586e756f404d5696fc77a705890602001610c09565b60008360116000600b838154811061444c577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff16835282019290925260400190205460ff166144e7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c2064697361626c6564000000000000000000000000006044820152606401610970565b60268581548110614521577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020918290209181049091015460ff601f9092166101000a900416156145a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4275796261636b206973207061757365640000000000000000000000000000006044820152606401610970565b60006145b2612e69565b905060006145be610fe5565b90506000811161462a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e73756620436f6c6c617420417661696c20466f722042424b0000000000006044820152606401610970565b600061463d620f4240610cd48986614ed8565b9050818111156146a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f496e73756620436f6c6c617420417661696c20466f722042424b0000000000006044820152606401610970565b6000614701600f8a815481106146e8577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600091825260209091200154610cd484620f4240614ed8565b905061475e600d8a81548110614740577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154600a614757919061594c565b8290614f8d565b95506147ae620f4240610cd46147a760208d815481106128fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8990614ed8565b95508686101561481a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f436f6c6c61746572616c20736c697070616765000000000000000000000000006044820152606401610970565b6005546040517fa8a778ae000000000000000000000000000000000000000000000000000000008152336004820152602481018a905273ffffffffffffffffffffffffffffffffffffffff9091169063a8a778ae90604401600060405180830381600087803b15801561488c57600080fd5b505af11580156148a0573d6000803e3d6000fd5b5050505061490a600b8a815481106148e1577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16338861521c565b80601a60006149176108be565b81526020019081526020016000206000828254614934919061589a565b90915550959998505050505050505050565b60025473ffffffffffffffffffffffffffffffffffffffff16331480614983575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6149e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b73ffffffffffffffffffffffffffffffffffffffff8116614a66576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610970565b60008173ffffffffffffffffffffffffffffffffffffffff166317284c946040518163ffffffff1660e01b815260040160206040518083038186803b158015614aae57600080fd5b505afa158015614ac2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ae69190615514565b73ffffffffffffffffffffffffffffffffffffffff831660008181526006602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590519182529192507f15db44a176b13a69368dde2d5ada5960b7025d8946d346c14e6ec5e5ce3fdba49101610ddb565b600f818154811061126057600080fd5b60025473ffffffffffffffffffffffffffffffffffffffff16331480614bb5575060005473ffffffffffffffffffffffffffffffffffffffff1633145b614c1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b6022829055601781905560408051838152602081018390527f03cd02afb025e556dd4cb5ab56c7de3b05bb254aa76ee6bd499f6d8a011a14489101610ddb565b60025473ffffffffffffffffffffffffffffffffffffffff16331480614c98575060005473ffffffffffffffffffffffffffffffffffffffff1633145b614cfe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610970565b80600e8381548110614d39577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055507f4cb99f07bf9ab5f864d81d791709058819f4188481fb3c70b90a1765e003b16e8282604051610ddb929190918252602082015260400190565b600080614d8c612e69565b90506000614d98610de7565b90506000614dad83610cd484620f4240614ed8565b90506000601c6000614dbd6108be565b8152602001908152602001600020549050610fdc81601d5484614fcf565b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b158015614e4657600080fd5b505afa158015614e5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614e7e9190615652565b505050915050612f24600954600a6128a1919061594c565b6000611f2b83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061538c565b600082614ee7575060006113a5565b6000614ef38385615a12565b905082614f0085836158b2565b14611f2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60448201527f77000000000000000000000000000000000000000000000000000000000000006064820152608401610970565b6000611f2b83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506153e0565b6000828410614fe057506000611f2b565b6000614fec8486614e96565b9050808310614ffc579050611f2b565b50909392505050565b600080615012838561589a565b905083811015611f2b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006044820152606401610970565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161511d9190615707565b6000604051808303816000865af19150503d806000811461515a576040519150601f19603f3d011682016040523d82523d6000602084013e61515f565b606091505b509150915081801561518957508051158061518957508080602001905181019061518991906154e0565b615214576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610970565b505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916152b39190615707565b6000604051808303816000865af19150503d80600081146152f0576040519150601f19603f3d011682016040523d82523d6000602084013e6152f5565b606091505b509150915081801561531f57508051158061531f57508080602001905181019061531f91906154e0565b615385576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610970565b5050505050565b600081848411156153ca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610970919061577d565b5060006153d78486615a4f565b95945050505050565b6000818361541b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610970919061577d565b5060006153d784866158b2565b803573ffffffffffffffffffffffffffffffffffffffff8116811461544c57600080fd5b919050565b805169ffffffffffffffffffff8116811461544c57600080fd5b60006020828403121561547c578081fd5b611f2b82615428565b60008060408385031215615497578081fd5b6154a083615428565b91506154ae60208401615428565b90509250929050565b600080604083850312156154c9578182fd5b6154d283615428565b946020939093013593505050565b6000602082840312156154f1578081fd5b8151611f2b81615b52565b60006020828403121561550d578081fd5b5035919050565b600060208284031215615525578081fd5b5051919050565b6000806040838503121561553e578182fd5b50508035926020909101359150565b600080600060608486031215615561578081fd5b505081359360208301359350604090920135919050565b6000806000806080858703121561558d578081fd5b84359350602085013592506040850135915060608501356155ad81615b52565b939692955090935050565b600080600080608085870312156155cd578384fd5b5050823594602084013594506040840135936060013592509050565b600080600080600060a08688031215615600578081fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060408385031215615635578182fd5b82359150602083013561564781615b63565b809150509250929050565b600080600080600060a08688031215615669578283fd5b61567286615451565b945060208601519350604086015192506060860151915061569560808701615451565b90509295509295909350565b6000602082840312156156b2578081fd5b8151611f2b81615b63565b600081518084526156d5816020860160208601615a66565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60008251615719818460208701615a66565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b8181101561577157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161573f565b50909695505050505050565b602081526000611f2b60208301846156bd565b6020815281516020820152600060208301516101e08060408501526157b96102008501836156bd565b915060408501516157e2606086018273ffffffffffffffffffffffffffffffffffffffff169052565b506060850151801515608086015250608085015160a085015260a085015160c085015260c085015160e085015260e08501516101006158248187018315159052565b86015190506101206158398682018315159052565b860151905061014061584e8682018315159052565b86015190506101606158638682018315159052565b860151610180868101919091528601516101a0808701919091528601516101c0808701919091529095015193019290925250919050565b600082198211156158ad576158ad615b23565b500190565b6000826158e6577f4e487b710000000000000000000000000000000000000000000000000000000081526012600452602481fd5b500490565b600181815b8085111561594457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561592a5761592a615b23565b8085161561593757918102915b93841c93908002906158f0565b509250929050565b6000611f2b8383600082615962575060016113a5565b8161596f575060006113a5565b8160018114615985576002811461598f576159ab565b60019150506113a5565b60ff8411156159a0576159a0615b23565b50506001821b6113a5565b5060208310610133831016604e8410600b84101617156159ce575081810a6113a5565b6159d883836158eb565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a0a57615a0a615b23565b029392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615a4a57615a4a615b23565b500290565b600082821015615a6157615a61615b23565b500390565b60005b83811015615a81578181015183820152602001615a69565b83811115615a90576000848401525b50505050565b600181811c90821680615aaa57607f821691505b60208210811415615ae4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415615b1c57615b1c615b23565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8015158114615b6057600080fd5b50565b60ff81168114615b6057600080fdfea264697066735822122093a59cf8fdd8f1ed30f01182bb6491821d023dbe30666b3076cad1c38014a72c64736f6c63430008040033000000000000000000000000b39e2041b042f39b8572b6f84deba99bbb589c8d000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd20000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000060000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba000000000000000000000000057ab1ec28d129707052df4df418d58a2d46d5f510000000000000000000000001456688345527be1f37e9e627da0837d6f08c9250000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000956f47f50a910163d8bf957cf5846d573e7f87ca000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000a968163f0a57b400000000000000000000000000000000000000000000000000a968163f0a57b400000000000000000000000000000000000000000000000000a968163f0a57b400000000000000000000000000000000000000000000000000a968163f0a57b400000000000000000000000000000000000000000000000000a968163f0a57b4000000000000000000000000000000000000000000000000000000000000ba43b740000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000000000000000000000000000000000000000157c00000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001770","name":"FraxPoolV3","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"istanbul","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_pool_manager_address","type":"address"},{"internalType":"address","name":"_custodian_address","type":"address"},{"internalType":"address","name":"_timelock_address","type":"address"},{"internalType":"address[]","name":"_collateral_addresses","type":"address[]"},{"internalType":"uint256[]","name":"_pool_ceilings","type":"uint256[]"},{"internalType":"uint256[]","name":"_initial_fees","type":"uint256[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"amo_minter_addr","type":"address"}],"name":"AMOMinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"amo_minter_addr","type":"address"}],"name":"AMOMinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bbkMaxColE18OutPerHour","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rctMaxFxsOutPerHour","type":"uint256"}],"name":"BbkRctPerHourSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"col_idx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_price","type":"uint256"}],"name":"CollateralPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"col_idx","type":"uint256"},{"indexed":false,"internalType":"bool","name":"new_state","type":"bool"}],"name":"CollateralToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"new_custodian","type":"address"}],"name":"CustodianSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"col_idx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_mint_fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_redeem_fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_buyback_fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_recollat_fee","type":"uint256"}],"name":"FeesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"col_idx","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"tog_idx","type":"uint8"}],"name":"MRBRToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"frax_usd_chainlink_addr","type":"address"},{"indexed":false,"internalType":"address","name":"fxs_usd_chainlink_addr","type":"address"}],"name":"OraclesSet","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":"uint256","name":"col_idx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_ceiling","type":"uint256"}],"name":"PoolCeilingSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"new_bonus_rate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_redemption_delay","type":"uint256"}],"name":"PoolParametersSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"new_bonus_rate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"new_redemption_delay","type":"uint256"}],"name":"PriceThresholdsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"new_timelock","type":"address"}],"name":"TimelockSet","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"amo_minter_addr","type":"address"}],"name":"addAMOMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allCollaterals","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"collateral_amount","type":"uint256"}],"name":"amoMinterBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"amo_minter_addresses","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bbkHourlyCum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bbkMaxColE18OutPerHour","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonus_rate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"},{"internalType":"uint256","name":"fxs_amount","type":"uint256"},{"internalType":"uint256","name":"col_out_min","type":"uint256"}],"name":"buyBackFxs","outputs":[{"internalType":"uint256","name":"col_out","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buybackAvailableCollat","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatDollarBalance","outputs":[{"internalType":"uint256","name":"balance_tally","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collateralAddrToIdx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"collateral_addresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collat_address","type":"address"}],"name":"collateral_information","outputs":[{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"col_addr","type":"address"},{"internalType":"bool","name":"is_enabled","type":"bool"},{"internalType":"uint256","name":"missing_decs","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"pool_ceiling","type":"uint256"},{"internalType":"bool","name":"mint_paused","type":"bool"},{"internalType":"bool","name":"redeem_paused","type":"bool"},{"internalType":"bool","name":"recollat_paused","type":"bool"},{"internalType":"bool","name":"buyback_paused","type":"bool"},{"internalType":"uint256","name":"minting_fee","type":"uint256"},{"internalType":"uint256","name":"redemption_fee","type":"uint256"},{"internalType":"uint256","name":"buyback_fee","type":"uint256"},{"internalType":"uint256","name":"recollat_fee","type":"uint256"}],"internalType":"struct FraxPoolV3.CollateralInformation","name":"return_data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"collateral_prices","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"collateral_symbols","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"}],"name":"collectRedemption","outputs":[{"internalType":"uint256","name":"fxs_amount","type":"uint256"},{"internalType":"uint256","name":"collateral_amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"curEpochHr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"custodian_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"enabled_collaterals","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"}],"name":"freeCollatBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"},{"internalType":"uint256","name":"frax_amount","type":"uint256"}],"name":"getFRAXInCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFRAXPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFXSPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastRedeemed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"},{"internalType":"uint256","name":"frax_amt","type":"uint256"},{"internalType":"uint256","name":"frax_out_min","type":"uint256"},{"internalType":"bool","name":"one_to_one_override","type":"bool"}],"name":"mintFrax","outputs":[{"internalType":"uint256","name":"total_frax_mint","type":"uint256"},{"internalType":"uint256","name":"collat_needed","type":"uint256"},{"internalType":"uint256","name":"fxs_needed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mint_price_threshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pool_ceilings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedFRAXUSD","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeedFXSUSD","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rctHourlyCum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rctMaxFxsOutPerHour","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recollatAvailableFxs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recollatTheoColAvailableE18","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"},{"internalType":"uint256","name":"collateral_amount","type":"uint256"},{"internalType":"uint256","name":"fxs_out_min","type":"uint256"}],"name":"recollateralize","outputs":[{"internalType":"uint256","name":"fxs_out","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"redeemCollateralBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"redeemFXSBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"},{"internalType":"uint256","name":"frax_amount","type":"uint256"},{"internalType":"uint256","name":"fxs_out_min","type":"uint256"},{"internalType":"uint256","name":"col_out_min","type":"uint256"}],"name":"redeemFrax","outputs":[{"internalType":"uint256","name":"collat_out","type":"uint256"},{"internalType":"uint256","name":"fxs_out","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redeem_price_threshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemption_delay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"amo_minter_addr","type":"address"}],"name":"removeAMOMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bbkMaxColE18OutPerHour","type":"uint256"},{"internalType":"uint256","name":"_rctMaxFxsOutPerHour","type":"uint256"}],"name":"setBbkRctPerHour","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"},{"internalType":"uint256","name":"_new_price","type":"uint256"}],"name":"setCollateralPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"new_custodian","type":"address"}],"name":"setCustodian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"},{"internalType":"uint256","name":"new_mint_fee","type":"uint256"},{"internalType":"uint256","name":"new_redeem_fee","type":"uint256"},{"internalType":"uint256","name":"new_buyback_fee","type":"uint256"},{"internalType":"uint256","name":"new_recollat_fee","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_frax_usd_chainlink_addr","type":"address"},{"internalType":"address","name":"_fxs_usd_chainlink_addr","type":"address"}],"name":"setOracles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"},{"internalType":"uint256","name":"new_ceiling","type":"uint256"}],"name":"setPoolCeiling","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"new_bonus_rate","type":"uint256"},{"internalType":"uint256","name":"new_redemption_delay","type":"uint256"}],"name":"setPoolParameters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"new_mint_price_threshold","type":"uint256"},{"internalType":"uint256","name":"new_redeem_price_threshold","type":"uint256"}],"name":"setPriceThresholds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"new_timelock","type":"address"}],"name":"setTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timelock_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"}],"name":"toggleCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"col_idx","type":"uint256"},{"internalType":"uint8","name":"tog_idx","type":"uint8"}],"name":"toggleMRBR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"unclaimedPoolCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unclaimedPoolFXS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"000000000000000000000000b39e2041b042f39b8572b6f84deba99bbb589c8d000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd20000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000000060000000000000000000000005f98805a4e8be255a32880fdec7f6728c6568ba000000000000000000000000057ab1ec28d129707052df4df418d58a2d46d5f510000000000000000000000001456688345527be1f37e9e627da0837d6f08c9250000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000956f47f50a910163d8bf957cf5846d573e7f87ca000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000a968163f0a57b400000000000000000000000000000000000000000000000000a968163f0a57b400000000000000000000000000000000000000000000000000a968163f0a57b400000000000000000000000000000000000000000000000000a968163f0a57b400000000000000000000000000000000000000000000000000a968163f0a57b4000000000000000000000000000000000000000000000000000000000000ba43b740000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000bb8000000000000000000000000000000000000000000000000000000000000157c00000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001770"}