Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 59 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Sync Dollar Bala... | 16587484 | 750 days ago | IN | 0 ETH | 0.06908735 | ||||
Sync Dollar Bala... | 14825532 | 1012 days ago | IN | 0 ETH | 0.01426739 | ||||
Sync Dollar Bala... | 14803440 | 1016 days ago | IN | 0 ETH | 0.01658295 | ||||
Sync Dollar Bala... | 14803417 | 1016 days ago | IN | 0 ETH | 0.01578292 | ||||
Sync Dollar Bala... | 14784925 | 1019 days ago | IN | 0 ETH | 0.01900073 | ||||
Sync Dollar Bala... | 14613601 | 1046 days ago | IN | 0 ETH | 0.02808779 | ||||
Sync Dollar Bala... | 14541251 | 1057 days ago | IN | 0 ETH | 0.04355812 | ||||
Sync Dollar Bala... | 14181903 | 1113 days ago | IN | 0 ETH | 0.05918157 | ||||
Sync Dollar Bala... | 13909790 | 1155 days ago | IN | 0 ETH | 0.10486593 | ||||
Sync Dollar Bala... | 13699940 | 1188 days ago | IN | 0 ETH | 0.0812162 | ||||
Sync Dollar Bala... | 13699873 | 1188 days ago | IN | 0 ETH | 0.10215512 | ||||
Sync Dollar Bala... | 13699729 | 1188 days ago | IN | 0 ETH | 0.1090934 | ||||
Sync Dollar Bala... | 13699697 | 1188 days ago | IN | 0 ETH | 0.08745683 | ||||
Sync Dollar Bala... | 13610146 | 1202 days ago | IN | 0 ETH | 0.10682516 | ||||
Sync Dollar Bala... | 13566214 | 1209 days ago | IN | 0 ETH | 0.07135722 | ||||
Sync Dollar Bala... | 13565804 | 1209 days ago | IN | 0 ETH | 0.08380182 | ||||
Sync Dollar Bala... | 13560243 | 1210 days ago | IN | 0 ETH | 0.06231072 | ||||
Sync Dollar Bala... | 13560182 | 1210 days ago | IN | 0 ETH | 0.08022328 | ||||
Sync Dollar Bala... | 13534239 | 1214 days ago | IN | 0 ETH | 0.11204852 | ||||
Sync Dollar Bala... | 13487735 | 1222 days ago | IN | 0 ETH | 0.4685592 | ||||
Sync Dollar Bala... | 13469311 | 1225 days ago | IN | 0 ETH | 0.09791261 | ||||
Sync Dollar Bala... | 13452309 | 1227 days ago | IN | 0 ETH | 0.06602861 | ||||
Mint Fxs For AMO | 13368000 | 1240 days ago | IN | 0 ETH | 0.10278812 | ||||
Mint Fxs For AMO | 13367995 | 1240 days ago | IN | 0 ETH | 0.10548996 | ||||
Mint Frax For AM... | 13367991 | 1240 days ago | IN | 0 ETH | 0.69668633 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
FraxAMOMinter
Compiler Version
v0.8.6+commit.11564f7e
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-09-14 */ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; // Sources flattened with hardhat v2.6.2 https://hardhat.org // File contracts/Math/SafeMath.sol /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File contracts/Frax/IFrax.sol interface IFrax { function COLLATERAL_RATIO_PAUSER() external view returns (bytes32); function DEFAULT_ADMIN_ADDRESS() external view returns (address); function DEFAULT_ADMIN_ROLE() external view returns (bytes32); function addPool(address pool_address ) external; function allowance(address owner, address spender ) external view returns (uint256); function approve(address spender, uint256 amount ) external returns (bool); function balanceOf(address account ) external view returns (uint256); function burn(uint256 amount ) external; function burnFrom(address account, uint256 amount ) external; function collateral_ratio_paused() external view returns (bool); function controller_address() external view returns (address); function creator_address() external view returns (address); function decimals() external view returns (uint8); function decreaseAllowance(address spender, uint256 subtractedValue ) external returns (bool); function eth_usd_consumer_address() external view returns (address); function eth_usd_price() external view returns (uint256); function frax_eth_oracle_address() external view returns (address); function frax_info() external view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256); function frax_pools(address ) external view returns (bool); function frax_pools_array(uint256 ) external view returns (address); function frax_price() external view returns (uint256); function frax_step() external view returns (uint256); function fxs_address() external view returns (address); function fxs_eth_oracle_address() external view returns (address); function fxs_price() external view returns (uint256); function genesis_supply() external view returns (uint256); function getRoleAdmin(bytes32 role ) external view returns (bytes32); function getRoleMember(bytes32 role, uint256 index ) external view returns (address); function getRoleMemberCount(bytes32 role ) external view returns (uint256); function globalCollateralValue() external view returns (uint256); function global_collateral_ratio() external view returns (uint256); function grantRole(bytes32 role, address account ) external; function hasRole(bytes32 role, address account ) external view returns (bool); function increaseAllowance(address spender, uint256 addedValue ) external returns (bool); function last_call_time() external view returns (uint256); function minting_fee() external view returns (uint256); function name() external view returns (string memory); function owner_address() external view returns (address); function pool_burn_from(address b_address, uint256 b_amount ) external; function pool_mint(address m_address, uint256 m_amount ) external; function price_band() external view returns (uint256); function price_target() external view returns (uint256); function redemption_fee() external view returns (uint256); function refreshCollateralRatio() external; function refresh_cooldown() external view returns (uint256); function removePool(address pool_address ) external; function renounceRole(bytes32 role, address account ) external; function revokeRole(bytes32 role, address account ) external; function setController(address _controller_address ) external; function setETHUSDOracle(address _eth_usd_consumer_address ) external; function setFRAXEthOracle(address _frax_oracle_addr, address _weth_address ) external; function setFXSAddress(address _fxs_address ) external; function setFXSEthOracle(address _fxs_oracle_addr, address _weth_address ) external; function setFraxStep(uint256 _new_step ) external; function setMintingFee(uint256 min_fee ) external; function setOwner(address _owner_address ) external; function setPriceBand(uint256 _price_band ) external; function setPriceTarget(uint256 _new_price_target ) external; function setRedemptionFee(uint256 red_fee ) external; function setRefreshCooldown(uint256 _new_cooldown ) external; function setTimelock(address new_timelock ) external; function symbol() external view returns (string memory); function timelock_address() external view returns (address); function toggleCollateralRatio() external; function totalSupply() external view returns (uint256); function transfer(address recipient, uint256 amount ) external returns (bool); function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool); function weth_address() external view returns (address); } // File contracts/FXS/IFxs.sol interface IFxs { function DEFAULT_ADMIN_ROLE() external view returns(bytes32); function FRAXStablecoinAdd() external view returns(address); function FXS_DAO_min() external view returns(uint256); function allowance(address owner, address spender) external view returns(uint256); function approve(address spender, uint256 amount) external returns(bool); function balanceOf(address account) external view returns(uint256); function burn(uint256 amount) external; function burnFrom(address account, uint256 amount) external; function checkpoints(address, uint32) external view returns(uint32 fromBlock, uint96 votes); function decimals() external view returns(uint8); function decreaseAllowance(address spender, uint256 subtractedValue) external returns(bool); function genesis_supply() external view returns(uint256); function getCurrentVotes(address account) external view returns(uint96); function getPriorVotes(address account, uint256 blockNumber) external view returns(uint96); function getRoleAdmin(bytes32 role) external view returns(bytes32); function getRoleMember(bytes32 role, uint256 index) external view returns(address); function getRoleMemberCount(bytes32 role) external view returns(uint256); function grantRole(bytes32 role, address account) external; function hasRole(bytes32 role, address account) external view returns(bool); function increaseAllowance(address spender, uint256 addedValue) external returns(bool); function mint(address to, uint256 amount) external; function name() external view returns(string memory); function numCheckpoints(address) external view returns(uint32); function oracle_address() external view returns(address); function owner_address() external view returns(address); function pool_burn_from(address b_address, uint256 b_amount) external; function pool_mint(address m_address, uint256 m_amount) external; function renounceRole(bytes32 role, address account) external; function revokeRole(bytes32 role, address account) external; function setFRAXAddress(address frax_contract_address) external; function setFXSMinDAO(uint256 min_FXS) external; function setOracle(address new_oracle) external; function setOwner(address _owner_address) external; function setTimelock(address new_timelock) external; function symbol() external view returns(string memory); function timelock_address() external view returns(address); function toggleVotes() external; function totalSupply() external view returns(uint256); function trackingVotes() external view returns(bool); function transfer(address recipient, uint256 amount) external returns(bool); function transferFrom(address sender, address recipient, uint256 amount) external returns(bool); } // File contracts/Uniswap/TransferHelper.sol // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove(address token, address to, uint value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); } function safeTransfer(address token, address to, uint value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); } function safeTransferFrom(address token, address from, address to, uint value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); } function safeTransferETH(address to, uint value) internal { (bool success,) = to.call{value:value}(new bytes(0)); require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); } } // File contracts/Staking/Owned.sol // https://docs.synthetix.io/contracts/Owned contract Owned { address public owner; address public nominatedOwner; constructor (address _owner) public { require(_owner != address(0), "Owner address cannot be 0"); owner = _owner; emit OwnerChanged(address(0), _owner); } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); emit OwnerChanged(owner, nominatedOwner); owner = nominatedOwner; nominatedOwner = address(0); } modifier onlyOwner { require(msg.sender == owner, "Only the contract owner may perform this action"); _; } event OwnerNominated(address newOwner); event OwnerChanged(address oldOwner, address newOwner); } // File contracts/Oracle/AggregatorV3Interface.sol interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); } // File contracts/Frax/IFraxAMOMinter.sol // MAY need to be updated interface IFraxAMOMinter { function FRAX() external view returns(address); function FXS() external view returns(address); function acceptOwnership() external; function addAMO(address amo_address, bool sync_too) external; function allAMOAddresses() external view returns(address[] memory); function allAMOsLength() external view returns(uint256); function amoProfit(address amo_address) external view returns(int256); function amos(address) external view returns(bool); function amos_array(uint256) external view returns(address); function burnFXS(uint256 amount) external; function burnFraxFromAMO(uint256 frax_amount) external; function burnFxsFromAMO(uint256 fxs_amount) external; function col_idx() external view returns(uint256); function collatDollarBalance() external view returns(uint256); function collatDollarBalanceStored() external view returns(uint256); function collat_borrow_cap() external view returns(int256); function collat_borrowed_balances(address) external view returns(int256); function collat_borrowed_sum() external view returns(int256); function collateral_address() external view returns(address); function collateral_token() external view returns(address); function custodian_address() external view returns(address); function fraxDollarBalanceStored() external view returns(uint256); function giveCollatToAMO(address destination_amo, uint256 collat_amount) external; function min_cr() external view returns(uint256); function mintFraxForAMO(address destination_amo, uint256 frax_amount) external; function mint_balances(address) external view returns(int256); function mint_cap() external view returns(int256); function mint_sum() external view returns(int256); function missing_decimals() external view returns(uint256); function nominateNewOwner(address _owner) external; function nominatedOwner() external view returns(address); function override_collat_balance() external view returns(bool); function override_collat_balance_amount() external view returns(uint256); function owner() external view returns(address); function pool() external view returns(address); function receiveCollatFromAMO(uint256 usdc_amount) external; function recoverERC20(address tokenAddress, uint256 tokenAmount) external; function removeAMO(address amo_address, bool sync_too) external; function setCustodian(address _custodian_address) external; function setFraxPool(address _pool_address) external; function setMinimumCollateralRatio(uint256 _min_cr) external; function setMintCap(uint256 _mint_cap) external; function setOverrideCollatBalance(bool _state, uint256 _balance) external; function setTimelock(address new_timelock) external; function syncDollarBalances() external; function timelock_address() external view returns(address); function unspentProfitGlobal() external view returns(int256); } // File contracts/Common/Context.sol /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return payable(msg.sender); } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File contracts/ERC20/IERC20.sol /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File contracts/Utils/Address.sol /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File contracts/ERC20/ERC20.sol /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory __name, string memory __symbol) public { _name = __name; _symbol = __symbol; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address.approve(address spender, uint256 amount) */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public virtual { _burn(_msgSender(), amount); } /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for `accounts`'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance"); _approve(account, _msgSender(), decreasedAllowance); _burn(account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal virtual { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of `from`'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of `from`'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:using-hooks.adoc[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } // File contracts/Frax/Pools/FraxPoolV3.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ============================ FraxPoolV3 ============================ // ==================================================================== // Allows multiple stablecoins (fixed amount at initialization) as collateral // LUSD, sUSD, USDP, Wrapped UST, and FEI initially // For this pool, the goal is to accept crypto-backed / overcollateralized stablecoins to limit // government / regulatory risk (e.g. USDC blacklisting until holders KYC) // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Travis Moore: https://github.com/FortisFortuna // Reviewer(s) / Contributor(s) // Jason Huan: https://github.com/jasonhuan // Sam Kazemian: https://github.com/samkazemian // Dennis: github.com/denett // Hameed contract FraxPoolV3 is Owned { using SafeMath for uint256; // SafeMath automatically included in Solidity >= 8.0.0 /* ========== STATE VARIABLES ========== */ // Core address public timelock_address; address public custodian_address; // Custodian is an EOA (or msig) with pausing privileges only, in case of an emergency IFrax private FRAX = IFrax(0x853d955aCEf822Db058eb8505911ED77F175b99e); IFxs private FXS = IFxs(0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0); mapping(address => bool) public amo_minter_addresses; // minter address -> is it enabled AggregatorV3Interface public priceFeedFRAXUSD = AggregatorV3Interface(0xB9E1E3A9feFf48998E45Fa90847ed4D467E8BcfD); AggregatorV3Interface public priceFeedFXSUSD = AggregatorV3Interface(0x6Ebc52C8C1089be9eB3945C4350B68B8E4C2233f); uint256 private chainlink_frax_usd_decimals; uint256 private chainlink_fxs_usd_decimals; // Collateral address[] public collateral_addresses; string[] public collateral_symbols; uint256[] public missing_decimals; // Number of decimals needed to get to E18. collateral index -> missing_decimals uint256[] public pool_ceilings; // Total across all collaterals. Accounts for missing_decimals uint256[] public collateral_prices; // Stores price of the collateral, if price is paused mapping(address => uint256) public collateralAddrToIdx; // collateral addr -> collateral index mapping(address => bool) public enabled_collaterals; // collateral address -> is it enabled // Redeem related mapping (address => uint256) public redeemFXSBalances; mapping (address => mapping(uint256 => uint256)) public redeemCollateralBalances; // Address -> collateral index -> balance uint256[] public unclaimedPoolCollateral; // collateral index -> balance uint256 public unclaimedPoolFXS; mapping (address => uint256) public lastRedeemed; // Collateral independent uint256 public redemption_delay = 2; // Number of blocks to wait before being able to collectRedemption() uint256 public redeem_price_threshold = 990000; // $0.99 uint256 public mint_price_threshold = 1010000; // $1.01 // Buyback related mapping(uint256 => uint256) public bbkHourlyCum; // Epoch hour -> Collat out in that hour (E18) uint256 public bbkMaxColE18OutPerHour = 1000e18; // Recollat related mapping(uint256 => uint256) public rctHourlyCum; // Epoch hour -> FXS out in that hour uint256 public rctMaxFxsOutPerHour = 1000e18; // Fees and rates // getters are in collateral_information() uint256[] private minting_fee; uint256[] private redemption_fee; uint256[] private buyback_fee; uint256[] private recollat_fee; uint256 public bonus_rate; // Bonus rate on FXS minted during recollateralize(); 6 decimals of precision, set to 0.75% on genesis // Constants for various precisions uint256 private constant PRICE_PRECISION = 1e6; // Pause variables // getters are in collateral_information() bool[] private mintPaused; // Collateral-specific bool[] private redeemPaused; // Collateral-specific bool[] private recollateralizePaused; // Collateral-specific bool[] private buyBackPaused; // Collateral-specific /* ========== MODIFIERS ========== */ modifier onlyByOwnGov() { require(msg.sender == timelock_address || msg.sender == owner, "Not owner or timelock"); _; } modifier onlyByOwnGovCust() { require(msg.sender == timelock_address || msg.sender == owner || msg.sender == custodian_address, "Not owner, tlck, or custd"); _; } modifier onlyAMOMinters() { require(amo_minter_addresses[msg.sender], "Not an AMO Minter"); _; } modifier collateralEnabled(uint256 col_idx) { require(enabled_collaterals[collateral_addresses[col_idx]], "Collateral disabled"); _; } /* ========== CONSTRUCTOR ========== */ constructor ( address _pool_manager_address, address _custodian_address, address _timelock_address, address[] memory _collateral_addresses, uint256[] memory _pool_ceilings, uint256[] memory _initial_fees ) Owned(_pool_manager_address){ // Core timelock_address = _timelock_address; custodian_address = _custodian_address; // Fill collateral info collateral_addresses = _collateral_addresses; for (uint256 i = 0; i < _collateral_addresses.length; i++){ // For fast collateral address -> collateral idx lookups later collateralAddrToIdx[_collateral_addresses[i]] = i; // Set all of the collaterals initially to disabled enabled_collaterals[_collateral_addresses[i]] = false; // Add in the missing decimals missing_decimals.push(uint256(18).sub(ERC20(_collateral_addresses[i]).decimals())); // Add in the collateral symbols collateral_symbols.push(ERC20(_collateral_addresses[i]).symbol()); // Initialize unclaimed pool collateral unclaimedPoolCollateral.push(0); // Initialize paused prices to $1 as a backup collateral_prices.push(PRICE_PRECISION); // Handle the fees minting_fee.push(_initial_fees[0]); redemption_fee.push(_initial_fees[1]); buyback_fee.push(_initial_fees[2]); recollat_fee.push(_initial_fees[3]); // Handle the pauses mintPaused.push(false); redeemPaused.push(false); recollateralizePaused.push(false); buyBackPaused.push(false); } // Pool ceiling pool_ceilings = _pool_ceilings; // Set the decimals chainlink_frax_usd_decimals = priceFeedFRAXUSD.decimals(); chainlink_fxs_usd_decimals = priceFeedFXSUSD.decimals(); } /* ========== STRUCTS ========== */ struct CollateralInformation { uint256 index; string symbol; address col_addr; bool is_enabled; uint256 missing_decs; uint256 price; uint256 pool_ceiling; bool mint_paused; bool redeem_paused; bool recollat_paused; bool buyback_paused; uint256 minting_fee; uint256 redemption_fee; uint256 buyback_fee; uint256 recollat_fee; } /* ========== VIEWS ========== */ // Helpful for UIs function collateral_information(address collat_address) external view returns (CollateralInformation memory return_data){ require(enabled_collaterals[collat_address], "Invalid collateral"); // Get the index uint256 idx = collateralAddrToIdx[collat_address]; return_data = CollateralInformation( idx, // [0] collateral_symbols[idx], // [1] collat_address, // [2] enabled_collaterals[collat_address], // [3] missing_decimals[idx], // [4] collateral_prices[idx], // [5] pool_ceilings[idx], // [6] mintPaused[idx], // [7] redeemPaused[idx], // [8] recollateralizePaused[idx], // [9] buyBackPaused[idx], // [10] minting_fee[idx], // [11] redemption_fee[idx], // [12] buyback_fee[idx], // [13] recollat_fee[idx] // [14] ); } function allCollaterals() external view returns (address[] memory) { return collateral_addresses; } function getFRAXPrice() public view returns (uint256) { ( , int price, , , ) = priceFeedFRAXUSD.latestRoundData(); return uint256(price).mul(PRICE_PRECISION).div(10 ** chainlink_frax_usd_decimals); } function getFXSPrice() public view returns (uint256) { ( , int price, , , ) = priceFeedFXSUSD.latestRoundData(); return uint256(price).mul(PRICE_PRECISION).div(10 ** chainlink_fxs_usd_decimals); } // Returns the FRAX value in collateral tokens function getFRAXInCollateral(uint256 col_idx, uint256 frax_amount) public view returns (uint256) { return frax_amount.mul(PRICE_PRECISION).div(10 ** missing_decimals[col_idx]).div(collateral_prices[col_idx]); } // Used by some functions. function freeCollatBalance(uint256 col_idx) public view returns (uint256) { return ERC20(collateral_addresses[col_idx]).balanceOf(address(this)).sub(unclaimedPoolCollateral[col_idx]); } // Returns dollar value of collateral held in this Frax pool, in E18 function collatDollarBalance() external view returns (uint256 balance_tally) { balance_tally = 0; // Test 1 for (uint256 i = 0; i < collateral_addresses.length; i++){ balance_tally += freeCollatBalance(i).mul(10 ** missing_decimals[i]).mul(collateral_prices[i]).div(PRICE_PRECISION); } } function comboCalcBbkRct(uint256 cur, uint256 max, uint256 theo) internal pure returns (uint256) { if (cur >= max) { // If the hourly limit has already been reached, return 0; return 0; } else { // Get the available amount uint256 available = max.sub(cur); if (theo >= available) { // If the the theoretical is more than the available, return the available return available; } else { // Otherwise, return the theoretical amount return theo; } } } // Returns the value of excess collateral (in E18) held globally, compared to what is needed to maintain the global collateral ratio // Also has throttling to avoid dumps during large price movements function buybackAvailableCollat() public view returns (uint256) { uint256 total_supply = FRAX.totalSupply(); uint256 global_collateral_ratio = FRAX.global_collateral_ratio(); uint256 global_collat_value = FRAX.globalCollateralValue(); if (global_collateral_ratio > PRICE_PRECISION) global_collateral_ratio = PRICE_PRECISION; // Handles an overcollateralized contract with CR > 1 uint256 required_collat_dollar_value_d18 = (total_supply.mul(global_collateral_ratio)).div(PRICE_PRECISION); // Calculates collateral needed to back each 1 FRAX with $1 of collateral at current collat ratio if (global_collat_value > required_collat_dollar_value_d18) { // Get the theoretical buyback amount uint256 theoretical_bbk_amt = global_collat_value.sub(required_collat_dollar_value_d18); // See how much has collateral has been issued this hour uint256 current_hr_bbk = bbkHourlyCum[curEpochHr()]; // Account for the throttling return comboCalcBbkRct(current_hr_bbk, bbkMaxColE18OutPerHour, theoretical_bbk_amt); } else return 0; } // Returns the missing amount of collateral (in E18) needed to maintain the collateral ratio function recollatTheoColAvailableE18() public view returns (uint256) { uint256 frax_total_supply = FRAX.totalSupply(); uint256 effective_collateral_ratio = FRAX.globalCollateralValue().mul(PRICE_PRECISION).div(frax_total_supply); // Returns it in 1e6 uint256 desired_collat_e24 = (FRAX.global_collateral_ratio()).mul(frax_total_supply); uint256 effective_collat_e24 = effective_collateral_ratio.mul(frax_total_supply); // Return 0 if already overcollateralized // Otherwise, return the deficiency if (effective_collat_e24 >= desired_collat_e24) return 0; else { return (desired_collat_e24.sub(effective_collat_e24)).div(PRICE_PRECISION); } } // Returns the value of FXS available to be used for recollats // Also has throttling to avoid dumps during large price movements function recollatAvailableFxs() public view returns (uint256) { uint256 fxs_price = getFXSPrice(); // Get the amount of collateral theoretically available uint256 recollat_theo_available_e18 = recollatTheoColAvailableE18(); // Get the amount of FXS theoretically outputtable uint256 fxs_theo_out = recollat_theo_available_e18.mul(PRICE_PRECISION).div(fxs_price); // See how much FXS has been issued this hour uint256 current_hr_rct = rctHourlyCum[curEpochHr()]; // Account for the throttling return comboCalcBbkRct(current_hr_rct, rctMaxFxsOutPerHour, fxs_theo_out); } // Returns the current epoch hour function curEpochHr() public view returns (uint256) { return (block.timestamp / 3600); // Truncation desired } /* ========== PUBLIC FUNCTIONS ========== */ function mintFrax( uint256 col_idx, uint256 frax_amt, uint256 frax_out_min, bool one_to_one_override ) external collateralEnabled(col_idx) returns ( uint256 total_frax_mint, uint256 collat_needed, uint256 fxs_needed ) { require(mintPaused[col_idx] == false, "Minting is paused"); // Prevent unneccessary mints require(getFRAXPrice() >= mint_price_threshold, "Frax price too low"); uint256 global_collateral_ratio = FRAX.global_collateral_ratio(); if (one_to_one_override || global_collateral_ratio >= PRICE_PRECISION) { // 1-to-1, overcollateralized, or user selects override collat_needed = getFRAXInCollateral(col_idx, frax_amt); fxs_needed = 0; } else if (global_collateral_ratio == 0) { // Algorithmic collat_needed = 0; fxs_needed = frax_amt.mul(PRICE_PRECISION).div(getFXSPrice()); } else { // Fractional uint256 frax_for_collat = frax_amt.mul(global_collateral_ratio).div(PRICE_PRECISION); uint256 frax_for_fxs = frax_amt.sub(frax_for_collat); collat_needed = getFRAXInCollateral(col_idx, frax_for_collat); fxs_needed = frax_for_fxs.mul(PRICE_PRECISION).div(getFXSPrice()); } // Subtract the minting fee total_frax_mint = (frax_amt.mul(PRICE_PRECISION.sub(minting_fee[col_idx]))).div(PRICE_PRECISION); // Checks require((frax_out_min <= total_frax_mint), "FRAX slippage"); require(freeCollatBalance(col_idx).add(collat_needed) <= pool_ceilings[col_idx], "Pool ceiling"); // Take the FXS and collateral first FXS.pool_burn_from(msg.sender, fxs_needed); TransferHelper.safeTransferFrom(collateral_addresses[col_idx], msg.sender, address(this), collat_needed); // Mint the FRAX FRAX.pool_mint(msg.sender, total_frax_mint); } function redeemFrax( uint256 col_idx, uint256 frax_amount, uint256 fxs_out_min, uint256 col_out_min ) external collateralEnabled(col_idx) returns ( uint256 collat_out, uint256 fxs_out ) { require(redeemPaused[col_idx] == false, "Redeeming is paused"); // Prevent unneccessary redemptions that could adversely affect the FXS price require(getFRAXPrice() <= redeem_price_threshold, "Frax price too high"); uint256 global_collateral_ratio = FRAX.global_collateral_ratio(); uint256 frax_after_fee = (frax_amount.mul(PRICE_PRECISION.sub(redemption_fee[col_idx]))).div(PRICE_PRECISION); // Assumes $1 FRAX in all cases if(global_collateral_ratio >= PRICE_PRECISION) { // 1-to-1 or overcollateralized collat_out = frax_after_fee .mul(collateral_prices[col_idx]) .div(10 ** (6 + missing_decimals[col_idx])); // PRICE_PRECISION + missing decimals fxs_out = 0; } else if (global_collateral_ratio == 0) { // Algorithmic fxs_out = frax_after_fee .mul(PRICE_PRECISION) .div(getFXSPrice()); collat_out = 0; } else { // Fractional collat_out = frax_after_fee .mul(global_collateral_ratio) .mul(collateral_prices[col_idx]) .div(10 ** (12 + missing_decimals[col_idx])); // PRICE_PRECISION ^2 + missing decimals fxs_out = frax_after_fee .mul(PRICE_PRECISION.sub(global_collateral_ratio)) .div(getFXSPrice()); // PRICE_PRECISIONS CANCEL OUT } // Checks require(collat_out <= (ERC20(collateral_addresses[col_idx])).balanceOf(address(this)).sub(unclaimedPoolCollateral[col_idx]), "Insufficient pool collateral"); require(collat_out >= col_out_min, "Collateral slippage"); require(fxs_out >= fxs_out_min, "FXS slippage"); // Account for the redeem delay redeemCollateralBalances[msg.sender][col_idx] = redeemCollateralBalances[msg.sender][col_idx].add(collat_out); unclaimedPoolCollateral[col_idx] = unclaimedPoolCollateral[col_idx].add(collat_out); redeemFXSBalances[msg.sender] = redeemFXSBalances[msg.sender].add(fxs_out); unclaimedPoolFXS = unclaimedPoolFXS.add(fxs_out); lastRedeemed[msg.sender] = block.number; FRAX.pool_burn_from(msg.sender, frax_amount); FXS.pool_mint(address(this), fxs_out); } // After a redemption happens, transfer the newly minted FXS and owed collateral from this pool // contract to the user. Redemption is split into two functions to prevent flash loans from being able // to take out FRAX/collateral from the system, use an AMM to trade the new price, and then mint back into the system. function collectRedemption(uint256 col_idx) external returns (uint256 fxs_amount, uint256 collateral_amount) { require(redeemPaused[col_idx] == false, "Redeeming is paused"); require((lastRedeemed[msg.sender].add(redemption_delay)) <= block.number, "Too soon"); bool sendFXS = false; bool sendCollateral = false; // Use Checks-Effects-Interactions pattern if(redeemFXSBalances[msg.sender] > 0){ fxs_amount = redeemFXSBalances[msg.sender]; redeemFXSBalances[msg.sender] = 0; unclaimedPoolFXS = unclaimedPoolFXS.sub(fxs_amount); sendFXS = true; } if(redeemCollateralBalances[msg.sender][col_idx] > 0){ collateral_amount = redeemCollateralBalances[msg.sender][col_idx]; redeemCollateralBalances[msg.sender][col_idx] = 0; unclaimedPoolCollateral[col_idx] = unclaimedPoolCollateral[col_idx].sub(collateral_amount); sendCollateral = true; } // Send out the tokens if(sendFXS){ TransferHelper.safeTransfer(address(FXS), msg.sender, fxs_amount); } if(sendCollateral){ TransferHelper.safeTransfer(collateral_addresses[col_idx], msg.sender, collateral_amount); } } // Function can be called by an FXS holder to have the protocol buy back FXS with excess collateral value from a desired collateral pool // This can also happen if the collateral ratio > 1 function buyBackFxs(uint256 col_idx, uint256 fxs_amount, uint256 col_out_min) external collateralEnabled(col_idx) returns (uint256 col_out) { require(buyBackPaused[col_idx] == false, "Buyback is paused"); uint256 fxs_price = getFXSPrice(); uint256 available_excess_collat_dv = buybackAvailableCollat(); // If the total collateral value is higher than the amount required at the current collateral ratio then buy back up to the possible FXS with the desired collateral require(available_excess_collat_dv > 0, "Insuf Collat Avail For BBK"); // Make sure not to take more than is available uint256 fxs_dollar_value_d18 = fxs_amount.mul(fxs_price).div(PRICE_PRECISION); require(fxs_dollar_value_d18 <= available_excess_collat_dv, "Insuf Collat Avail For BBK"); // Get the equivalent amount of collateral based on the market value of FXS provided uint256 collateral_equivalent_d18 = fxs_dollar_value_d18.mul(PRICE_PRECISION).div(collateral_prices[col_idx]); col_out = collateral_equivalent_d18.div(10 ** missing_decimals[col_idx]); // In its natural decimals() // Subtract the buyback fee col_out = (col_out.mul(PRICE_PRECISION.sub(buyback_fee[col_idx]))).div(PRICE_PRECISION); // Check for slippage require(col_out >= col_out_min, "Collateral slippage"); // Take in and burn the FXS, then send out the collateral FXS.pool_burn_from(msg.sender, fxs_amount); TransferHelper.safeTransfer(collateral_addresses[col_idx], msg.sender, col_out); // Increment the outbound collateral, in E18, for that hour // Used for buyback throttling bbkHourlyCum[curEpochHr()] += collateral_equivalent_d18; } // When the protocol is recollateralizing, we need to give a discount of FXS to hit the new CR target // Thus, if the target collateral ratio is higher than the actual value of collateral, minters get FXS for adding collateral // This function simply rewards anyone that sends collateral to a pool with the same amount of FXS + the bonus rate // Anyone can call this function to recollateralize the protocol and take the extra FXS value from the bonus rate as an arb opportunity function recollateralize(uint256 col_idx, uint256 collateral_amount, uint256 fxs_out_min) external collateralEnabled(col_idx) returns (uint256 fxs_out) { require(recollateralizePaused[col_idx] == false, "Recollat is paused"); uint256 collateral_amount_d18 = collateral_amount * (10 ** missing_decimals[col_idx]); uint256 fxs_price = getFXSPrice(); // Get the amount of FXS actually available (accounts for throttling) uint256 fxs_actually_available = recollatAvailableFxs(); // Calculated the attempted amount of FXS fxs_out = collateral_amount_d18.mul(PRICE_PRECISION.add(bonus_rate).sub(recollat_fee[col_idx])).div(fxs_price); // Make sure there is FXS available require(fxs_out <= fxs_actually_available, "Insuf FXS Avail For RCT"); // Check slippage require(fxs_out >= fxs_out_min, "FXS slippage"); // Don't take in more collateral than the pool ceiling for this token allows require(freeCollatBalance(col_idx).add(collateral_amount) <= pool_ceilings[col_idx], "Pool ceiling"); // Take in the collateral and pay out the FXS TransferHelper.safeTransferFrom(collateral_addresses[col_idx], msg.sender, address(this), collateral_amount); FXS.pool_mint(msg.sender, fxs_out); // Increment the outbound FXS, in E18 // Used for recollat throttling rctHourlyCum[curEpochHr()] += fxs_out; } // Bypasses the gassy mint->redeem cycle for AMOs to borrow collateral function amoMinterBorrow(uint256 collateral_amount) external onlyAMOMinters { // Checks the col_idx of the minter as an additional safety check uint256 minter_col_idx = IFraxAMOMinter(msg.sender).col_idx(); // Transfer TransferHelper.safeTransfer(collateral_addresses[minter_col_idx], msg.sender, collateral_amount); } /* ========== RESTRICTED FUNCTIONS, CUSTODIAN CAN CALL TOO ========== */ function toggleMRBR(uint256 col_idx, uint8 tog_idx) external onlyByOwnGovCust { if (tog_idx == 0) mintPaused[col_idx] = !mintPaused[col_idx]; else if (tog_idx == 1) redeemPaused[col_idx] = !redeemPaused[col_idx]; else if (tog_idx == 2) buyBackPaused[col_idx] = !buyBackPaused[col_idx]; else if (tog_idx == 3) recollateralizePaused[col_idx] = !recollateralizePaused[col_idx]; emit MRBRToggled(col_idx, tog_idx); } /* ========== RESTRICTED FUNCTIONS, GOVERNANCE ONLY ========== */ // Add an AMO Minter function addAMOMinter(address amo_minter_addr) external onlyByOwnGov { require(amo_minter_addr != address(0), "Zero address detected"); // Make sure the AMO Minter has collatDollarBalance() uint256 collat_val_e18 = IFraxAMOMinter(amo_minter_addr).collatDollarBalance(); require(collat_val_e18 >= 0, "Invalid AMO"); amo_minter_addresses[amo_minter_addr] = true; emit AMOMinterAdded(amo_minter_addr); } // Remove an AMO Minter function removeAMOMinter(address amo_minter_addr) external onlyByOwnGov { amo_minter_addresses[amo_minter_addr] = false; emit AMOMinterRemoved(amo_minter_addr); } function setCollateralPrice(uint256 col_idx, uint256 _new_price) external onlyByOwnGov { collateral_prices[col_idx] = _new_price; emit CollateralPriceSet(col_idx, _new_price); } // Could also be called toggleCollateral function toggleCollateral(uint256 col_idx) external onlyByOwnGov { address col_address = collateral_addresses[col_idx]; enabled_collaterals[col_address] = !enabled_collaterals[col_address]; emit CollateralToggled(col_idx, enabled_collaterals[col_address]); } function setPoolCeiling(uint256 col_idx, uint256 new_ceiling) external onlyByOwnGov { pool_ceilings[col_idx] = new_ceiling; emit PoolCeilingSet(col_idx, new_ceiling); } function setFees(uint256 col_idx, uint256 new_mint_fee, uint256 new_redeem_fee, uint256 new_buyback_fee, uint256 new_recollat_fee) external onlyByOwnGov { minting_fee[col_idx] = new_mint_fee; redemption_fee[col_idx] = new_redeem_fee; buyback_fee[col_idx] = new_buyback_fee; recollat_fee[col_idx] = new_recollat_fee; emit FeesSet(col_idx, new_mint_fee, new_redeem_fee, new_buyback_fee, new_recollat_fee); } function setPoolParameters(uint256 new_bonus_rate, uint256 new_redemption_delay) external onlyByOwnGov { bonus_rate = new_bonus_rate; redemption_delay = new_redemption_delay; emit PoolParametersSet(new_bonus_rate, new_redemption_delay); } function setPriceThresholds(uint256 new_mint_price_threshold, uint256 new_redeem_price_threshold) external onlyByOwnGov { mint_price_threshold = new_mint_price_threshold; redeem_price_threshold = new_redeem_price_threshold; emit PriceThresholdsSet(new_mint_price_threshold, new_redeem_price_threshold); } function setBbkRctPerHour(uint256 _bbkMaxColE18OutPerHour, uint256 _rctMaxFxsOutPerHour) external onlyByOwnGov { bbkMaxColE18OutPerHour = _bbkMaxColE18OutPerHour; rctMaxFxsOutPerHour = _rctMaxFxsOutPerHour; emit BbkRctPerHourSet(_bbkMaxColE18OutPerHour, _rctMaxFxsOutPerHour); } // Set the Chainlink oracles function setOracles(address _frax_usd_chainlink_addr, address _fxs_usd_chainlink_addr) external onlyByOwnGov { // Set the instances priceFeedFRAXUSD = AggregatorV3Interface(_frax_usd_chainlink_addr); priceFeedFXSUSD = AggregatorV3Interface(_fxs_usd_chainlink_addr); // Set the decimals chainlink_frax_usd_decimals = priceFeedFRAXUSD.decimals(); chainlink_fxs_usd_decimals = priceFeedFXSUSD.decimals(); emit OraclesSet(_frax_usd_chainlink_addr, _fxs_usd_chainlink_addr); } function setCustodian(address new_custodian) external onlyByOwnGov { custodian_address = new_custodian; emit CustodianSet(new_custodian); } function setTimelock(address new_timelock) external onlyByOwnGov { timelock_address = new_timelock; emit TimelockSet(new_timelock); } /* ========== EVENTS ========== */ event CollateralToggled(uint256 col_idx, bool new_state); event PoolCeilingSet(uint256 col_idx, uint256 new_ceiling); event FeesSet(uint256 col_idx, uint256 new_mint_fee, uint256 new_redeem_fee, uint256 new_buyback_fee, uint256 new_recollat_fee); event PoolParametersSet(uint256 new_bonus_rate, uint256 new_redemption_delay); event PriceThresholdsSet(uint256 new_bonus_rate, uint256 new_redemption_delay); event BbkRctPerHourSet(uint256 bbkMaxColE18OutPerHour, uint256 rctMaxFxsOutPerHour); event AMOMinterAdded(address amo_minter_addr); event AMOMinterRemoved(address amo_minter_addr); event OraclesSet(address frax_usd_chainlink_addr, address fxs_usd_chainlink_addr); event CustodianSet(address new_custodian); event TimelockSet(address new_timelock); event MRBRToggled(uint256 col_idx, uint8 tog_idx); event CollateralPriceSet(uint256 col_idx, uint256 new_price); } // File contracts/Frax/Pools/IFraxPool.sol interface IFraxPool { function minting_fee() external returns (uint256); function redeemCollateralBalances(address addr) external returns (uint256); function redemption_fee() external returns (uint256); function buyback_fee() external returns (uint256); function recollat_fee() external returns (uint256); function collatDollarBalance() external returns (uint256); function availableExcessCollatDV() external returns (uint256); function getCollateralPrice() external returns (uint256); function setCollatETHOracle(address _collateral_weth_oracle_address, address _weth_address) external; function mint1t1FRAX(uint256 collateral_amount, uint256 FRAX_out_min) external; function mintAlgorithmicFRAX(uint256 fxs_amount_d18, uint256 FRAX_out_min) external; function mintFractionalFRAX(uint256 collateral_amount, uint256 fxs_amount, uint256 FRAX_out_min) external; function redeem1t1FRAX(uint256 FRAX_amount, uint256 COLLATERAL_out_min) external; function redeemFractionalFRAX(uint256 FRAX_amount, uint256 FXS_out_min, uint256 COLLATERAL_out_min) external; function redeemAlgorithmicFRAX(uint256 FRAX_amount, uint256 FXS_out_min) external; function collectRedemption() external; function recollateralizeFRAX(uint256 collateral_amount, uint256 FXS_out_min) external; function buyBackFXS(uint256 FXS_amount, uint256 COLLATERAL_out_min) external; function toggleMinting() external; function toggleRedeeming() external; function toggleRecollateralize() external; function toggleBuyBack() external; function toggleCollateralPrice(uint256 _new_price) external; function setPoolParameters(uint256 new_ceiling, uint256 new_bonus_rate, uint256 new_redemption_delay, uint256 new_mint_fee, uint256 new_redeem_fee, uint256 new_buyback_fee, uint256 new_recollat_fee) external; function setTimelock(address new_timelock) external; function setOwner(address _owner_address) external; } // File contracts/Misc_AMOs/IAMO.sol pragma experimental ABIEncoderV2; interface IAMO { function dollarBalances() external view returns (uint256 frax_val_e18, uint256 collat_val_e18); } // File contracts/Frax/FraxAMOMinter.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // =========================== FraxAMOMinter ========================== // ==================================================================== // globalCollateralValue() in Frax.sol is gassy because of the loop and all of the AMOs attached to it. // This minter would be single mint point for all of the AMOs, and would track the collatDollarBalance with a // state variable after any mint occurs, or manually with a sync() call // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Travis Moore: https://github.com/FortisFortuna // Reviewer(s) / Contributor(s) // Jason Huan: https://github.com/jasonhuan // Sam Kazemian: https://github.com/samkazemian // Dennis: github.com/denett // Hameed contract FraxAMOMinter is Owned { // SafeMath automatically included in Solidity >= 8.0.0 /* ========== STATE VARIABLES ========== */ // Core IFrax public FRAX = IFrax(0x853d955aCEf822Db058eb8505911ED77F175b99e); IFxs public FXS = IFxs(0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0); ERC20 public collateral_token; FraxPoolV3 public pool = FraxPoolV3(0x2fE065e6FFEf9ac95ab39E5042744d695F560729); IFraxPool public old_pool = IFraxPool(0x1864Ca3d47AaB98Ee78D11fc9DCC5E7bADdA1c0d); address public timelock_address; address public custodian_address; // Collateral related address public collateral_address; uint256 public col_idx; // AMO addresses address[] public amos_array; mapping(address => bool) public amos; // Mapping is also used for faster verification // Price constants uint256 private constant PRICE_PRECISION = 1e6; // Max amount of collateral the contract can borrow from the FraxPool int256 public collat_borrow_cap = int256(10000000e6); // Max amount of FRAX and FXS this contract can mint int256 public frax_mint_cap = int256(100000000e18); int256 public fxs_mint_cap = int256(100000000e18); // Minimum collateral ratio needed for new FRAX minting uint256 public min_cr = 810000; // Frax mint balances mapping(address => int256) public frax_mint_balances; // Amount of FRAX the contract minted, by AMO int256 public frax_mint_sum = 0; // Across all AMOs // Fxs mint balances mapping(address => int256) public fxs_mint_balances; // Amount of FXS the contract minted, by AMO int256 public fxs_mint_sum = 0; // Across all AMOs // Collateral borrowed balances mapping(address => int256) public collat_borrowed_balances; // Amount of collateral the contract borrowed, by AMO int256 public collat_borrowed_sum = 0; // Across all AMOs // FRAX balance related uint256 public fraxDollarBalanceStored = 0; // Collateral balance related uint256 public missing_decimals; uint256 public collatDollarBalanceStored = 0; // AMO balance corrections mapping(address => int256[2]) public correction_offsets_amos; // [amo_address][0] = AMO's frax_val_e18 // [amo_address][1] = AMO's collat_val_e18 /* ========== CONSTRUCTOR ========== */ constructor ( address _owner_address, address _custodian_address, address _timelock_address, address _collateral_address, address _pool_address ) Owned(_owner_address) { custodian_address = _custodian_address; timelock_address = _timelock_address; // Pool related pool = FraxPoolV3(_pool_address); // Collateral related collateral_address = _collateral_address; col_idx = pool.collateralAddrToIdx(_collateral_address); collateral_token = ERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); missing_decimals = uint(18) - collateral_token.decimals(); } /* ========== MODIFIERS ========== */ modifier onlyByOwnGov() { require(msg.sender == timelock_address || msg.sender == owner, "Not owner or timelock"); _; } modifier validAMO(address amo_address) { require(amos[amo_address], "Invalid AMO"); _; } /* ========== VIEWS ========== */ function collatDollarBalance() external view returns (uint256) { (, uint256 collat_val_e18) = dollarBalances(); return collat_val_e18; } function dollarBalances() public view returns (uint256 frax_val_e18, uint256 collat_val_e18) { frax_val_e18 = fraxDollarBalanceStored; collat_val_e18 = collatDollarBalanceStored; } function allAMOAddresses() external view returns (address[] memory) { return amos_array; } function allAMOsLength() external view returns (uint256) { return amos_array.length; } function fraxTrackedGlobal() external view returns (int256) { return int256(fraxDollarBalanceStored) - frax_mint_sum - (collat_borrowed_sum * int256(10 ** missing_decimals)); } function fraxTrackedAMO(address amo_address) external view returns (int256) { (uint256 frax_val_e18, ) = IAMO(amo_address).dollarBalances(); int256 frax_val_e18_corrected = int256(frax_val_e18) + correction_offsets_amos[amo_address][0]; return frax_val_e18_corrected - frax_mint_balances[amo_address] - ((collat_borrowed_balances[amo_address]) * int256(10 ** missing_decimals)); } /* ========== PUBLIC FUNCTIONS ========== */ // Callable by anyone willing to pay the gas function syncDollarBalances() public { uint256 total_frax_value_d18 = 0; uint256 total_collateral_value_d18 = 0; for (uint i = 0; i < amos_array.length; i++){ // Exclude null addresses address amo_address = amos_array[i]; if (amo_address != address(0)){ (uint256 frax_val_e18, uint256 collat_val_e18) = IAMO(amo_address).dollarBalances(); total_frax_value_d18 += uint256(int256(frax_val_e18) + correction_offsets_amos[amo_address][0]); total_collateral_value_d18 += uint256(int256(collat_val_e18) + correction_offsets_amos[amo_address][1]); } } fraxDollarBalanceStored = total_frax_value_d18; collatDollarBalanceStored = total_collateral_value_d18; } /* ========== OLD POOL / BACKWARDS COMPATIBILITY ========== */ function oldPoolRedeem(uint256 frax_amount) external onlyByOwnGov { uint256 redemption_fee = old_pool.redemption_fee(); uint256 col_price_usd = old_pool.getCollateralPrice(); uint256 global_collateral_ratio = FRAX.global_collateral_ratio(); uint256 redeem_amount_E6 = ((frax_amount * (uint256(1e6) - redemption_fee)) / 1e6) / (10 ** missing_decimals); uint256 expected_collat_amount = (redeem_amount_E6 * global_collateral_ratio) / 1e6; expected_collat_amount = (expected_collat_amount * 1e6) / col_price_usd; require((collat_borrowed_sum + int256(expected_collat_amount)) <= collat_borrow_cap, "Borrow cap"); collat_borrowed_sum += int256(expected_collat_amount); // Mint the frax FRAX.pool_mint(address(this), frax_amount); // Redeem the frax FRAX.approve(address(old_pool), frax_amount); old_pool.redeemFractionalFRAX(frax_amount, 0, 0); } function oldPoolCollectAndGive(address destination_amo) external onlyByOwnGov validAMO(destination_amo) { // Get the amount to be collected uint256 collat_amount = old_pool.redeemCollateralBalances(address(this)); // Collect the redemption old_pool.collectRedemption(); // Mark the destination amo's borrowed amount collat_borrowed_balances[destination_amo] += int256(collat_amount); // Give the collateral to the AMO TransferHelper.safeTransfer(collateral_address, destination_amo, collat_amount); // Sync syncDollarBalances(); } /* ========== OWNER / GOVERNANCE FUNCTIONS ONLY ========== */ // Only owner or timelock can call, to limit risk // ------------------------------------------------------------------ // ------------------------------ FRAX ------------------------------ // ------------------------------------------------------------------ // This contract is essentially marked as a 'pool' so it can call OnlyPools functions like pool_mint and pool_burn_from // on the main FRAX contract function mintFraxForAMO(address destination_amo, uint256 frax_amount) external onlyByOwnGov validAMO(destination_amo) { int256 frax_amt_i256 = int256(frax_amount); // Make sure you aren't minting more than the mint cap require((frax_mint_sum + frax_amt_i256) <= frax_mint_cap, "Mint cap reached"); frax_mint_balances[destination_amo] += frax_amt_i256; frax_mint_sum += frax_amt_i256; // Make sure the FRAX minting wouldn't push the CR down too much // This is also a sanity check for the int256 math uint256 current_collateral_E18 = FRAX.globalCollateralValue(); uint256 cur_frax_supply = FRAX.totalSupply(); uint256 new_frax_supply = cur_frax_supply + frax_amount; uint256 new_cr = (current_collateral_E18 * PRICE_PRECISION) / new_frax_supply; require(new_cr >= min_cr, "CR would be too low"); // Mint the FRAX to the AMO FRAX.pool_mint(destination_amo, frax_amount); // Sync syncDollarBalances(); } function burnFraxFromAMO(uint256 frax_amount) external validAMO(msg.sender) { int256 frax_amt_i256 = int256(frax_amount); // Burn first FRAX.pool_burn_from(msg.sender, frax_amount); // Then update the balances frax_mint_balances[msg.sender] -= frax_amt_i256; frax_mint_sum -= frax_amt_i256; // Sync syncDollarBalances(); } // ------------------------------------------------------------------ // ------------------------------- FXS ------------------------------ // ------------------------------------------------------------------ function mintFxsForAMO(address destination_amo, uint256 fxs_amount) external onlyByOwnGov validAMO(destination_amo) { int256 fxs_amt_i256 = int256(fxs_amount); // Make sure you aren't minting more than the mint cap require((fxs_mint_sum + fxs_amt_i256) <= fxs_mint_cap, "Mint cap reached"); fxs_mint_balances[destination_amo] += fxs_amt_i256; fxs_mint_sum += fxs_amt_i256; // Mint the FXS to the AMO FXS.pool_mint(destination_amo, fxs_amount); // Sync syncDollarBalances(); } function burnFxsFromAMO(uint256 fxs_amount) external validAMO(msg.sender) { int256 fxs_amt_i256 = int256(fxs_amount); // Burn first FXS.pool_burn_from(msg.sender, fxs_amount); // Then update the balances fxs_mint_balances[msg.sender] -= fxs_amt_i256; fxs_mint_sum -= fxs_amt_i256; // Sync syncDollarBalances(); } // ------------------------------------------------------------------ // --------------------------- Collateral --------------------------- // ------------------------------------------------------------------ function giveCollatToAMO( address destination_amo, uint256 collat_amount ) external onlyByOwnGov validAMO(destination_amo) { int256 collat_amount_i256 = int256(collat_amount); require((collat_borrowed_sum + collat_amount_i256) <= collat_borrow_cap, "Borrow cap"); collat_borrowed_balances[destination_amo] += collat_amount_i256; collat_borrowed_sum += collat_amount_i256; // Borrow the collateral pool.amoMinterBorrow(collat_amount); // Give the collateral to the AMO TransferHelper.safeTransfer(collateral_address, destination_amo, collat_amount); // Sync syncDollarBalances(); } function receiveCollatFromAMO(uint256 usdc_amount) external validAMO(msg.sender) { int256 collat_amt_i256 = int256(usdc_amount); // Give back first TransferHelper.safeTransferFrom(collateral_address, msg.sender, address(pool), usdc_amount); // Then update the balances collat_borrowed_balances[msg.sender] -= collat_amt_i256; collat_borrowed_sum -= collat_amt_i256; // Sync syncDollarBalances(); } /* ========== RESTRICTED GOVERNANCE FUNCTIONS ========== */ // Adds an AMO function addAMO(address amo_address, bool sync_too) public onlyByOwnGov { require(amo_address != address(0), "Zero address detected"); (uint256 frax_val_e18, uint256 collat_val_e18) = IAMO(amo_address).dollarBalances(); require(frax_val_e18 >= 0 && collat_val_e18 >= 0, "Invalid AMO"); require(amos[amo_address] == false, "Address already exists"); amos[amo_address] = true; amos_array.push(amo_address); // Mint balances frax_mint_balances[amo_address] = 0; fxs_mint_balances[amo_address] = 0; collat_borrowed_balances[amo_address] = 0; // Offsets correction_offsets_amos[amo_address][0] = 0; correction_offsets_amos[amo_address][1] = 0; if (sync_too) syncDollarBalances(); emit AMOAdded(amo_address); } // Removes an AMO function removeAMO(address amo_address, bool sync_too) public onlyByOwnGov { require(amo_address != address(0), "Zero address detected"); require(amos[amo_address] == true, "Address nonexistant"); // Delete from the mapping delete amos[amo_address]; // 'Delete' from the array by setting the address to 0x0 for (uint i = 0; i < amos_array.length; i++){ if (amos_array[i] == amo_address) { amos_array[i] = address(0); // This will leave a null in the array and keep the indices the same break; } } if (sync_too) syncDollarBalances(); emit AMORemoved(amo_address); } function setTimelock(address new_timelock) external onlyByOwnGov { require(new_timelock != address(0), "Timelock address cannot be 0"); timelock_address = new_timelock; } function setCustodian(address _custodian_address) external onlyByOwnGov { require(_custodian_address != address(0), "Custodian address cannot be 0"); custodian_address = _custodian_address; } function setFraxMintCap(uint256 _frax_mint_cap) external onlyByOwnGov { frax_mint_cap = int256(_frax_mint_cap); } function setFxsMintCap(uint256 _fxs_mint_cap) external onlyByOwnGov { fxs_mint_cap = int256(_fxs_mint_cap); } function setCollatBorrowCap(uint256 _collat_borrow_cap) external onlyByOwnGov { collat_borrow_cap = int256(_collat_borrow_cap); } function setMinimumCollateralRatio(uint256 _min_cr) external onlyByOwnGov { min_cr = _min_cr; } function setAMOCorrectionOffsets(address amo_address, int256 frax_e18_correction, int256 collat_e18_correction) external onlyByOwnGov { correction_offsets_amos[amo_address][0] = frax_e18_correction; correction_offsets_amos[amo_address][1] = collat_e18_correction; syncDollarBalances(); } function setFraxPool(address _pool_address) external onlyByOwnGov { pool = FraxPoolV3(_pool_address); // Make sure the collaterals match, or balances could get corrupted require(pool.collateralAddrToIdx(collateral_address) == col_idx, "col_idx mismatch"); } function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyByOwnGov { // Can only be triggered by owner or governance TransferHelper.safeTransfer(tokenAddress, owner, tokenAmount); emit Recovered(tokenAddress, tokenAmount); } // Generic proxy function execute( address _to, uint256 _value, bytes calldata _data ) external onlyByOwnGov returns (bool, bytes memory) { (bool success, bytes memory result) = _to.call{value:_value}(_data); return (success, result); } /* ========== EVENTS ========== */ event AMOAdded(address amo_address); event AMORemoved(address amo_address); event Recovered(address token, uint256 amount); }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner_address","type":"address"},{"internalType":"address","name":"_custodian_address","type":"address"},{"internalType":"address","name":"_timelock_address","type":"address"},{"internalType":"address","name":"_collateral_address","type":"address"},{"internalType":"address","name":"_pool_address","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"amo_address","type":"address"}],"name":"AMOAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"amo_address","type":"address"}],"name":"AMORemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Recovered","type":"event"},{"inputs":[],"name":"FRAX","outputs":[{"internalType":"contract IFrax","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FXS","outputs":[{"internalType":"contract IFxs","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"amo_address","type":"address"},{"internalType":"bool","name":"sync_too","type":"bool"}],"name":"addAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"allAMOAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"allAMOsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"amos","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"amos_array","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"frax_amount","type":"uint256"}],"name":"burnFraxFromAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fxs_amount","type":"uint256"}],"name":"burnFxsFromAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"col_idx","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatDollarBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collatDollarBalanceStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collat_borrow_cap","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collat_borrowed_balances","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collat_borrowed_sum","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateral_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateral_token","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"correction_offsets_amos","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"custodian_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dollarBalances","outputs":[{"internalType":"uint256","name":"frax_val_e18","type":"uint256"},{"internalType":"uint256","name":"collat_val_e18","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"execute","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fraxDollarBalanceStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"amo_address","type":"address"}],"name":"fraxTrackedAMO","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fraxTrackedGlobal","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"frax_mint_balances","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"frax_mint_cap","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"frax_mint_sum","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"fxs_mint_balances","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxs_mint_cap","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fxs_mint_sum","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_amo","type":"address"},{"internalType":"uint256","name":"collat_amount","type":"uint256"}],"name":"giveCollatToAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"min_cr","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_amo","type":"address"},{"internalType":"uint256","name":"frax_amount","type":"uint256"}],"name":"mintFraxForAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination_amo","type":"address"},{"internalType":"uint256","name":"fxs_amount","type":"uint256"}],"name":"mintFxsForAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"missing_decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination_amo","type":"address"}],"name":"oldPoolCollectAndGive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"frax_amount","type":"uint256"}],"name":"oldPoolRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"old_pool","outputs":[{"internalType":"contract IFraxPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract FraxPoolV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"usdc_amount","type":"uint256"}],"name":"receiveCollatFromAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"recoverERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"amo_address","type":"address"},{"internalType":"bool","name":"sync_too","type":"bool"}],"name":"removeAMO","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"amo_address","type":"address"},{"internalType":"int256","name":"frax_e18_correction","type":"int256"},{"internalType":"int256","name":"collat_e18_correction","type":"int256"}],"name":"setAMOCorrectionOffsets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_collat_borrow_cap","type":"uint256"}],"name":"setCollatBorrowCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_custodian_address","type":"address"}],"name":"setCustodian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_frax_mint_cap","type":"uint256"}],"name":"setFraxMintCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_pool_address","type":"address"}],"name":"setFraxPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_fxs_mint_cap","type":"uint256"}],"name":"setFxsMintCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_min_cr","type":"uint256"}],"name":"setMinimumCollateralRatio","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"new_timelock","type":"address"}],"name":"setTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"syncDollarBalances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"timelock_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052600280546001600160a01b031990811673853d955acef822db058eb8505911ed77f175b99e17909155600380548216733432b6a60d23ca0dfca7761b7ab56459d9c964d0179055600580548216732fe065e6ffef9ac95ab39e5042744d695f56072917905560068054909116731864ca3d47aab98ee78d11fc9dcc5e7badda1c0d1790556509184e72a000600d556a52b7d2dcc80cd2e4000000600e819055600f55620c5c1060105560006012819055601481905560168190556017819055601955348015620000d357600080fd5b506040516200431638038062004316833981016040819052620000f6916200033f565b846001600160a01b038116620001525760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015260640160405180910390fd5b600080546001600160a01b0319166001600160a01b03831690811782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a150600880546001600160a01b038681166001600160a01b0319928316179092556007805486841690831617905560058054848416908316811790915560098054938616939092168317909155604051636d8f2e4f60e11b815260048101929092529063db1e5c9e9060240160206040518083038186803b1580156200022d57600080fd5b505afa15801562000242573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002689190620003af565b600a55600480546001600160a01b03191673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4890811782556040805163313ce56760e01b81529051919263313ce567928282019260209290829003018186803b158015620002c857600080fd5b505afa158015620002dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003039190620003c9565b620003139060ff166012620003f5565b601855506200041b9350505050565b80516001600160a01b03811681146200033a57600080fd5b919050565b600080600080600060a086880312156200035857600080fd5b620003638662000322565b9450620003736020870162000322565b9350620003836040870162000322565b9250620003936060870162000322565b9150620003a36080870162000322565b90509295509295909350565b600060208284031215620003c257600080fd5b5051919050565b600060208284031215620003dc57600080fd5b815160ff81168114620003ee57600080fd5b9392505050565b6000828210156200041657634e487b7160e01b600052601160045260246000fd5b500390565b613eeb806200042b6000396000f3fe608060405234801561001057600080fd5b50600436106103785760003560e01c8063725adbdd116101d3578063b61d27f611610104578063dc6663c7116100a2578063e97d85a51161007c578063e97d85a5146107ee578063eaff6bba146107f7578063f5158e0014610800578063f87d29331461080857600080fd5b8063dc6663c7146107a6578063e05261ec146107c6578063e5d47fe0146107db57600080fd5b8063c6428b5f116100de578063c6428b5f1461076f578063cd71678e14610782578063d819eab51461078a578063d8ad1eed1461079357600080fd5b8063b61d27f614610708578063bda767ab14610729578063bdacb3031461075c57600080fd5b806390c3a206116101715780639d7576761161014b5780639d757676146106a7578063a4c3e73c146106ba578063ae38b182146106d5578063b0e4556f146106e857600080fd5b806390c3a2061461066e57806394582327146106815780639aa776ce1461069457600080fd5b80638980f11f116101ad5780638980f11f146106295780638b4433961461063c5780638da5cb5b1461064557806390074a511461066557600080fd5b8063725adbdd146105ee57806379ba5097146106015780637ce6112b1461060957600080fd5b80633a6e2f07116102ad578063526b1dfb1161024b5780636325890d116102255780636325890d146105ac5780636c052939146105b557806370bef0af146105c857806370c59475146105db57600080fd5b8063526b1dfb1461057057806353a47bb71461057957806360fdf1751461059957600080fd5b8063403f373111610287578063403f37311461052157806349696b20146105345780634ed67d9b14610547578063504ab9121461055057600080fd5b80633a6e2f07146104ef5780633ed4e55c1461050f5780633f10ecbe1461051857600080fd5b80631eaa0e171161031a5780632621db2f116102f45780632621db2f146104a057806326d9fc86146104c057806336082ac0146104d357806337ae1b82146104dc57600080fd5b80631eaa0e171461044d578063200ea2221461046d5780632245904c1461048d57600080fd5b806310b5ed651161035657806310b5ed65146103fd5780631627540c1461041057806316f0115b1461042557806317284c941461044557600080fd5b8063052ed9751461037d5780630cf2cb55146103c75780630edcfbe9146103f5575b600080fd5b60065461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6103e76103d53660046137e7565b60156020526000908152604090205481565b6040519081526020016103be565b6103e761081b565b6103e761040b36600461386c565b610858565b61042361041e3660046137e7565b61087d565b005b60055461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103e76109a2565b60095461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b60035461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61042361049b36600461386c565b6109b9565b60045461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6104236104ce36600461393a565b610e39565b6103e760105481565b6104236104ea36600461393a565b610f2b565b6103e76104fd3660046137e7565b60136020526000908152604090205481565b6103e760185481565b6103e760125481565b61042361052f3660046137e7565b610fd3565b61039d61054236600461393a565b61113a565b6103e7600f5481565b6103e761055e3660046137e7565b60116020526000908152604090205481565b6103e760165481565b60015461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6104236105a73660046137e7565b611171565b6103e760195481565b6104236105c3366004613802565b61134f565b6104236105d636600461386c565b61167c565b6104236105e936600461393a565b611919565b6104236105fc3660046137e7565b611a55565b610423611d17565b60085461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61042361063736600461386c565b611e62565b6103e7600a5481565b60005461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103e760175481565b61042361067c36600461386c565b611f76565b61042361068f366004613802565b61222a565b6104236106a236600461393a565b612592565b6104236106b536600461393a565b612afd565b601754601954604080519283526020830191909152016103be565b6103e76106e33660046137e7565b612ba5565b60025461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61071b610716366004613896565b612cdd565b6040516103be929190613a16565b61074c6107373660046137e7565b600c6020526000908152604090205460ff1681565b60405190151581526020016103be565b61042361076a3660046137e7565b612e03565b61042361077d36600461393a565b612f6a565b600b546103e7565b6103e7600e5481565b6104236107a136600461393a565b613012565b60075461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6107ce6130ba565b6040516103be91906139bc565b6104236107e936600461393a565b613129565b6103e7600d5481565b6103e760145481565b610423613265565b610423610816366004613839565b6133d7565b6000601854600a61082c9190613b98565b6016546108399190613c60565b6012546017546108499190613d59565b6108539190613d59565b905090565b601a602052816000526040600020816002811061087457600080fd5b01549150829050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b6000806109b26017546019549091565b9392505050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806109f6575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610a5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff16610aed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600e54601254839190610b01908390613a70565b1315610b69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d696e74206361702072656163686564000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff841660009081526011602052604081208054839290610b9e908490613a70565b925050819055508060126000828254610bb79190613a70565b9091555050600254604080517fd2d97b06000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163d2d97b06916004808301926020929190829003018186803b158015610c2757600080fd5b505afa158015610c3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5f9190613953565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ccb57600080fd5b505afa158015610cdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d039190613953565b90506000610d118683613ae4565b9050600081610d23620f424086613d1c565b610d2d9190613afc565b9050601054811015610d9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f435220776f756c6420626520746f6f206c6f77000000000000000000000000006044820152606401610920565b6002546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a81166004830152602482018a90529091169063b4f56b2690604401600060405180830381600087803b158015610e0f57600080fd5b505af1158015610e23573d6000803e3d6000fd5b50505050610e2f613265565b5050505050505050565b336000818152600c602052604090205460ff16610eb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6009546005548391610ee09173ffffffffffffffffffffffffffffffffffffffff91821691339116846134b0565b3360009081526015602052604081208054839290610eff908490613d59565b925050819055508060166000828254610f189190613d59565b90915550610f269050613265565b505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480610f68575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600d55565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611010575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff81166110f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437573746f6469616e20616464726573732063616e6e6f7420626520300000006044820152606401610920565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600b818154811061114a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60075473ffffffffffffffffffffffffffffffffffffffff163314806111ae575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600a546009546040517fdb1e5c9e000000000000000000000000000000000000000000000000000000008152931660048401529163db1e5c9e9060240160206040518083038186803b1580156112ad57600080fd5b505afa1580156112c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e59190613953565b1461134c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f636f6c5f696478206d69736d61746368000000000000000000000000000000006044820152606401610920565b50565b60075473ffffffffffffffffffffffffffffffffffffffff1633148061138c575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6113f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff821661146f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c602052604090205460ff161515600114611503576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f41646472657373206e6f6e6578697374616e74000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600b5481101561161f578273ffffffffffffffffffffffffffffffffffffffff16600b828154811061158357611583613e78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561160d576000600b82815481106115c0576115c0613e78565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061161f565b8061161781613e10565b91505061154f565b50801561162e5761162e613265565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fcfdb9256a3d90cc6d479617ca43d8c8d264a9f5fe7f480029c4d918862c46db4906020015b60405180910390a15050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806116b9575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61171f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff166117b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600f546014548391906117c4908390613a70565b131561182c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d696e74206361702072656163686564000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604081208054839290611861908490613a70565b92505081905550806014600082825461187a9190613a70565b90915550506003546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690529091169063b4f56b2690604401600060405180830381600087803b1580156118f357600080fd5b505af1158015611907573d6000803e3d6000fd5b50505050611913613265565b50505050565b336000818152600c602052604090205460ff16611992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6002546040517fa8a778ae00000000000000000000000000000000000000000000000000000000815233600482015260248101849052839173ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b158015611a0457600080fd5b505af1158015611a18573d6000803e3d6000fd5b50503360009081526011602052604081208054859450909250611a3c908490613d59565b925050819055508060126000828254610f189190613d59565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611a92575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611af8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600c6020526040902054819060ff16611b89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6006546040517f08a7493d00000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906308a7493d90602401602060405180830381600087803b158015611bf557600080fd5b505af1158015611c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2d9190613953565b9050600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312ace5a26040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c9957600080fd5b505af1158015611cad573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff831660009081526015602052604081208054839290611ce6908490613a70565b9091555050600954611d0f9073ffffffffffffffffffffffffffffffffffffffff16848361364e565b610f26613265565b60015473ffffffffffffffffffffffffffffffffffffffff163314611dbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610920565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611e9f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611f05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600054611f2a90839073ffffffffffffffffffffffffffffffffffffffff168361364e565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa289101611670565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611fb3575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612019576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff166120aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600d546016548391906120be908390613a70565b1315612126576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f426f72726f7720636170000000000000000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601560205260408120805483929061215b908490613a70565b9250508190555080601660008282546121749190613a70565b90915550506005546040517f9aae55a70000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff90911690639aae55a790602401600060405180830381600087803b1580156121e557600080fd5b505af11580156121f9573d6000803e3d6000fd5b5050600954612222925073ffffffffffffffffffffffffffffffffffffffff169050858561364e565b611913613265565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612267575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6122cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff821661234a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610920565b6000808373ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b15801561239257600080fd5b505afa1580156123a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ca919061396c565b909250905073ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604090205460ff161561245f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4164647265737320616c726561647920657869737473000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155600b80548083019091557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180547fffffffffffffffffffffffff000000000000000000000000000000000000000016909517909455601182528083208390556013825280832083905560158252808320839055601a909152812081815590910155821561254357612543613265565b60405173ffffffffffffffffffffffffffffffffffffffff851681527faa5bd6bda335b0c74f281b4b10d444ed06cd74963d7d77daa9a274eb4a7b36399060200160405180910390a150505050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806125cf575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612635576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600654604080517fcb73999f000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cb73999f91600480830192602092919082900301818787803b1580156126a157600080fd5b505af11580156126b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d99190613953565b90506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f7683bbc6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561274757600080fd5b505af115801561275b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277f9190613953565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127eb57600080fd5b505afa1580156127ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128239190613953565b90506000601854600a6128369190613b98565b620f42406128448682613dcd565b61284e9088613d1c565b6128589190613afc565b6128629190613afc565b90506000620f42406128748484613d1c565b61287e9190613afc565b90508361288e82620f4240613d1c565b6128989190613afc565b9050600d54816016546128ab9190613a70565b1315612913576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f426f72726f7720636170000000000000000000000000000000000000000000006044820152606401610920565b80601660008282546129259190613a70565b90915550506002546040517fb4f56b260000000000000000000000000000000000000000000000000000000081523060048201526024810188905273ffffffffffffffffffffffffffffffffffffffff9091169063b4f56b2690604401600060405180830381600087803b15801561299c57600080fd5b505af11580156129b0573d6000803e3d6000fd5b50506002546006546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018b90529116925063095ea7b39150604401602060405180830381600087803b158015612a2a57600080fd5b505af1158015612a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a62919061391d565b506006546040517f7e108af900000000000000000000000000000000000000000000000000000000815260048101889052600060248201819052604482015273ffffffffffffffffffffffffffffffffffffffff90911690637e108af990606401600060405180830381600087803b158015612add57600080fd5b505af1158015612af1573d6000803e3d6000fd5b50505050505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612b3a575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612ba0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600f55565b6000808273ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b158015612bed57600080fd5b505afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c25919061396c565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601a602052604081205491925090612c5a9083613a70565b9050601854600a612c6b9190613b98565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260156020526040902054612c9b9190613c60565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260116020526040902054612ccb9083613d59565b612cd59190613d59565b949350505050565b60075460009060609073ffffffffffffffffffffffffffffffffffffffff16331480612d20575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612d86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b6000808773ffffffffffffffffffffffffffffffffffffffff16878787604051612db1929190613990565b60006040518083038185875af1925050503d8060008114612dee576040519150601f19603f3d011682016040523d82523d6000602084013e612df3565b606091505b5090999098509650505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612e40575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff8116612f23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f54696d656c6f636b20616464726573732063616e6e6f742062652030000000006044820152606401610920565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612fa7575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61300d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600e55565b60075473ffffffffffffffffffffffffffffffffffffffff1633148061304f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6130b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b601055565b6060600b80548060200260200160405190810160405280929190818152602001828054801561311f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116130f4575b5050505050905090565b336000818152600c602052604090205460ff166131a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6003546040517fa8a778ae00000000000000000000000000000000000000000000000000000000815233600482015260248101849052839173ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b15801561321457600080fd5b505af1158015613228573d6000803e3d6000fd5b5050336000908152601360205260408120805485945090925061324c908490613d59565b925050819055508060146000828254610f189190613d59565b60008060005b600b548110156133cb576000600b828154811061328a5761328a613e78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156133b8576000808273ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b1580156132fc57600080fd5b505afa158015613310573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613334919061396c565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601a602052604090205491935091506133699083613a70565b6133739087613ae4565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601a60205260409020909650600101546133a99082613a70565b6133b39086613ae4565b945050505b50806133c381613e10565b91505061326b565b50601791909155601955565b60075473ffffffffffffffffffffffffffffffffffffffff16331480613414575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61347a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601a60205260409020828155600101819055610f26613265565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161354f91906139a0565b6000604051808303816000865af19150503d806000811461358c576040519150601f19603f3d011682016040523d82523d6000602084013e613591565b606091505b50915091508180156135bb5750805115806135bb5750808060200190518101906135bb919061391d565b613646576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610920565b505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916136e591906139a0565b6000604051808303816000865af19150503d8060008114613722576040519150601f19603f3d011682016040523d82523d6000602084013e613727565b606091505b5091509150818015613751575080511580613751575080806020019051810190613751919061391d565b6137b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610920565b5050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146137e257600080fd5b919050565b6000602082840312156137f957600080fd5b6109b2826137be565b6000806040838503121561381557600080fd5b61381e836137be565b9150602083013561382e81613ea7565b809150509250929050565b60008060006060848603121561384e57600080fd5b613857846137be565b95602085013595506040909401359392505050565b6000806040838503121561387f57600080fd5b613888836137be565b946020939093013593505050565b600080600080606085870312156138ac57600080fd5b6138b5856137be565b935060208501359250604085013567ffffffffffffffff808211156138d957600080fd5b818701915087601f8301126138ed57600080fd5b8135818111156138fc57600080fd5b88602082850101111561390e57600080fd5b95989497505060200194505050565b60006020828403121561392f57600080fd5b81516109b281613ea7565b60006020828403121561394c57600080fd5b5035919050565b60006020828403121561396557600080fd5b5051919050565b6000806040838503121561397f57600080fd5b505080516020909101519092909150565b8183823760009101908152919050565b600082516139b2818460208701613de4565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015613a0a57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016139d8565b50909695505050505050565b82151581526040602082015260008251806040840152613a3d816060850160208701613de4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615613aaa57613aaa613e49565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615613ade57613ade613e49565b50500190565b60008219821115613af757613af7613e49565b500190565b600082613b32577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600181815b80851115613b9057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613b7657613b76613e49565b80851615613b8357918102915b93841c9390800290613b3c565b509250929050565b60006109b28383600082613bae57506001613c5a565b81613bbb57506000613c5a565b8160018114613bd15760028114613bdb57613bf7565b6001915050613c5a565b60ff841115613bec57613bec613e49565b50506001821b613c5a565b5060208310610133831016604e8410600b8410161715613c1a575081810a613c5a565b613c248383613b37565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613c5657613c56613e49565b0290505b92915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613ca157613ca1613e49565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615613cdc57613cdc613e49565b60008712925087820587128484161615613cf857613cf8613e49565b87850587128184161615613d0e57613d0e613e49565b505050929093029392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613d5457613d54613e49565b500290565b6000808312837f800000000000000000000000000000000000000000000000000000000000000001831281151615613d9357613d93613e49565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615613dc757613dc7613e49565b50500390565b600082821015613ddf57613ddf613e49565b500390565b60005b83811015613dff578181015183820152602001613de7565b838111156119135750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613e4257613e42613e49565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b801515811461134c57600080fdfea2646970667358221220d7505757b29efdbf7dd8a05f225e43d07f180164296d60d6c8815eede21ee64464736f6c63430008060033000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd20000000000000000000000005180db0237291a6449dda9ed33ad90a38787621c0000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000002fe065e6ffef9ac95ab39e5042744d695f560729
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103785760003560e01c8063725adbdd116101d3578063b61d27f611610104578063dc6663c7116100a2578063e97d85a51161007c578063e97d85a5146107ee578063eaff6bba146107f7578063f5158e0014610800578063f87d29331461080857600080fd5b8063dc6663c7146107a6578063e05261ec146107c6578063e5d47fe0146107db57600080fd5b8063c6428b5f116100de578063c6428b5f1461076f578063cd71678e14610782578063d819eab51461078a578063d8ad1eed1461079357600080fd5b8063b61d27f614610708578063bda767ab14610729578063bdacb3031461075c57600080fd5b806390c3a206116101715780639d7576761161014b5780639d757676146106a7578063a4c3e73c146106ba578063ae38b182146106d5578063b0e4556f146106e857600080fd5b806390c3a2061461066e57806394582327146106815780639aa776ce1461069457600080fd5b80638980f11f116101ad5780638980f11f146106295780638b4433961461063c5780638da5cb5b1461064557806390074a511461066557600080fd5b8063725adbdd146105ee57806379ba5097146106015780637ce6112b1461060957600080fd5b80633a6e2f07116102ad578063526b1dfb1161024b5780636325890d116102255780636325890d146105ac5780636c052939146105b557806370bef0af146105c857806370c59475146105db57600080fd5b8063526b1dfb1461057057806353a47bb71461057957806360fdf1751461059957600080fd5b8063403f373111610287578063403f37311461052157806349696b20146105345780634ed67d9b14610547578063504ab9121461055057600080fd5b80633a6e2f07146104ef5780633ed4e55c1461050f5780633f10ecbe1461051857600080fd5b80631eaa0e171161031a5780632621db2f116102f45780632621db2f146104a057806326d9fc86146104c057806336082ac0146104d357806337ae1b82146104dc57600080fd5b80631eaa0e171461044d578063200ea2221461046d5780632245904c1461048d57600080fd5b806310b5ed651161035657806310b5ed65146103fd5780631627540c1461041057806316f0115b1461042557806317284c941461044557600080fd5b8063052ed9751461037d5780630cf2cb55146103c75780630edcfbe9146103f5575b600080fd5b60065461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6103e76103d53660046137e7565b60156020526000908152604090205481565b6040519081526020016103be565b6103e761081b565b6103e761040b36600461386c565b610858565b61042361041e3660046137e7565b61087d565b005b60055461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103e76109a2565b60095461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b60035461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61042361049b36600461386c565b6109b9565b60045461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6104236104ce36600461393a565b610e39565b6103e760105481565b6104236104ea36600461393a565b610f2b565b6103e76104fd3660046137e7565b60136020526000908152604090205481565b6103e760185481565b6103e760125481565b61042361052f3660046137e7565b610fd3565b61039d61054236600461393a565b61113a565b6103e7600f5481565b6103e761055e3660046137e7565b60116020526000908152604090205481565b6103e760165481565b60015461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6104236105a73660046137e7565b611171565b6103e760195481565b6104236105c3366004613802565b61134f565b6104236105d636600461386c565b61167c565b6104236105e936600461393a565b611919565b6104236105fc3660046137e7565b611a55565b610423611d17565b60085461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61042361063736600461386c565b611e62565b6103e7600a5481565b60005461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6103e760175481565b61042361067c36600461386c565b611f76565b61042361068f366004613802565b61222a565b6104236106a236600461393a565b612592565b6104236106b536600461393a565b612afd565b601754601954604080519283526020830191909152016103be565b6103e76106e33660046137e7565b612ba5565b60025461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b61071b610716366004613896565b612cdd565b6040516103be929190613a16565b61074c6107373660046137e7565b600c6020526000908152604090205460ff1681565b60405190151581526020016103be565b61042361076a3660046137e7565b612e03565b61042361077d36600461393a565b612f6a565b600b546103e7565b6103e7600e5481565b6104236107a136600461393a565b613012565b60075461039d9073ffffffffffffffffffffffffffffffffffffffff1681565b6107ce6130ba565b6040516103be91906139bc565b6104236107e936600461393a565b613129565b6103e7600d5481565b6103e760145481565b610423613265565b610423610816366004613839565b6133d7565b6000601854600a61082c9190613b98565b6016546108399190613c60565b6012546017546108499190613d59565b6108539190613d59565b905090565b601a602052816000526040600020816002811061087457600080fd5b01549150829050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610929576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201527f6f726d207468697320616374696f6e000000000000000000000000000000000060648201526084015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229060200160405180910390a150565b6000806109b26017546019549091565b9392505050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806109f6575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610a5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff16610aed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600e54601254839190610b01908390613a70565b1315610b69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d696e74206361702072656163686564000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff841660009081526011602052604081208054839290610b9e908490613a70565b925050819055508060126000828254610bb79190613a70565b9091555050600254604080517fd2d97b06000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163d2d97b06916004808301926020929190829003018186803b158015610c2757600080fd5b505afa158015610c3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5f9190613953565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015610ccb57600080fd5b505afa158015610cdf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d039190613953565b90506000610d118683613ae4565b9050600081610d23620f424086613d1c565b610d2d9190613afc565b9050601054811015610d9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f435220776f756c6420626520746f6f206c6f77000000000000000000000000006044820152606401610920565b6002546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a81166004830152602482018a90529091169063b4f56b2690604401600060405180830381600087803b158015610e0f57600080fd5b505af1158015610e23573d6000803e3d6000fd5b50505050610e2f613265565b5050505050505050565b336000818152600c602052604090205460ff16610eb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6009546005548391610ee09173ffffffffffffffffffffffffffffffffffffffff91821691339116846134b0565b3360009081526015602052604081208054839290610eff908490613d59565b925050819055508060166000828254610f189190613d59565b90915550610f269050613265565b505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480610f68575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610fce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600d55565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611010575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611076576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff81166110f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437573746f6469616e20616464726573732063616e6e6f7420626520300000006044820152606401610920565b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600b818154811061114a57600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60075473ffffffffffffffffffffffffffffffffffffffff163314806111ae575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600a546009546040517fdb1e5c9e000000000000000000000000000000000000000000000000000000008152931660048401529163db1e5c9e9060240160206040518083038186803b1580156112ad57600080fd5b505afa1580156112c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e59190613953565b1461134c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f636f6c5f696478206d69736d61746368000000000000000000000000000000006044820152606401610920565b50565b60075473ffffffffffffffffffffffffffffffffffffffff1633148061138c575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6113f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff821661146f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c602052604090205460ff161515600114611503576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f41646472657373206e6f6e6578697374616e74000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555b600b5481101561161f578273ffffffffffffffffffffffffffffffffffffffff16600b828154811061158357611583613e78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16141561160d576000600b82815481106115c0576115c0613e78565b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061161f565b8061161781613e10565b91505061154f565b50801561162e5761162e613265565b60405173ffffffffffffffffffffffffffffffffffffffff831681527fcfdb9256a3d90cc6d479617ca43d8c8d264a9f5fe7f480029c4d918862c46db4906020015b60405180910390a15050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806116b9575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61171f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff166117b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600f546014548391906117c4908390613a70565b131561182c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f4d696e74206361702072656163686564000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff841660009081526013602052604081208054839290611861908490613a70565b92505081905550806014600082825461187a9190613a70565b90915550506003546040517fb4f56b2600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152602482018690529091169063b4f56b2690604401600060405180830381600087803b1580156118f357600080fd5b505af1158015611907573d6000803e3d6000fd5b50505050611913613265565b50505050565b336000818152600c602052604090205460ff16611992576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6002546040517fa8a778ae00000000000000000000000000000000000000000000000000000000815233600482015260248101849052839173ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b158015611a0457600080fd5b505af1158015611a18573d6000803e3d6000fd5b50503360009081526011602052604081208054859450909250611a3c908490613d59565b925050819055508060126000828254610f189190613d59565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611a92575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611af8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600c6020526040902054819060ff16611b89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6006546040517f08a7493d00000000000000000000000000000000000000000000000000000000815230600482015260009173ffffffffffffffffffffffffffffffffffffffff16906308a7493d90602401602060405180830381600087803b158015611bf557600080fd5b505af1158015611c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2d9190613953565b9050600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166312ace5a26040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611c9957600080fd5b505af1158015611cad573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff831660009081526015602052604081208054839290611ce6908490613a70565b9091555050600954611d0f9073ffffffffffffffffffffffffffffffffffffffff16848361364e565b610f26613265565b60015473ffffffffffffffffffffffffffffffffffffffff163314611dbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527f2063616e20616363657074206f776e65727368697000000000000000000000006064820152608401610920565b6000546001546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a160018054600080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff841617909155169055565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611e9f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b611f05576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600054611f2a90839073ffffffffffffffffffffffffffffffffffffffff168361364e565b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f8c1256b8896378cd5044f80c202f9772b9d77dc85c8a6eb51967210b09bfaa289101611670565b60075473ffffffffffffffffffffffffffffffffffffffff16331480611fb3575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612019576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600c6020526040902054829060ff166120aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b600d546016548391906120be908390613a70565b1315612126576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f426f72726f7720636170000000000000000000000000000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601560205260408120805483929061215b908490613a70565b9250508190555080601660008282546121749190613a70565b90915550506005546040517f9aae55a70000000000000000000000000000000000000000000000000000000081526004810185905273ffffffffffffffffffffffffffffffffffffffff90911690639aae55a790602401600060405180830381600087803b1580156121e557600080fd5b505af11580156121f9573d6000803e3d6000fd5b5050600954612222925073ffffffffffffffffffffffffffffffffffffffff169050858561364e565b611913613265565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612267575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6122cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff821661234a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f5a65726f206164647265737320646574656374656400000000000000000000006044820152606401610920565b6000808373ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b15801561239257600080fd5b505afa1580156123a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ca919061396c565b909250905073ffffffffffffffffffffffffffffffffffffffff84166000908152600c602052604090205460ff161561245f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4164647265737320616c726561647920657869737473000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600c6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001908117909155600b80548083019091557f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180547fffffffffffffffffffffffff000000000000000000000000000000000000000016909517909455601182528083208390556013825280832083905560158252808320839055601a909152812081815590910155821561254357612543613265565b60405173ffffffffffffffffffffffffffffffffffffffff851681527faa5bd6bda335b0c74f281b4b10d444ed06cd74963d7d77daa9a274eb4a7b36399060200160405180910390a150505050565b60075473ffffffffffffffffffffffffffffffffffffffff163314806125cf575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612635576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600654604080517fcb73999f000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cb73999f91600480830192602092919082900301818787803b1580156126a157600080fd5b505af11580156126b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126d99190613953565b90506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f7683bbc6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561274757600080fd5b505af115801561275b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277f9190613953565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632eb9771b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156127eb57600080fd5b505afa1580156127ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128239190613953565b90506000601854600a6128369190613b98565b620f42406128448682613dcd565b61284e9088613d1c565b6128589190613afc565b6128629190613afc565b90506000620f42406128748484613d1c565b61287e9190613afc565b90508361288e82620f4240613d1c565b6128989190613afc565b9050600d54816016546128ab9190613a70565b1315612913576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f426f72726f7720636170000000000000000000000000000000000000000000006044820152606401610920565b80601660008282546129259190613a70565b90915550506002546040517fb4f56b260000000000000000000000000000000000000000000000000000000081523060048201526024810188905273ffffffffffffffffffffffffffffffffffffffff9091169063b4f56b2690604401600060405180830381600087803b15801561299c57600080fd5b505af11580156129b0573d6000803e3d6000fd5b50506002546006546040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9182166004820152602481018b90529116925063095ea7b39150604401602060405180830381600087803b158015612a2a57600080fd5b505af1158015612a3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a62919061391d565b506006546040517f7e108af900000000000000000000000000000000000000000000000000000000815260048101889052600060248201819052604482015273ffffffffffffffffffffffffffffffffffffffff90911690637e108af990606401600060405180830381600087803b158015612add57600080fd5b505af1158015612af1573d6000803e3d6000fd5b50505050505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612b3a575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612ba0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600f55565b6000808273ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b158015612bed57600080fd5b505afa158015612c01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c25919061396c565b5073ffffffffffffffffffffffffffffffffffffffff84166000908152601a602052604081205491925090612c5a9083613a70565b9050601854600a612c6b9190613b98565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260156020526040902054612c9b9190613c60565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260116020526040902054612ccb9083613d59565b612cd59190613d59565b949350505050565b60075460009060609073ffffffffffffffffffffffffffffffffffffffff16331480612d20575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612d86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b6000808773ffffffffffffffffffffffffffffffffffffffff16878787604051612db1929190613990565b60006040518083038185875af1925050503d8060008114612dee576040519150601f19603f3d011682016040523d82523d6000602084013e612df3565b606091505b5090999098509650505050505050565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612e40575060005473ffffffffffffffffffffffffffffffffffffffff1633145b612ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff8116612f23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f54696d656c6f636b20616464726573732063616e6e6f742062652030000000006044820152606401610920565b600780547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60075473ffffffffffffffffffffffffffffffffffffffff16331480612fa7575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61300d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b600e55565b60075473ffffffffffffffffffffffffffffffffffffffff1633148061304f575060005473ffffffffffffffffffffffffffffffffffffffff1633145b6130b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b601055565b6060600b80548060200260200160405190810160405280929190818152602001828054801561311f57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116130f4575b5050505050905090565b336000818152600c602052604090205460ff166131a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f496e76616c696420414d4f0000000000000000000000000000000000000000006044820152606401610920565b6003546040517fa8a778ae00000000000000000000000000000000000000000000000000000000815233600482015260248101849052839173ffffffffffffffffffffffffffffffffffffffff169063a8a778ae90604401600060405180830381600087803b15801561321457600080fd5b505af1158015613228573d6000803e3d6000fd5b5050336000908152601360205260408120805485945090925061324c908490613d59565b925050819055508060146000828254610f189190613d59565b60008060005b600b548110156133cb576000600b828154811061328a5761328a613e78565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905080156133b8576000808273ffffffffffffffffffffffffffffffffffffffff1663a4c3e73c6040518163ffffffff1660e01b8152600401604080518083038186803b1580156132fc57600080fd5b505afa158015613310573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613334919061396c565b73ffffffffffffffffffffffffffffffffffffffff85166000908152601a602052604090205491935091506133699083613a70565b6133739087613ae4565b73ffffffffffffffffffffffffffffffffffffffff84166000908152601a60205260409020909650600101546133a99082613a70565b6133b39086613ae4565b945050505b50806133c381613e10565b91505061326b565b50601791909155601955565b60075473ffffffffffffffffffffffffffffffffffffffff16331480613414575060005473ffffffffffffffffffffffffffffffffffffffff1633145b61347a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f4e6f74206f776e6572206f722074696d656c6f636b00000000000000000000006044820152606401610920565b73ffffffffffffffffffffffffffffffffffffffff83166000908152601a60205260409020828155600101819055610f26613265565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161354f91906139a0565b6000604051808303816000865af19150503d806000811461358c576040519150601f19603f3d011682016040523d82523d6000602084013e613591565b606091505b50915091508180156135bb5750805115806135bb5750808060200190518101906135bb919061391d565b613646576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f464160448201527f494c4544000000000000000000000000000000000000000000000000000000006064820152608401610920565b505050505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905291516000928392908716916136e591906139a0565b6000604051808303816000865af19150503d8060008114613722576040519150601f19603f3d011682016040523d82523d6000602084013e613727565b606091505b5091509150818015613751575080511580613751575080806020019051810190613751919061391d565b6137b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c4544006044820152606401610920565b5050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146137e257600080fd5b919050565b6000602082840312156137f957600080fd5b6109b2826137be565b6000806040838503121561381557600080fd5b61381e836137be565b9150602083013561382e81613ea7565b809150509250929050565b60008060006060848603121561384e57600080fd5b613857846137be565b95602085013595506040909401359392505050565b6000806040838503121561387f57600080fd5b613888836137be565b946020939093013593505050565b600080600080606085870312156138ac57600080fd5b6138b5856137be565b935060208501359250604085013567ffffffffffffffff808211156138d957600080fd5b818701915087601f8301126138ed57600080fd5b8135818111156138fc57600080fd5b88602082850101111561390e57600080fd5b95989497505060200194505050565b60006020828403121561392f57600080fd5b81516109b281613ea7565b60006020828403121561394c57600080fd5b5035919050565b60006020828403121561396557600080fd5b5051919050565b6000806040838503121561397f57600080fd5b505080516020909101519092909150565b8183823760009101908152919050565b600082516139b2818460208701613de4565b9190910192915050565b6020808252825182820181905260009190848201906040850190845b81811015613a0a57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016139d8565b50909695505050505050565b82151581526040602082015260008251806040840152613a3d816060850160208701613de4565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016060019392505050565b6000808212827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03841381151615613aaa57613aaa613e49565b827f8000000000000000000000000000000000000000000000000000000000000000038412811615613ade57613ade613e49565b50500190565b60008219821115613af757613af7613e49565b500190565b600082613b32577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600181815b80851115613b9057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613b7657613b76613e49565b80851615613b8357918102915b93841c9390800290613b3c565b509250929050565b60006109b28383600082613bae57506001613c5a565b81613bbb57506000613c5a565b8160018114613bd15760028114613bdb57613bf7565b6001915050613c5a565b60ff841115613bec57613bec613e49565b50506001821b613c5a565b5060208310610133831016604e8410600b8410161715613c1a575081810a613c5a565b613c248383613b37565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115613c5657613c56613e49565b0290505b92915050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600084136000841385830485118282161615613ca157613ca1613e49565b7f80000000000000000000000000000000000000000000000000000000000000006000871286820588128184161615613cdc57613cdc613e49565b60008712925087820587128484161615613cf857613cf8613e49565b87850587128184161615613d0e57613d0e613e49565b505050929093029392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613d5457613d54613e49565b500290565b6000808312837f800000000000000000000000000000000000000000000000000000000000000001831281151615613d9357613d93613e49565b837f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff018313811615613dc757613dc7613e49565b50500390565b600082821015613ddf57613ddf613e49565b500390565b60005b83811015613dff578181015183820152602001613de7565b838111156119135750506000910152565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415613e4257613e42613e49565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b801515811461134c57600080fdfea2646970667358221220d7505757b29efdbf7dd8a05f225e43d07f180164296d60d6c8815eede21ee64464736f6c63430008060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd20000000000000000000000005180db0237291a6449dda9ed33ad90a38787621c0000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000002fe065e6ffef9ac95ab39e5042744d695f560729
-----Decoded View---------------
Arg [0] : _owner_address (address): 0x234D953a9404Bf9DbC3b526271d440cD2870bCd2
Arg [1] : _custodian_address (address): 0x5180db0237291A6449DdA9ed33aD90a38787621c
Arg [2] : _timelock_address (address): 0x8412ebf45bAC1B340BbE8F318b928C466c4E39CA
Arg [3] : _collateral_address (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [4] : _pool_address (address): 0x2fE065e6FFEf9ac95ab39E5042744d695F560729
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000234d953a9404bf9dbc3b526271d440cd2870bcd2
Arg [1] : 0000000000000000000000005180db0237291a6449dda9ed33ad90a38787621c
Arg [2] : 0000000000000000000000008412ebf45bac1b340bbe8f318b928c466c4e39ca
Arg [3] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [4] : 0000000000000000000000002fe065e6ffef9ac95ab39e5042744d695f560729
Deployed Bytecode Sourcemap
77664:15983:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78101:81;;;;;;;;;;;;3653:42:1;3641:55;;;3623:74;;3611:2;3596:18;78101:81:0;;;;;;;;79418:58;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;7524:25:1;;;7512:2;7497:18;79418:58:0;7479:76:1;81704:190:0;;;:::i;79840:60::-;;;;;;:::i;:::-;;:::i;15005:141::-;;;;;;:::i;:::-;;:::i;:::-;;78015:79;;;;;;;;;81106:159;;;:::i;78295:33::-;;;;;;;;;77906:66;;;;;;;;;85455:1057;;;;;;:::i;:::-;;:::i;77979:29::-;;;;;;;;;89079:480;;;;;;:::i;:::-;;:::i;78964:30::-;;;;;;91975:143;;;;;;:::i;:::-;;:::i;79220:51::-;;;;;;:::i;:::-;;;;;;;;;;;;;;79717:31;;;;;;79135;;;;;;91479:222;;;;;;:::i;:::-;;:::i;78388:27::-;;;;;;:::i;:::-;;:::i;78845:49::-;;;;;;79030:52;;;;;;:::i;:::-;;;;;;;;;;;;;;79537:37;;;;;;14773:29;;;;;;;;;92572:291;;;;;;:::i;:::-;;:::i;79755:44::-;;;;;;90543:727;;;;;;:::i;:::-;;:::i;87160:567::-;;;;;;:::i;:::-;;:::i;86520:405::-;;;;;;:::i;:::-;;:::i;84295:641::-;;;;;;:::i;:::-;;:::i;15154:271::-;;;:::i;78227:32::-;;;;;;;;;92871:286;;;;;;:::i;:::-;;:::i;78335:22::-;;;;;;14746:20;;;;;;;;;79631:42;;;;;;88365:706;;;;;;:::i;:::-;;:::i;89655:857::-;;;;;;:::i;:::-;;:::i;83316:971::-;;;;;;:::i;:::-;;:::i;91844:123::-;;;;;;:::i;:::-;;:::i;81273:203::-;81392:23;;81443:25;;81273:203;;;13690:25:1;;;13746:2;13731:18;;13724:34;;;;13663:18;81273:203:0;13645:119:1;81902:412:0;;;;;;:::i;:::-;;:::i;77830:69::-;;;;;;;;;93187:274;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;78422:36::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;5596:14:1;;5589:22;5571:41;;5559:2;5544:18;78422:36:0;5526:92:1;91278:193:0;;;;;;:::i;:::-;;:::i;91709:127::-;;;;;;:::i;:::-;;:::i;81596:100::-;81671:10;:17;81596:100;;78788:50;;;;;;92126:109;;;;;;:::i;:::-;;:::i;78189:31::-;;;;;;;;;81484:104;;;:::i;:::-;;;;;;;:::i;87735:395::-;;;;;;:::i;:::-;;:::i;78669:52::-;;;;;;79323:30;;;;;;82424:814;;;:::i;92243:321::-;;;;;;:::i;:::-;;:::i;81704:190::-;81756:6;81868:16;;81862:2;:22;;;;:::i;:::-;81833:19;;:52;;;;:::i;:::-;81816:13;;81789:23;;81782:47;;;;:::i;:::-;:104;;;;:::i;:::-;81775:111;;81704:190;:::o;79840:60::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;79840:60:0;;-1:-1:-1;79840:60:0:o;15005:141::-;15485:5;;;;15471:10;:19;15463:79;;;;;;;9941:2:1;15463:79:0;;;9923:21:1;9980:2;9960:18;;;9953:30;10019:34;9999:18;;;9992:62;10090:17;10070:18;;;10063:45;10125:19;;15463:79:0;;;;;;;;;15077:14:::1;:23:::0;;;::::1;;::::0;::::1;::::0;;::::1;::::0;;;15116:22:::1;::::0;3623:74:1;;;15116:22:0::1;::::0;3611:2:1;3596:18;15116:22:0::1;;;;;;;15005:141:::0;:::o;81106:159::-;81160:7;81183:22;81209:16;81392:23;;81443:25;;81392:23;;81273:203;81209:16;81180:45;81106:159;-1:-1:-1;;;81106:159:0:o;85455:1057::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;81004:17:::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;85556:15;;81004:17:::1;;80996:41;;;::::0;::::1;::::0;;10357:2:1;80996:41:0::1;::::0;::::1;10339:21:1::0;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0::1;10329:161:1::0;80996:41:0::1;85746:13:::2;::::0;85712::::2;::::0;85614:11;;85746:13;85712:29:::2;::::0;85614:11;;85712:29:::2;:::i;:::-;85711:48;;85703:77;;;::::0;::::2;::::0;;11741:2:1;85703:77:0::2;::::0;::::2;11723:21:1::0;11780:2;11760:18;;;11753:30;11819:18;11799;;;11792:46;11855:18;;85703:77:0::2;11713:166:1::0;85703:77:0::2;85791:35;::::0;::::2;;::::0;;;:18:::2;:35;::::0;;;;:52;;85830:13;;85791:35;:52:::2;::::0;85830:13;;85791:52:::2;:::i;:::-;;;;;;;;85871:13;85854;;:30;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;86064:4:0::2;::::0;:28:::2;::::0;;;;;;;86031:30:::2;::::0;86064:4:::2;;::::0;:26:::2;::::0;:28:::2;::::0;;::::2;::::0;::::2;::::0;;;;;;;;:4;:28;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;86031:61;;86103:23;86129:4;;;;;;;;;;;:16;;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;86103:44:::0;-1:-1:-1;86158:23:0::2;86184:29;86202:11:::0;86103:44;86184:29:::2;:::i;:::-;86158:55:::0;-1:-1:-1;86224:14:0::2;86158:55:::0;86242:40:::2;78582:3;86242:22:::0;:40:::2;:::i;:::-;86241:60;;;;:::i;:::-;86224:77;;86330:6;;86320;:16;;86312:48;;;::::0;::::2;::::0;;12848:2:1;86312:48:0::2;::::0;::::2;12830:21:1::0;12887:2;12867:18;;;12860:30;12926:21;12906:18;;;12899:49;12965:18;;86312:48:0::2;12820:169:1::0;86312:48:0::2;86410:4;::::0;:44:::2;::::0;;;;:4:::2;4635:55:1::0;;;86410:44:0::2;::::0;::::2;4617:74:1::0;4707:18;;;4700:34;;;86410:4:0;;::::2;::::0;:14:::2;::::0;4590:18:1;;86410:44:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;86484:20;:18;:20::i;:::-;85573:939;;;;;80929:1:::1;85455:1057:::0;;:::o;89079:480::-;89148:10;81004:17;;;;:4;:17;;;;;;;;80996:41;;;;;;;10357:2:1;80996:41:0;;;10339:21:1;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0;10329:161:1;80996:41:0;89288:18:::1;::::0;89328:4:::1;::::0;89203:11;;89256:91:::1;::::0;89288:18:::1;::::0;;::::1;::::0;89308:10:::1;::::0;89328:4:::1;89203:11:::0;89256:31:::1;:91::i;:::-;89422:10;89397:36;::::0;;;:24:::1;:36;::::0;;;;:55;;89437:15;;89397:36;:55:::1;::::0;89437:15;;89397:55:::1;:::i;:::-;;;;;;;;89486:15;89463:19;;:38;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;89531:20:0::1;::::0;-1:-1:-1;89531:18:0::1;:20::i;:::-;89160:399;89079:480:::0;;:::o;91975:143::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;92064:17:::1;:46:::0;91975:143::o;91479:222::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;91570:32:::1;::::0;::::1;91562:74;;;::::0;::::1;::::0;;9244:2:1;91562:74:0::1;::::0;::::1;9226:21:1::0;9283:2;9263:18;;;9256:30;9322:31;9302:18;;;9295:59;9371:18;;91562:74:0::1;9216:179:1::0;91562:74:0::1;91655:17;:38:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;91479:222::o;78388:27::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;78388:27:0;:::o;92572:291::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;92649:4:::1;:32:::0;;;::::1;;::::0;;::::1;::::0;;::::1;::::0;;;92827:7:::1;::::0;92804:18:::1;::::0;92779:44:::1;::::0;;;;92804:18;::::1;92779:44;::::0;::::1;3623:74:1::0;92827:7:0;92779:24:::1;::::0;3596:18:1;;92779:44:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:55;92771:84;;;::::0;::::1;::::0;;11396:2:1;92771:84:0::1;::::0;::::1;11378:21:1::0;11435:2;11415:18;;;11408:30;11474:18;11454;;;11447:46;11510:18;;92771:84:0::1;11368:166:1::0;92771:84:0::1;92572:291:::0;:::o;90543:727::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;90637:25:::1;::::0;::::1;90629:59;;;::::0;::::1;::::0;;8894:2:1;90629:59:0::1;::::0;::::1;8876:21:1::0;8933:2;8913:18;;;8906:30;8972:23;8952:18;;;8945:51;9013:18;;90629:59:0::1;8866:171:1::0;90629:59:0::1;90707:17;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;::::1;;:25;;:17:::0;:25:::1;90699:57;;;::::0;::::1;::::0;;11048:2:1;90699:57:0::1;::::0;::::1;11030:21:1::0;11087:2;11067:18;;;11060:30;11126:21;11106:18;;;11099:49;11165:18;;90699:57:0::1;11020:169:1::0;90699:57:0::1;90820:17;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;90813:24;;;::::1;::::0;;90916:259:::1;90937:10;:17:::0;90933:21;::::1;90916:259;;;90997:11;90980:28;;:10;90991:1;90980:13;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;::::0;::::1;;:28;90976:188;;;91053:1;91029:10;91040:1;91029:13;;;;;;;;:::i;:::-;;;;;;;;;:26;;;;;;;;;;;;;;;;;;91143:5;;90976:188;90956:3:::0;::::1;::::0;::::1;:::i;:::-;;;;90916:259;;;;91191:8;91187:34;;;91201:20;:18;:20::i;:::-;91239:23;::::0;3653:42:1;3641:55;;3623:74;;91239:23:0::1;::::0;3611:2:1;3596:18;91239:23:0::1;;;;;;;;90543:727:::0;;:::o;87160:567::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;81004:17:::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;87259:15;;81004:17:::1;;80996:41;;;::::0;::::1;::::0;;10357:2:1;80996:41:0::1;::::0;::::1;10339:21:1::0;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0::1;10329:161:1::0;80996:41:0::1;87445:12:::2;::::0;87413::::2;::::0;87316:10;;87445:12;87413:27:::2;::::0;87316:10;;87413:27:::2;:::i;:::-;87412:45;;87404:74;;;::::0;::::2;::::0;;11741:2:1;87404:74:0::2;::::0;::::2;11723:21:1::0;11780:2;11760:18;;;11753:30;11819:18;11799;;;11792:46;11855:18;;87404:74:0::2;11713:166:1::0;87404:74:0::2;87489:34;::::0;::::2;;::::0;;;:17:::2;:34;::::0;;;;:50;;87527:12;;87489:34;:50:::2;::::0;87527:12;;87489:50:::2;:::i;:::-;;;;;;;;87566:12;87550;;:28;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;87627:3:0::2;::::0;:42:::2;::::0;;;;:3:::2;4635:55:1::0;;;87627:42:0::2;::::0;::::2;4617:74:1::0;4707:18;;;4700:34;;;87627:3:0;;::::2;::::0;:13:::2;::::0;4590:18:1;;87627:42:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;87699:20;:18;:20::i;:::-;87276:451;80929:1:::1;87160:567:::0;;:::o;86520:405::-;86584:10;81004:17;;;;:4;:17;;;;;;;;80996:41;;;;;;;10357:2:1;80996:41:0;;;10339:21:1;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0;10329:161:1;80996:41:0;86685:4:::1;::::0;:44:::1;::::0;;;;86705:10:::1;86685:44;::::0;::::1;4617:74:1::0;4707:18;;;4700:34;;;86637:11:0;;86685:4:::1;;::::0;:19:::1;::::0;4590:18:1;;86685:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;86798:10:0::1;86779:30;::::0;;;:18:::1;:30;::::0;;;;:47;;86813:13;;-1:-1:-1;86779:30:0;;-1:-1:-1;86779:47:0::1;::::0;86813:13;;86779:47:::1;:::i;:::-;;;;;;;;86854:13;86837;;:30;;;;;;;:::i;84295:641::-:0;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;81004:17:::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;84382:15;;81004:17:::1;;80996:41;;;::::0;::::1;::::0;;10357:2:1;80996:41:0::1;::::0;::::1;10339:21:1::0;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0::1;10329:161:1::0;80996:41:0::1;84477:8:::2;::::0;:48:::2;::::0;;;;84519:4:::2;84477:48;::::0;::::2;3623:74:1::0;84453:21:0::2;::::0;84477:8:::2;;::::0;:33:::2;::::0;3596:18:1;;84477:48:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;84453:72;;84581:8;;;;;;;;;;;:26;;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;;;84677:41:0::2;::::0;::::2;;::::0;;;:24:::2;:41;::::0;;;;:66;;84729:13;;84677:41;:66:::2;::::0;84729:13;;84677:66:::2;:::i;:::-;::::0;;;-1:-1:-1;;84827:18:0::2;::::0;84799:79:::2;::::0;84827:18:::2;;84847:15:::0;84864:13;84799:27:::2;:79::i;:::-;84908:20;:18;:20::i;15154:271::-:0;15223:14;;;;15209:10;:28;15201:94;;;;;;;8122:2:1;15201:94:0;;;8104:21:1;8161:2;8141:18;;;8134:30;8200:34;8180:18;;;8173:62;8271:23;8251:18;;;8244:51;8312:19;;15201:94:0;8094:243:1;15201:94:0;15324:5;;;15331:14;15311:35;;;15324:5;;;;3943:34:1;;15331:14:0;;;;4008:2:1;3993:18;;3986:43;15311:35:0;;3855:18:1;15311:35:0;;;;;;;15365:14;;;;15357:22;;;;;;15365:14;;;15357:22;;;;15390:27;;;15154:271::o;92871:286::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;93068:5:::1;::::0;93026:61:::1;::::0;93054:12;;93068:5:::1;;93075:11:::0;93026:27:::1;:61::i;:::-;93113:36;::::0;;4647:42:1;4635:55;;4617:74;;4722:2;4707:18;;4700:34;;;93113:36:0::1;::::0;4590:18:1;93113:36:0::1;4572:168:1::0;88365:706:0;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;81004:17:::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;88494:15;;81004:17:::1;;80996:41;;;::::0;::::1;::::0;;10357:2:1;80996:41:0::1;::::0;::::1;10339:21:1::0;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0::1;10329:161:1::0;80996:41:0::1;88638:17:::2;::::0;88593:19:::2;::::0;88557:13;;88638:17;88593:40:::2;::::0;88557:13;;88593:40:::2;:::i;:::-;88592:63;;88584:86;;;::::0;::::2;::::0;;9602:2:1;88584:86:0::2;::::0;::::2;9584:21:1::0;9641:2;9621:18;;;9614:30;9680:12;9660:18;;;9653:40;9710:18;;88584:86:0::2;9574:160:1::0;88584:86:0::2;88681:41;::::0;::::2;;::::0;;;:24:::2;:41;::::0;;;;:63;;88726:18;;88681:41;:63:::2;::::0;88726:18;;88681:63:::2;:::i;:::-;;;;;;;;88778:18;88755:19;;:41;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;88843:4:0::2;::::0;:35:::2;::::0;;;;::::2;::::0;::::2;7524:25:1::0;;;88843:4:0::2;::::0;;::::2;::::0;:20:::2;::::0;7497:18:1;;88843:35:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;-1:-1:-1::0;;88962:18:0::2;::::0;88934:79:::2;::::0;-1:-1:-1;88962:18:0::2;;::::0;-1:-1:-1;88982:15:0;88999:13;88934:27:::2;:79::i;:::-;89043:20;:18;:20::i;89655:857::-:0;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;89746:25:::1;::::0;::::1;89738:59;;;::::0;::::1;::::0;;8894:2:1;89738:59:0::1;::::0;::::1;8876:21:1::0;8933:2;8913:18;;;8906:30;8972:23;8952:18;;;8945:51;9013:18;;89738:59:0::1;8866:171:1::0;89738:59:0::1;89811:20;89833:22:::0;89864:11:::1;89859:32;;;:34;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89810:83:::0;;-1:-1:-1;89810:83:0;-1:-1:-1;89989:17:0::1;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;::::1;;:26;89981:61;;;::::0;::::1;::::0;;10697:2:1;89981:61:0::1;::::0;::::1;10679:21:1::0;10736:2;10716:18;;;10709:30;10775:24;10755:18;;;10748:52;10817:18;;89981:61:0::1;10669:172:1::0;89981:61:0::1;90053:17;::::0;::::1;;::::0;;;:4:::1;:17;::::0;;;;;;;:24;;;::::1;90073:4;90053:24:::0;;::::1;::::0;;;90089:10:::1;:28:::0;;;;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;90156:18:::1;:31:::0;;;;;:35;;;90202:17:::1;:30:::0;;;;;:34;;;90247:24:::1;:37:::0;;;;;:41;;;90321:23:::1;:36:::0;;;;;:43;;;90375:39;;::::1;:43:::0;90431:34;::::1;;;90445:20;:18;:20::i;:::-;90483:21;::::0;3653:42:1;3641:55;;3623:74;;90483:21:0::1;::::0;3611:2:1;3596:18;90483:21:0::1;;;;;;;89727:785;;89655:857:::0;;:::o;83316:971::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;83418:8:::1;::::0;:25:::1;::::0;;;;;;;83393:22:::1;::::0;83418:8:::1;;::::0;:23:::1;::::0;:25:::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;;83393:22;83418:8;:25;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83393:50;;83454:21;83478:8;;;;;;;;;;;:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83454:53;;83518:31;83552:4;;;;;;;;;;;:28;;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83518:64;;83593:24;83685:16;;83679:2;:22;;;;:::i;:::-;83671:3;83637:29;83652:14:::0;83671:3;83637:29:::1;:::i;:::-;83622:45;::::0;:11;:45:::1;:::i;:::-;83621:53;;;;:::i;:::-;83620:82;;;;:::i;:::-;83593:109:::0;-1:-1:-1;83713:30:0::1;83793:3;83747:42;83766:23:::0;83593:109;83747:42:::1;:::i;:::-;83746:50;;;;:::i;:::-;83713:83:::0;-1:-1:-1;83865:13:0;83833:28:::1;83713:83:::0;83858:3:::1;83833:28;:::i;:::-;83832:46;;;;:::i;:::-;83807:71;;83957:17;;83929:22;83900:19;;:52;;;;:::i;:::-;83899:75;;83891:98;;;::::0;::::1;::::0;;9602:2:1;83891:98:0::1;::::0;::::1;9584:21:1::0;9641:2;9621:18;;;9614:30;9680:12;9660:18;;;9653:40;9710:18;;83891:98:0::1;9574:160:1::0;83891:98:0::1;84030:22;84000:19;;:53;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;84093:4:0::1;::::0;:42:::1;::::0;;;;84116:4:::1;84093:42;::::0;::::1;4617:74:1::0;4707:18;;;4700:34;;;84093:4:0::1;::::0;;::::1;::::0;:14:::1;::::0;4590:18:1;;84093:42:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;84176:4:0::1;::::0;84197:8:::1;::::0;84176:44:::1;::::0;;;;:4:::1;84197:8:::0;;::::1;84176:44;::::0;::::1;4617:74:1::0;4707:18;;;4700:34;;;84176:4:0;::::1;::::0;-1:-1:-1;84176:12:0::1;::::0;-1:-1:-1;4590:18:1;;84176:44:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;84231:8:0::1;::::0;:48:::1;::::0;;;;::::1;::::0;::::1;13394:25:1::0;;;84231:8:0::1;13435:18:1::0;;;13428:34;;;13478:18;;;13471:34;84231:8:0::1;::::0;;::::1;::::0;:29:::1;::::0;13367:18:1;;84231:48:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;83382:905;;;;;83316:971:::0;:::o;91844:123::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;91923:12:::1;:36:::0;91844:123::o;81902:412::-;81970:6;81990:20;82021:11;82016:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;82116:36:0;;;82061:29;82116:36;;;:23;:36;;;;;:39;81989:61;;-1:-1:-1;82061:29:0;82093:62;;81989:61;82093:62;:::i;:::-;82061:94;;82288:16;;82282:2;:22;;;;:::i;:::-;82234:37;;;;;;;:24;:37;;;;;;82233:72;;;;:::i;:::-;82198:31;;;;;;;:18;:31;;;;;;82173:56;;:22;:56;:::i;:::-;:133;;;;:::i;:::-;82166:140;81902:412;-1:-1:-1;;;;81902:412:0:o;93187:274::-;80853:16;;93320:4;;93326:12;;80853:16;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;93352:12:::1;93366:19:::0;93389:3:::1;:8;;93404:6;93412:5;;93389:29;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;93351:67:0;;;;-1:-1:-1;93187:274:0;-1:-1:-1;;;;;;;93187:274:0:o;91278:193::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;91362:26:::1;::::0;::::1;91354:67;;;::::0;::::1;::::0;;12086:2:1;91354:67:0::1;::::0;::::1;12068:21:1::0;12125:2;12105:18;;;12098:30;12164;12144:18;;;12137:58;12212:18;;91354:67:0::1;12058:178:1::0;91354:67:0::1;91432:16;:31:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;91278:193::o;91709:127::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;91790:13:::1;:38:::0;91709:127::o;92126:109::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;92211:6:::1;:16:::0;92126:109::o;81484:104::-;81534:16;81570:10;81563:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81484:104;:::o;87735:395::-;87797:10;81004:17;;;;:4;:17;;;;;;;;80996:41;;;;;;;10357:2:1;80996:41:0;;;10339:21:1;10396:2;10376:18;;;10369:30;10435:13;10415:18;;;10408:41;10466:18;;80996:41:0;10329:161:1;80996:41:0;87896:3:::1;::::0;:42:::1;::::0;;;;87915:10:::1;87896:42;::::0;::::1;4617:74:1::0;4707:18;;;4700:34;;;87849:10:0;;87896:3:::1;;::::0;:18:::1;::::0;4590::1;;87896:42:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;88006:10:0::1;87988:29;::::0;;;:17:::1;:29;::::0;;;;:45;;88021:12;;-1:-1:-1;87988:29:0;;-1:-1:-1;87988:45:0::1;::::0;88021:12;;87988:45:::1;:::i;:::-;;;;;;;;88060:12;88044;;:28;;;;;;;:::i;82424:814::-:0;82472:28;82515:34;82570:6;82565:544;82586:10;:17;82582:21;;82565:544;;;82664:19;82686:10;82697:1;82686:13;;;;;;;;:::i;:::-;;;;;;;;;;;;;;-1:-1:-1;82718:25:0;;82714:384;;82764:20;82786:22;82817:11;82812:32;;;:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;82920:36;;;;;;;:23;:36;;;;;:39;82763:83;;-1:-1:-1;82763:83:0;-1:-1:-1;82897:62:0;;82763:83;82897:62;:::i;:::-;82865:95;;;;:::i;:::-;83042:36;;;;;;;:23;:36;;;;;82865:95;;-1:-1:-1;83079:1:0;83042:39;;83017:64;;83024:14;83017:64;:::i;:::-;82979:103;;;;:::i;:::-;;;82744:354;;82714:384;-1:-1:-1;82605:3:0;;;;:::i;:::-;;;;82565:544;;;-1:-1:-1;83119:23:0;:46;;;;83176:25;:54;82424:814::o;92243:321::-;80853:16;;;;80839:10;:30;;:53;;-1:-1:-1;80887:5:0;;;;80873:10;:19;80839:53;80831:87;;;;;;;8544:2:1;80831:87:0;;;8526:21:1;8583:2;8563:18;;;8556:30;8622:23;8602:18;;;8595:51;8663:18;;80831:87:0;8516:171:1;80831:87:0;92388:36:::1;::::0;::::1;;::::0;;;:23:::1;:36;::::0;;;;:61;;;92497:1:::1;92460:39;:63:::0;;;92536:20:::1;:18;:20::i;14023:402::-:0;14248:51;;;14237:10;4321:15:1;;;14248:51:0;;;4303:34:1;4373:15;;;4353:18;;;4346:43;4405:18;;;;4398:34;;;14248:51:0;;;;;;;;;;4215:18:1;;;;14248:51:0;;;;;;;;;;;;;14237:63;;-1:-1:-1;;;;14237:10:0;;;;:63;;14248:51;14237:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14201:99;;;;14319:7;:57;;;;-1:-1:-1;14331:11:0;;:16;;:44;;;14362:4;14351:24;;;;;;;;;;;;:::i;:::-;14311:106;;;;;;;12443:2:1;14311:106:0;;;12425:21:1;12482:2;12462:18;;;12455:30;12521:34;12501:18;;;12494:62;12592:6;12572:18;;;12565:34;12616:19;;14311:106:0;12415:226:1;14311:106:0;14111:314;;14023:402;;;;:::o;13654:361::-;13849:45;;;13838:10;4635:55:1;;;13849:45:0;;;4617:74:1;4707:18;;;;4700:34;;;13849:45:0;;;;;;;;;;4590:18:1;;;;13849:45:0;;;;;;;;;;;;;13838:57;;-1:-1:-1;;;;13838:10:0;;;;:57;;13849:45;13838:57;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13802:93;;;;13914:7;:57;;;;-1:-1:-1;13926:11:0;;:16;;:44;;;13957:4;13946:24;;;;;;;;;;;;:::i;:::-;13906:101;;;;;;;7762:2:1;13906:101:0;;;7744:21:1;7801:2;7781:18;;;7774:30;7840:33;7820:18;;;7813:61;7891:18;;13906:101:0;7734:181:1;13906:101:0;13724:291;;13654:361;;;:::o;14:196:1:-;82:20;;142:42;131:54;;121:65;;111:2;;200:1;197;190:12;111:2;63:147;;;:::o;215:186::-;274:6;327:2;315:9;306:7;302:23;298:32;295:2;;;343:1;340;333:12;295:2;366:29;385:9;366:29;:::i;406:315::-;471:6;479;532:2;520:9;511:7;507:23;503:32;500:2;;;548:1;545;538:12;500:2;571:29;590:9;571:29;:::i;:::-;561:39;;650:2;639:9;635:18;622:32;663:28;685:5;663:28;:::i;:::-;710:5;700:15;;;490:231;;;;;:::o;726:320::-;801:6;809;817;870:2;858:9;849:7;845:23;841:32;838:2;;;886:1;883;876:12;838:2;909:29;928:9;909:29;:::i;:::-;899:39;985:2;970:18;;957:32;;-1:-1:-1;1036:2:1;1021:18;;;1008:32;;828:218;-1:-1:-1;;;828:218:1:o;1051:254::-;1119:6;1127;1180:2;1168:9;1159:7;1155:23;1151:32;1148:2;;;1196:1;1193;1186:12;1148:2;1219:29;1238:9;1219:29;:::i;:::-;1209:39;1295:2;1280:18;;;;1267:32;;-1:-1:-1;;;1138:167:1:o;1310:733::-;1398:6;1406;1414;1422;1475:2;1463:9;1454:7;1450:23;1446:32;1443:2;;;1491:1;1488;1481:12;1443:2;1514:29;1533:9;1514:29;:::i;:::-;1504:39;;1590:2;1579:9;1575:18;1562:32;1552:42;;1645:2;1634:9;1630:18;1617:32;1668:18;1709:2;1701:6;1698:14;1695:2;;;1725:1;1722;1715:12;1695:2;1763:6;1752:9;1748:22;1738:32;;1808:7;1801:4;1797:2;1793:13;1789:27;1779:2;;1830:1;1827;1820:12;1779:2;1870;1857:16;1896:2;1888:6;1885:14;1882:2;;;1912:1;1909;1902:12;1882:2;1957:7;1952:2;1943:6;1939:2;1935:15;1931:24;1928:37;1925:2;;;1978:1;1975;1968:12;1925:2;1433:610;;;;-1:-1:-1;;2009:2:1;2001:11;;-1:-1:-1;;;1433:610:1:o;2048:245::-;2115:6;2168:2;2156:9;2147:7;2143:23;2139:32;2136:2;;;2184:1;2181;2174:12;2136:2;2216:9;2210:16;2235:28;2257:5;2235:28;:::i;2298:180::-;2357:6;2410:2;2398:9;2389:7;2385:23;2381:32;2378:2;;;2426:1;2423;2416:12;2378:2;-1:-1:-1;2449:23:1;;2368:110;-1:-1:-1;2368:110:1:o;2483:184::-;2553:6;2606:2;2594:9;2585:7;2581:23;2577:32;2574:2;;;2622:1;2619;2612:12;2574:2;-1:-1:-1;2645:16:1;;2564:103;-1:-1:-1;2564:103:1:o;2672:245::-;2751:6;2759;2812:2;2800:9;2791:7;2787:23;2783:32;2780:2;;;2828:1;2825;2818:12;2780:2;-1:-1:-1;;2851:16:1;;2907:2;2892:18;;;2886:25;2851:16;;2886:25;;-1:-1:-1;2770:147:1:o;2922:271::-;3105:6;3097;3092:3;3079:33;3061:3;3131:16;;3156:13;;;3131:16;3069:124;-1:-1:-1;3069:124:1:o;3198:274::-;3327:3;3365:6;3359:13;3381:53;3427:6;3422:3;3415:4;3407:6;3403:17;3381:53;:::i;:::-;3450:16;;;;;3335:137;-1:-1:-1;;3335:137:1:o;4745:681::-;4916:2;4968:21;;;5038:13;;4941:18;;;5060:22;;;4887:4;;4916:2;5139:15;;;;5113:2;5098:18;;;4887:4;5182:218;5196:6;5193:1;5190:13;5182:218;;;5261:13;;5276:42;5257:62;5245:75;;5375:15;;;;5340:12;;;;5218:1;5211:9;5182:218;;;-1:-1:-1;5417:3:1;;4896:530;-1:-1:-1;;;;;;4896:530:1:o;5623:521::-;5806:6;5799:14;5792:22;5781:9;5774:41;5851:2;5846;5835:9;5831:18;5824:30;5755:4;5883:6;5877:13;5926:6;5921:2;5910:9;5906:18;5899:34;5942:66;6001:6;5996:2;5985:9;5981:18;5976:2;5968:6;5964:15;5942:66;:::i;:::-;6060:2;6048:15;6065:66;6044:88;6029:104;;;;6135:2;6025:113;;5764:380;-1:-1:-1;;;5764:380:1:o;13769:367::-;13808:3;13843:1;13840;13836:9;13952:1;13884:66;13880:74;13877:1;13873:82;13868:2;13861:10;13857:99;13854:2;;;13959:18;;:::i;:::-;14078:1;14010:66;14006:74;14003:1;13999:82;13995:2;13991:91;13988:2;;;14085:18;;:::i;:::-;-1:-1:-1;;14121:9:1;;13816:320::o;14141:128::-;14181:3;14212:1;14208:6;14205:1;14202:13;14199:2;;;14218:18;;:::i;:::-;-1:-1:-1;14254:9:1;;14189:80::o;14274:274::-;14314:1;14340;14330:2;;14375:77;14372:1;14365:88;14476:4;14473:1;14466:15;14504:4;14501:1;14494:15;14330:2;-1:-1:-1;14533:9:1;;14320:228::o;14553:482::-;14642:1;14685:5;14642:1;14699:330;14720:7;14710:8;14707:21;14699:330;;;14839:4;14771:66;14767:77;14761:4;14758:87;14755:2;;;14848:18;;:::i;:::-;14898:7;14888:8;14884:22;14881:2;;;14918:16;;;;14881:2;14997:22;;;;14957:15;;;;14699:330;;;14703:3;14617:418;;;;;:::o;15040:131::-;15100:5;15129:36;15156:8;15150:4;15225:5;15255:8;15245:2;;-1:-1:-1;15296:1:1;15310:5;;15245:2;15344:4;15334:2;;-1:-1:-1;15381:1:1;15395:5;;15334:2;15426:4;15444:1;15439:59;;;;15512:1;15507:130;;;;15419:218;;15439:59;15469:1;15460:10;;15483:5;;;15507:130;15544:3;15534:8;15531:17;15528:2;;;15551:18;;:::i;:::-;-1:-1:-1;;15607:1:1;15593:16;;15622:5;;15419:218;;15721:2;15711:8;15708:16;15702:3;15696:4;15693:13;15689:36;15683:2;15673:8;15670:16;15665:2;15659:4;15656:12;15652:35;15649:77;15646:2;;;-1:-1:-1;15758:19:1;;;15790:5;;15646:2;15837:34;15862:8;15856:4;15837:34;:::i;:::-;15967:6;15899:66;15895:79;15886:7;15883:92;15880:2;;;15978:18;;:::i;:::-;16016:20;;-1:-1:-1;15235:807:1;;;;;:::o;16047:655::-;16086:7;16118:66;16210:1;16207;16203:9;16238:1;16235;16231:9;16283:1;16279:2;16275:10;16272:1;16269:17;16264:2;16260;16256:11;16252:35;16249:2;;;16290:18;;:::i;:::-;16329:66;16421:1;16418;16414:9;16468:1;16464:2;16459:11;16456:1;16452:19;16447:2;16443;16439:11;16435:37;16432:2;;;16475:18;;:::i;:::-;16521:1;16518;16514:9;16504:19;;16568:1;16564:2;16559:11;16556:1;16552:19;16547:2;16543;16539:11;16535:37;16532:2;;;16575:18;;:::i;:::-;16640:1;16636:2;16631:11;16628:1;16624:19;16619:2;16615;16611:11;16607:37;16604:2;;;16647:18;;:::i;:::-;-1:-1:-1;;;16687:9:1;;;;;16098:604;-1:-1:-1;;;16098:604:1:o;16707:228::-;16747:7;16873:1;16805:66;16801:74;16798:1;16795:81;16790:1;16783:9;16776:17;16772:105;16769:2;;;16880:18;;:::i;:::-;-1:-1:-1;16920:9:1;;16759:176::o;16940:369::-;16979:4;17015:1;17012;17008:9;17124:1;17056:66;17052:74;17049:1;17045:82;17040:2;17033:10;17029:99;17026:2;;;17131:18;;:::i;:::-;17250:1;17182:66;17178:74;17175:1;17171:82;17167:2;17163:91;17160:2;;;17257:18;;:::i;:::-;-1:-1:-1;;17294:9:1;;16988:321::o;17314:125::-;17354:4;17382:1;17379;17376:8;17373:2;;;17387:18;;:::i;:::-;-1:-1:-1;17424:9:1;;17363:76::o;17444:258::-;17516:1;17526:113;17540:6;17537:1;17534:13;17526:113;;;17616:11;;;17610:18;17597:11;;;17590:39;17562:2;17555:10;17526:113;;;17657:6;17654:1;17651:13;17648:2;;;-1:-1:-1;;17692:1:1;17674:16;;17667:27;17497:205::o;17707:195::-;17746:3;17777:66;17770:5;17767:77;17764:2;;;17847:18;;:::i;:::-;-1:-1:-1;17894:1:1;17883:13;;17754:148::o;17907:184::-;17959:77;17956:1;17949:88;18056:4;18053:1;18046:15;18080:4;18077:1;18070:15;18096:184;18148:77;18145:1;18138:88;18245:4;18242:1;18235:15;18269:4;18266:1;18259:15;18285:118;18371:5;18364:13;18357:21;18350:5;18347:32;18337:2;;18393:1;18390;18383:12
Swarm Source
ipfs://d7505757b29efdbf7dd8a05f225e43d07f180164296d60d6c8815eede21ee644
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.