Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 48 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Approve | 15454268 | 872 days ago | IN | 0 ETH | 0.00058268 | ||||
Approve | 15454265 | 872 days ago | IN | 0 ETH | 0.00114389 | ||||
Approve | 15227040 | 907 days ago | IN | 0 ETH | 0.00176854 | ||||
Approve | 15012498 | 942 days ago | IN | 0 ETH | 0.00103566 | ||||
Approve | 14731611 | 989 days ago | IN | 0 ETH | 0.00166505 | ||||
Approve | 14655053 | 1001 days ago | IN | 0 ETH | 0.00309045 | ||||
Liquidate Borrow | 14654988 | 1001 days ago | IN | 0 ETH | 0.01729746 | ||||
Liquidate Borrow | 14654948 | 1001 days ago | IN | 0 ETH | 0.01695728 | ||||
Transfer | 14654907 | 1001 days ago | IN | 0 ETH | 0.00391349 | ||||
Approve | 14654901 | 1001 days ago | IN | 0 ETH | 0.00259866 | ||||
Transfer | 14654879 | 1001 days ago | IN | 0 ETH | 0.00446533 | ||||
Transfer | 14654870 | 1001 days ago | IN | 0 ETH | 0.00560008 | ||||
Transfer | 14654829 | 1001 days ago | IN | 0 ETH | 0.00555048 | ||||
Approve | 14576004 | 1013 days ago | IN | 0 ETH | 0.00143348 | ||||
Approve | 14565534 | 1015 days ago | IN | 0 ETH | 0.00425613 | ||||
Approve | 14565525 | 1015 days ago | IN | 0 ETH | 0.00363991 | ||||
Approve | 14565517 | 1015 days ago | IN | 0 ETH | 0.00260961 | ||||
Approve | 14565414 | 1015 days ago | IN | 0 ETH | 0.00475607 | ||||
Approve | 14565235 | 1015 days ago | IN | 0 ETH | 0.00425061 | ||||
Approve | 14565163 | 1015 days ago | IN | 0 ETH | 0.00343158 | ||||
Approve | 14510773 | 1023 days ago | IN | 0 ETH | 0.00139101 | ||||
Approve | 14505385 | 1024 days ago | IN | 0 ETH | 0.00192271 | ||||
Approve | 14499493 | 1025 days ago | IN | 0 ETH | 0.00176856 | ||||
Approve | 14299557 | 1056 days ago | IN | 0 ETH | 0.0025165 | ||||
Approve | 12761406 | 1296 days ago | IN | 0 ETH | 0.00046502 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
11875737 | 1433 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xDB64e1F7...CB34aE540 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
FyToken
Compiler Version
v0.7.6+commit.7338295f
Contract Source Code (Solidity Multiple files format)
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./Admin.sol"; import "./CarefulMath.sol"; import "./Erc20.sol"; import "./Erc20Interface.sol"; import "./Erc20Permit.sol"; import "./Erc20Recover.sol"; import "./ReentrancyGuard.sol"; import "./BalanceSheetInterface.sol"; import "./FintrollerInterface.sol"; import "./FyTokenInterface.sol"; import "./RedemptionPool.sol"; /** * @title FyToken * @author Hifi * @notice Zero-coupon bond that tracks an Erc20 underlying asset. */ contract FyToken is ReentrancyGuard, /* no depedency */ FyTokenInterface, /* one dependency */ Admin, /* two dependencies */ Exponential, /* two dependencies */ Erc20, /* three dependencies */ Erc20Permit, /* five dependencies */ Erc20Recover /* five dependencies */ { modifier isVaultOpen(address account) { require(balanceSheet.isVaultOpen(this, account), "ERR_VAULT_NOT_OPEN"); _; } /** * @notice The fyToken always has 18 decimals. * @dev Instantiates the Redemption Pool. * @param name_ Erc20 name of this token. * @param symbol_ Erc20 symbol of this token. * @param expirationTime_ Unix timestamp in seconds for when this token expires. * @param fintroller_ The address of the Fintroller contract. * @param balanceSheet_ The address of the BalanceSheet contract. * @param underlying_ The contract address of the underlying asset. * @param collateral_ The contract address of the collateral asset. */ constructor( string memory name_, string memory symbol_, uint256 expirationTime_, FintrollerInterface fintroller_, BalanceSheetInterface balanceSheet_, Erc20Interface underlying_, Erc20Interface collateral_ ) Erc20Permit(name_, symbol_, 18) Admin() { uint8 defaultNumberOfDecimals = 18; /* Set the underlying contract and calculate the decimal scalar offsets. */ uint256 underlyingDecimals = underlying_.decimals(); require(underlyingDecimals > 0, "ERR_FYTOKEN_CONSTRUCTOR_UNDERLYING_DECIMALS_ZERO"); require(underlyingDecimals <= defaultNumberOfDecimals, "ERR_FYTOKEN_CONSTRUCTOR_UNDERLYING_DECIMALS_OVERFLOW"); underlyingPrecisionScalar = 10**(defaultNumberOfDecimals - underlyingDecimals); underlying = underlying_; /* Set the collateral contract and calculate the decimal scalar offsets. */ uint256 collateralDecimals = collateral_.decimals(); require(collateralDecimals > 0, "ERR_FYTOKEN_CONSTRUCTOR_COLLATERAL_DECIMALS_ZERO"); require(defaultNumberOfDecimals >= collateralDecimals, "ERR_FYTOKEN_CONSTRUCTOR_COLLATERAL_DECIMALS_OVERFLOW"); collateralPrecisionScalar = 10**(defaultNumberOfDecimals - collateralDecimals); collateral = collateral_; /* Set the unix expiration time. */ require(expirationTime_ > block.timestamp, "ERR_FYTOKEN_CONSTRUCTOR_EXPIRATION_TIME_NOT_VALID"); expirationTime = expirationTime_; /* Set the Fintroller contract and sanity check it. */ fintroller = fintroller_; fintroller.isFintroller(); /* Set the Balance Sheet contract and sanity check it. */ balanceSheet = balanceSheet_; balanceSheet.isBalanceSheet(); /* Create the Redemption Pool contract and transfer the owner from the fyToken itself to the current caller. */ redemptionPool = new RedemptionPool(fintroller_, this); AdminInterface(address(redemptionPool))._transferAdmin(msg.sender); } /** * CONSTANT FUNCTIONS */ /** * @notice Checks if the bond matured. * @return bool true = bond matured, otherwise it didn't. */ function isMatured() public view override returns (bool) { return block.timestamp >= expirationTime; } /** * NON-CONSTANT FUNCTIONS */ struct BorrowLocalVars { MathError mathErr; uint256 debt; uint256 debtCeiling; uint256 lockedCollateral; uint256 hypotheticalCollateralizationRatioMantissa; uint256 hypotheticalTotalSupply; uint256 newDebt; uint256 thresholdCollateralizationRatioMantissa; } /** * @notice Increases the debt of the caller and mints new fyToken. * * @dev Emits a {Borrow}, {Mint} and {Transfer} event. * * Requirements: * * - The vault must be open. * - Must be called prior to maturation. * - The amount to borrow cannot be zero. * - The Fintroller must allow this action to be performed. * - The locked collateral cannot be zero. * - The total supply of fyTokens cannot exceed the debt ceiling. * - The caller must not fall below the threshold collateralization ratio. * * @param borrowAmount The amount of fyTokens to borrow and print into existence. * @return bool true = success, otherwise it reverts. */ function borrow(uint256 borrowAmount) public override isVaultOpen(msg.sender) nonReentrant returns (bool) { BorrowLocalVars memory vars; /* Checks: bond not matured. */ require(isMatured() == false, "ERR_BOND_MATURED"); /* Checks: the zero edge case. */ require(borrowAmount > 0, "ERR_BORROW_ZERO"); /* Checks: the Fintroller allows this action to be performed. */ require(fintroller.getBorrowAllowed(this), "ERR_BORROW_NOT_ALLOWED"); /* Checks: debt ceiling. */ (vars.mathErr, vars.hypotheticalTotalSupply) = addUInt(totalSupply, borrowAmount); require(vars.mathErr == MathError.NO_ERROR, "ERR_BORROW_MATH_ERROR"); vars.debtCeiling = fintroller.getBondDebtCeiling(this); require(vars.hypotheticalTotalSupply <= vars.debtCeiling, "ERR_BORROW_DEBT_CEILING_OVERFLOW"); /* Add the borrow amount to the borrower account's current debt. */ (vars.debt, , vars.lockedCollateral, ) = balanceSheet.getVault(this, msg.sender); require(vars.lockedCollateral > 0, "ERR_BORROW_LOCKED_COLLATERAL_ZERO"); (vars.mathErr, vars.newDebt) = addUInt(vars.debt, borrowAmount); require(vars.mathErr == MathError.NO_ERROR, "ERR_BORROW_MATH_ERROR"); /* Checks: the hypothetical collateralization ratio is above the threshold. */ vars.hypotheticalCollateralizationRatioMantissa = balanceSheet.getHypotheticalCollateralizationRatio( this, msg.sender, vars.lockedCollateral, vars.newDebt ); vars.thresholdCollateralizationRatioMantissa = fintroller.getBondCollateralizationRatio(this); require( vars.hypotheticalCollateralizationRatioMantissa >= vars.thresholdCollateralizationRatioMantissa, "ERR_BELOW_COLLATERALIZATION_RATIO" ); /* Effects: print the new fyTokens into existence. */ mintInternal(msg.sender, borrowAmount); /* Emit a Transfer event. */ emit Transfer(address(this), msg.sender, borrowAmount); /* Interactions: increase the debt of the borrower account. */ require(balanceSheet.setVaultDebt(this, msg.sender, vars.newDebt), "ERR_BORROW_CALL_SET_VAULT_DEBT"); /* Emit a Borrow event. */ emit Borrow(msg.sender, borrowAmount); return true; } /** * @notice Destroys `burnAmount` tokens from `holder`, reducing the token supply. * * @dev Emits a {Burn} and a {Transfer} event. * * Requirements: * * - Must be called prior to maturation. * - Can only be called by the Redemption Pool. * - The amount to burn cannot be zero. * * @param holder The account whose fyTokens to burn. * @param burnAmount The amount of fyTokens to burn. * @return bool true = success, otherwise it reverts. */ function burn(address holder, uint256 burnAmount) external override nonReentrant returns (bool) { /* Checks: the caller is the Redemption Pool. */ require(msg.sender == address(redemptionPool), "ERR_BURN_NOT_AUTHORIZED"); /* Checks: the zero edge case. */ require(burnAmount > 0, "ERR_BURN_ZERO"); /* Effects: burns the fyTokens. */ burnInternal(holder, burnAmount); /* Emit a Transfer event. */ emit Transfer(holder, address(this), burnAmount); return true; } struct LiquidateBorrowsLocalVars { MathError mathErr; uint256 collateralizationRatioMantissa; uint256 lockedCollateral; bool isAccountUnderwater; } /** * @notice Repays the debt of the borrower and rewards the caler with a surplus of collateral. * * @dev Emits a {RepayBorrow}, {Transfer}, {ClutchCollateral} and {LiquidateBorrow} event. * * Requirements: * * - The vault must be open. * - The liquidator cannot liquidate themselves. * - The amount to repay cannot be zero. * - The Fintroller must allow this action to be performed. * - The borrower must be underwater if the bond didn't mature. * - The caller must have at least `repayAmount` fyTokens. * - The borrower must have at least `repayAmount` debt. * - The amount of clutched collateral cannot be more than what the borrower has in the vault. * * @param borrower The account to liquidate. * @param repayAmount The amount of fyTokens to repay. * @return bool true = success, otherwise it reverts. */ function liquidateBorrow(address borrower, uint256 repayAmount) external override isVaultOpen(borrower) nonReentrant returns (bool) { LiquidateBorrowsLocalVars memory vars; /* Checks: borrowers cannot self liquidate. */ require(msg.sender != borrower, "ERR_LIQUIDATE_BORROW_SELF"); /* Checks: the zero edge case. */ require(repayAmount > 0, "ERR_LIQUIDATE_BORROW_ZERO"); /* Checks: the Fintroller allows this action to be performed. */ require(fintroller.getLiquidateBorrowAllowed(this), "ERR_LIQUIDATE_BORROW_NOT_ALLOWED"); /* After maturation, any vault can be liquidated, irrespective of collateralization ratio. */ if (isMatured() == false) { /* Checks: the borrower fell below the threshold collateralization ratio. */ vars.isAccountUnderwater = balanceSheet.isAccountUnderwater(this, borrower); require(vars.isAccountUnderwater, "ERR_ACCOUNT_NOT_UNDERWATER"); } /* Effects & Interactions: repay the borrower's debt. */ repayBorrowInternal(msg.sender, borrower, repayAmount); /* Interactions: clutch the collateral. */ uint256 clutchableCollateralAmount = balanceSheet.getClutchableCollateral(this, repayAmount); require( balanceSheet.clutchCollateral(this, msg.sender, borrower, clutchableCollateralAmount), "ERR_LIQUIDATE_BORROW_CALL_CLUTCH_COLLATERAL" ); emit LiquidateBorrow(msg.sender, borrower, repayAmount, clutchableCollateralAmount); return true; } /** /** @notice Prints new tokens into existence and assigns them to `beneficiary`, * increasing the total supply. * * @dev Emits a {Mint} and a {Transfer} event. * * Requirements: * * - Can only be called by the Redemption Pool. * - The amount to mint cannot be zero. * * @param beneficiary The borrower account for which to mint the tokens. * @param mintAmount The amount of fyTokens to print into existence. * @return bool true = success, otherwise it reverts. */ function mint(address beneficiary, uint256 mintAmount) external override nonReentrant returns (bool) { /* Checks: the caller is the Redemption Pool. */ require(msg.sender == address(redemptionPool), "ERR_MINT_NOT_AUTHORIZED"); /* Checks: the zero edge case. */ require(mintAmount > 0, "ERR_MINT_ZERO"); /* Effects: print the new fyTokens into existence. */ mintInternal(beneficiary, mintAmount); /* Emit a Transfer event. */ emit Transfer(address(this), beneficiary, mintAmount); return true; } /** * @notice Deletes the borrower account's debt from the registry and take the fyTokens * out of circulation. * * @dev Emits a {Burn}, {Transfer} and {RepayBorrow} event. * * Requirements: * * - The vault must be open. * - The amount to repay cannot be zero. * - The Fintroller must allow this action to be performed. * - The caller must have at least `repayAmount` fyTokens. * - The caller must have at least `repayAmount` debt. * * @param repayAmount The amount of fyTokens to repay. * @return bool true = success, otherwise it reverts. */ function repayBorrow(uint256 repayAmount) external override isVaultOpen(msg.sender) nonReentrant returns (bool) { repayBorrowInternal(msg.sender, msg.sender, repayAmount); return true; } /** * @notice Clears the borrower account's debt from the registry and take the fyTokens * out of circulation. * * @dev Emits a {Burn}, {Transfer} and {RepayBorrow} event. * * Requirements: same as the `repayBorrow` function, but here `borrower` is the account that must * have at least `repayAmount` fyTokens to repay the borrow. * * @param borrower The borrower account for which to repay the borrow. * @param repayAmount The amount of fyTokens to repay. * @return bool true = success, otherwise it reverts. */ function repayBorrowBehalf(address borrower, uint256 repayAmount) external override isVaultOpen(borrower) nonReentrant returns (bool) { repayBorrowInternal(msg.sender, borrower, repayAmount); return true; } /** * @notice Updates the Fintroller contract's address saved in storage. * * @dev Throws a {SetFintroller} event. * * Requirements: * * - The caller must be the admin. * - The new Fintroller must pass the inspection. * * @param newFintroller The address of the new Fintroller contract. * @return bool true = success, otherwise it reverts. */ function _setFintroller(FintrollerInterface newFintroller) external override onlyAdmin returns (bool) { /* Checks: sanity check the new Fintroller contract. */ require(newFintroller.isFintroller(), "ERR_SET_FINTROLLER_INSPECTION"); /* Effects: update storage. */ FintrollerInterface oldFintroller = fintroller; fintroller = newFintroller; emit SetFintroller(admin, oldFintroller, newFintroller); return true; } /** * INTERNAL FUNCTIONS */ /** * @dev See the documentation for the public functions that call this internal function. */ function repayBorrowInternal( address payer, address borrower, uint256 repayAmount ) internal { /* Checks: the zero edge case. */ require(repayAmount > 0, "ERR_REPAY_BORROW_ZERO"); /* Checks: the Fintroller allows this action to be performed. */ require(fintroller.getRepayBorrowAllowed(this), "ERR_REPAY_BORROW_NOT_ALLOWED"); /* Checks: borrower has a debt to pay. */ uint256 debt = balanceSheet.getVaultDebt(this, borrower); require(debt >= repayAmount, "ERR_REPAY_BORROW_INSUFFICIENT_DEBT"); /* Checks: the payer has enough fyTokens. */ require(balanceOf(payer) >= repayAmount, "ERR_REPAY_BORROW_INSUFFICIENT_BALANCE"); /* Effects: burn the fyTokens. */ burnInternal(payer, repayAmount); /* Emit a Transfer event. */ emit Transfer(payer, address(this), repayAmount); /* Calculate the new debt of the borrower. */ MathError mathErr; uint256 newDebt; (mathErr, newDebt) = subUInt(debt, repayAmount); /* This operation can't fail because of the previous `require`. */ assert(mathErr == MathError.NO_ERROR); /* Interactions: reduce the debt of the borrower . */ require(balanceSheet.setVaultDebt(this, borrower, newDebt), "ERR_REPAY_BORROW_CALL_SET_VAULT_DEBT"); /* Emit both a RepayBorrow event. */ emit RepayBorrow(payer, borrower, repayAmount, newDebt); } }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; /** * @title Address * @author Paul Razvan Berg * @notice Collection of functions related to the address type. * @dev Forked from OpenZeppelin * https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v3.1.0/contracts/utils/Address.sol */ 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) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')`. bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; /* solhint-disable-next-line no-inline-assembly */ assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./AdminInterface.sol"; /** * @title Admin * @author Paul Razvan Berg * @notice Contract module which provides a basic access control mechanism, where there is * an account (an admin) that can be granted exclusive access to specific functions. * * By default, the admin account will be the one that deploys the contract. This can later * be changed with {transferAdmin}. * * This module is used through inheritance. It will make available the modifier `onlyAdmin`, * which can be applied to your functions to restrict their use to the admin. * * @dev Forked from OpenZeppelin * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/access/Ownable.sol */ abstract contract Admin is AdminInterface { /** * @notice Throws if called by any account other than the admin. */ modifier onlyAdmin() { require(admin == msg.sender, "ERR_NOT_ADMIN"); _; } /** * @notice Initializes the contract setting the deployer as the initial admin. */ constructor() { address msgSender = msg.sender; admin = msgSender; emit TransferAdmin(address(0x00), msgSender); } /** * @notice Leaves the contract without admin, so it will not be possible to call * `onlyAdmin` functions anymore. * * Requirements: * * - The caller must be the administrator. * * WARNING: Doing this will leave the contract without an admin, * thereby removing any functionality that is only available to the admin. */ function _renounceAdmin() external virtual override onlyAdmin { emit TransferAdmin(admin, address(0x00)); admin = address(0x00); } /** * @notice Transfers the admin of the contract to a new account (`newAdmin`). * Can only be called by the current admin. * @param newAdmin The acount of the new admin. */ function _transferAdmin(address newAdmin) external virtual override onlyAdmin { require(newAdmin != address(0x00), "ERR_SET_ADMIN_ZERO_ADDRESS"); emit TransferAdmin(admin, newAdmin); admin = newAdmin; } }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./AdminStorage.sol"; /** * @title AdminInterface * @author Paul Razvan Berg */ abstract contract AdminInterface is AdminStorage { /** * NON-CONSTANT FUNCTIONS */ function _renounceAdmin() external virtual; function _transferAdmin(address newAdmin) external virtual; /** * EVENTS */ event TransferAdmin(address indexed oldAdmin, address indexed newAdmin); }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; abstract contract AdminStorage { /** * @notice The address of the administrator account or contract. */ address public admin; }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; /** * @title AggregatorV3Interface * @author Hifi * @dev Forked from Chainlink * https://github.com/smartcontractkit/chainlink/blob/v0.9.9/evm-contracts/src/v0.7/interfaces/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 ); }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./BalanceSheetStorage.sol"; /** * @title BalanceSheetInterface * @author Hifi */ abstract contract BalanceSheetInterface is BalanceSheetStorage { /** * CONSTANT FUNCTIONS */ function getClutchableCollateral(FyTokenInterface fyToken, uint256 repayAmount) external view virtual returns (uint256); function getCurrentCollateralizationRatio(FyTokenInterface fyToken, address borrower) public view virtual returns (uint256); function getHypotheticalCollateralizationRatio( FyTokenInterface fyToken, address borrower, uint256 lockedCollateral, uint256 debt ) public view virtual returns (uint256); function getVault(FyTokenInterface fyToken, address borrower) external view virtual returns ( uint256, uint256, uint256, bool ); function getVaultDebt(FyTokenInterface fyToken, address borrower) external view virtual returns (uint256); function getVaultLockedCollateral(FyTokenInterface fyToken, address borrower) external view virtual returns (uint256); function isAccountUnderwater(FyTokenInterface fyToken, address borrower) external view virtual returns (bool); function isVaultOpen(FyTokenInterface fyToken, address borrower) external view virtual returns (bool); /** * NON-CONSTANT FUNCTIONS */ function clutchCollateral( FyTokenInterface fyToken, address liquidator, address borrower, uint256 clutchedCollateralAmount ) external virtual returns (bool); function depositCollateral(FyTokenInterface fyToken, uint256 collateralAmount) external virtual returns (bool); function freeCollateral(FyTokenInterface fyToken, uint256 collateralAmount) external virtual returns (bool); function lockCollateral(FyTokenInterface fyToken, uint256 collateralAmount) external virtual returns (bool); function openVault(FyTokenInterface fyToken) external virtual returns (bool); function setVaultDebt( FyTokenInterface fyToken, address borrower, uint256 newVaultDebt ) external virtual returns (bool); function withdrawCollateral(FyTokenInterface fyToken, uint256 collateralAmount) external virtual returns (bool); /** * EVENTS */ event ClutchCollateral( FyTokenInterface indexed fyToken, address indexed liquidator, address indexed borrower, uint256 clutchedCollateralAmount ); event DepositCollateral(FyTokenInterface indexed fyToken, address indexed borrower, uint256 collateralAmount); event FreeCollateral(FyTokenInterface indexed fyToken, address indexed borrower, uint256 collateralAmount); event LockCollateral(FyTokenInterface indexed fyToken, address indexed borrower, uint256 collateralAmount); event OpenVault(FyTokenInterface indexed fyToken, address indexed borrower); event SetVaultDebt(FyTokenInterface indexed fyToken, address indexed borrower, uint256 oldDebt, uint256 newDebt); event WithdrawCollateral(FyTokenInterface indexed fyToken, address indexed borrower, uint256 collateralAmount); }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./FyTokenInterface.sol"; /** * @title BalanceSheetStorage * @author Hifi */ abstract contract BalanceSheetStorage { struct Vault { uint256 debt; uint256 freeCollateral; uint256 lockedCollateral; bool isOpen; } /** * @notice The unique Fintroller associated with this contract. */ FintrollerInterface public fintroller; /** * @dev One vault for each fyToken for each account. */ mapping(address => mapping(address => Vault)) internal vaults; /** * @notice Indicator that this is a BalanceSheet contract, for inspection. */ bool public constant isBalanceSheet = true; }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; /** * @notice Possible error codes that can be returned. */ enum MathError { NO_ERROR, DIVISION_BY_ZERO, INTEGER_OVERFLOW, INTEGER_UNDERFLOW, MODULO_BY_ZERO } /** * @title CarefulMath * @author Paul Razvan Berg * @notice Exponential module for storing fixed-precision decimals. * @dev Forked from Compound * https://github.com/compound-finance/compound-protocol/blob/v2.8.1/contracts/CarefulMath.sol */ abstract contract CarefulMath { /** * @notice Adds two numbers, returns an error on overflow. */ function addUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) { uint256 c = a + b; if (c >= a) { return (MathError.NO_ERROR, c); } else { return (MathError.INTEGER_OVERFLOW, 0); } } /** * @notice Add `a` and `b` and then subtract `c`. */ function addThenSubUInt( uint256 a, uint256 b, uint256 c ) internal pure returns (MathError, uint256) { (MathError err0, uint256 sum) = addUInt(a, b); if (err0 != MathError.NO_ERROR) { return (err0, 0); } return subUInt(sum, c); } /** * @notice Integer division of two numbers, truncating the quotient. */ function divUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) { if (b == 0) { return (MathError.DIVISION_BY_ZERO, 0); } return (MathError.NO_ERROR, a / b); } /** * @notice Returns the remainder of dividing two numbers. * @dev 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). */ function modUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) { if (b == 0) { return (MathError.MODULO_BY_ZERO, 0); } return (MathError.NO_ERROR, a % b); } /** * @notice Multiplies two numbers, returns an error on overflow. */ function mulUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) { if (a == 0) { return (MathError.NO_ERROR, 0); } uint256 c = a * b; if (c / a != b) { return (MathError.INTEGER_OVERFLOW, 0); } else { return (MathError.NO_ERROR, c); } } /** * @notice Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend). */ function subUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) { if (b <= a) { return (MathError.NO_ERROR, a - b); } else { return (MathError.INTEGER_UNDERFLOW, 0); } } }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./CarefulMath.sol"; import "./Erc20Interface.sol"; import "./ChainlinkOperatorStorage.sol"; import "./AggregatorV3Interface.sol"; /** * @title ChainlinkOperatorInterface * @author Hifi */ abstract contract ChainlinkOperatorInterface is ChainlinkOperatorStorage { /** * EVENTS */ event DeleteFeed(Erc20Interface indexed asset, AggregatorV3Interface indexed feed); event SetFeed(Erc20Interface indexed asset, AggregatorV3Interface indexed feed); /** * CONSTANT FUNCTIONS. */ function getAdjustedPrice(string memory symbol) external view virtual returns (uint256); function getFeed(string memory symbol) external view virtual returns ( Erc20Interface, AggregatorV3Interface, bool ); function getPrice(string memory symbol) public view virtual returns (uint256); /** * NON-CONSTANT FUNCTIONS. */ function deleteFeed(string memory symbol) external virtual returns (bool); function setFeed(Erc20Interface asset, AggregatorV3Interface feed) external virtual returns (bool); }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./Erc20Interface.sol"; import "./AggregatorV3Interface.sol"; /** * @title ChainlinkOperatorStorage * @author Hifi */ abstract contract ChainlinkOperatorStorage { struct Feed { Erc20Interface asset; AggregatorV3Interface id; bool isSet; } /** * @dev Mapping between Erc20 symbols and Feed structs. */ mapping(string => Feed) internal feeds; /** * @notice Chainlink price precision for USD-quoted data. */ uint256 public constant pricePrecision = 8; /** * @notice The ratio between mantissa precision (1e18) and the Chainlink price precision (1e8). */ uint256 public constant pricePrecisionScalar = 1.0e10; }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./Erc20Interface.sol"; import "./CarefulMath.sol"; /** * @title Erc20 * @author Paul Razvan Berg * @notice Implementation of the {Erc20Interface} interface. * * 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 Erc 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 {Erc20Interface-approve}. * * @dev Forked from OpenZeppelin * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.2.0/contracts/token/Erc20/Erc20.sol */ contract Erc20 is CarefulMath, /* no dependency */ Erc20Interface /* one dependency */ { /** * @notice All three of these values are immutable: they can only be set once during construction. * @param name_ Erc20 name of this token. * @param symbol_ Erc20 symbol of this token. * @param decimals_ Erc20 decimal precision of this token. */ constructor( string memory name_, string memory symbol_, uint8 decimals_ ) { name = name_; symbol = symbol_; decimals = decimals_; } /** * CONSTANT FUNCTIONS */ /** * @notice 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 virtual override returns (uint256) { return allowances[owner][spender]; } /** * @notice Returns the amount of tokens owned by `account`. */ function balanceOf(address account) public view virtual override returns (uint256) { return balances[account]; } /** * NON-CONSTANT FUNCTIONS */ /** * @notice Sets `amount` as the allowance of `spender` over the caller's tokens. * * @dev 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. * * @return a boolean value indicating whether the operation succeeded. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) external virtual override returns (bool) { approveInternal(msg.sender, spender, amount); return true; } /** * @notice Atomically decreases the allowance granted to `spender` by the caller. * * @dev This is an alternative to {approve} that can be used as a mitigation for * problems described in {Erc20Interface-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) external virtual returns (bool) { MathError mathErr; uint256 newAllowance; (mathErr, newAllowance) = subUInt(allowances[msg.sender][spender], subtractedValue); require(mathErr == MathError.NO_ERROR, "ERR_ERC20_DECREASE_ALLOWANCE_UNDERFLOW"); approveInternal(msg.sender, spender, newAllowance); return true; } /** * @notice Atomically increases the allowance granted to `spender` by the caller. * * @dev This is an alternative to {approve} that can be used as a mitigation for * problems described above. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool) { MathError mathErr; uint256 newAllowance; (mathErr, newAllowance) = addUInt(allowances[msg.sender][spender], addedValue); require(mathErr == MathError.NO_ERROR, "ERR_ERC20_INCREASE_ALLOWANCE_OVERFLOW"); approveInternal(msg.sender, spender, newAllowance); return true; } /** * @notice Moves `amount` tokens from the caller's account to `recipient`. * * @dev Emits a {Transfer} event. * * @return a boolean value indicating whether the operation succeeded. * * Requirements: * * - `recipient` cannot be the zero address. * - The caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) external virtual override returns (bool) { transferInternal(msg.sender, recipient, amount); return true; } /** * @notice See Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * @dev Emits a {Transfer} event. Emits an {Approval} event indicating the * updated allowance. This is not required by the Erc. See the note at the * beginning of {Erc20}; * * @return a boolean value indicating whether the operation succeeded. * * 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 ) external virtual override returns (bool) { transferInternal(sender, recipient, amount); MathError mathErr; uint256 newAllowance; (mathErr, newAllowance) = subUInt(allowances[sender][msg.sender], amount); require(mathErr == MathError.NO_ERROR, "ERR_ERC20_TRANSFER_FROM_INSUFFICIENT_ALLOWANCE"); approveInternal(sender, msg.sender, newAllowance); return true; } /** * INTERNAL FUNCTIONS */ /** * @notice Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * @dev 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 approveInternal( address owner, address spender, uint256 amount ) internal virtual { require(owner != address(0x00), "ERR_ERC20_APPROVE_FROM_ZERO_ADDRESS"); require(spender != address(0x00), "ERR_ERC20_APPROVE_TO_ZERO_ADDRESS"); allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @notice Destroys `burnAmount` tokens from `holder`, recuding the token supply. * * @dev Emits a {Burn} event. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `holder` must have at least `amount` tokens. */ function burnInternal(address holder, uint256 burnAmount) internal { MathError mathErr; uint256 newHolderBalance; uint256 newTotalSupply; /* Burn the yTokens. */ (mathErr, newHolderBalance) = subUInt(balances[holder], burnAmount); require(mathErr == MathError.NO_ERROR, "ERR_ERC20_BURN_BALANCE_UNDERFLOW"); balances[holder] = newHolderBalance; /* Reduce the total supply. */ (mathErr, newTotalSupply) = subUInt(totalSupply, burnAmount); require(mathErr == MathError.NO_ERROR, "ERR_ERC20_BURN_TOTAL_SUPPLY_UNDERFLOW"); totalSupply = newTotalSupply; emit Burn(holder, burnAmount); } /** @notice Prints new tokens into existence and assigns them to `beneficiary`, * increasing the total supply. * * @dev Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - The beneficiary's balance and the total supply cannot overflow. */ function mintInternal(address beneficiary, uint256 mintAmount) internal { MathError mathErr; uint256 newBeneficiaryBalance; uint256 newTotalSupply; /* Mint the yTokens. */ (mathErr, newBeneficiaryBalance) = addUInt(balances[beneficiary], mintAmount); require(mathErr == MathError.NO_ERROR, "ERR_ERC20_MINT_BALANCE_OVERFLOW"); balances[beneficiary] = newBeneficiaryBalance; /* Increase the total supply. */ (mathErr, newTotalSupply) = addUInt(totalSupply, mintAmount); require(mathErr == MathError.NO_ERROR, "ERR_ERC20_MINT_TOTAL_SUPPLY_OVERFLOW"); totalSupply = newTotalSupply; emit Mint(beneficiary, mintAmount); } /** * @notice Moves `amount` tokens from `sender` to `recipient`. * * @dev 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 transferInternal( address sender, address recipient, uint256 amount ) internal virtual { require(sender != address(0x00), "ERR_ERC20_TRANSFER_FROM_ZERO_ADDRESS"); require(recipient != address(0x00), "ERR_ERC20_TRANSFER_TO_ZERO_ADDRESS"); MathError mathErr; uint256 newSenderBalance; uint256 newRecipientBalance; (mathErr, newSenderBalance) = subUInt(balances[sender], amount); require(mathErr == MathError.NO_ERROR, "ERR_ERC20_TRANSFER_SENDER_BALANCE_UNDERFLOW"); balances[sender] = newSenderBalance; (mathErr, newRecipientBalance) = addUInt(balances[recipient], amount); assert(mathErr == MathError.NO_ERROR); balances[recipient] = newRecipientBalance; emit Transfer(sender, recipient, amount); } }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./Erc20Storage.sol"; /** * @title Erc20Interface * @author Paul Razvan Berg * @notice Interface of the Erc20 standard * @dev Forked from OpenZeppelin * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.2.0/contracts/token/ERC20/IERC20.sol */ abstract contract Erc20Interface is Erc20Storage { /** * CONSTANT FUNCTIONS */ function allowance(address owner, address spender) external view virtual returns (uint256); function balanceOf(address account) external view virtual returns (uint256); /** * NON-CONSTANT FUNCTIONS */ function approve(address spender, uint256 amount) external virtual returns (bool); function transfer(address recipient, uint256 amount) external virtual returns (bool); function transferFrom( address sender, address recipient, uint256 amount ) external virtual returns (bool); /** * EVENTS */ event Approval(address indexed owner, address indexed spender, uint256 amount); event Burn(address indexed holder, uint256 burnAmount); event Mint(address indexed beneficiary, uint256 mintAmount); event Transfer(address indexed from, address indexed to, uint256 amount); }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./Erc20.sol"; import "./Erc20PermitInterface.sol"; /** * @title Erc20Permit * @author Paul Razvan Berg * @notice Extension of Erc20 that allows token holders to use their tokens * without sending any transactions by setting the allowance with a signature * using the `permit` method, and then spend them via `transferFrom`. * @dev See https://eips.ethereum.org/EIPS/eip-2612. */ contract Erc20Permit is Erc20PermitInterface, /* one dependency */ Erc20 /* three dependencies */ { constructor( string memory name_, string memory symbol_, uint8 decimals_ ) Erc20(name_, symbol_, decimals_) { uint256 chainId; /* solhint-disable-next-line no-inline-assembly */ assembly { chainId := chainid() } DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256(bytes(version)), chainId, address(this) ) ); } /** * @dev Sets `amount` as the allowance of `spender` over `owner`'s tokens, * assuming the latter's signed approval. * * IMPORTANT: The same issues Erc20 `approve` has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the Eip712-formatted function arguments. * - The signature must use `owner`'s current nonce. */ function permit( address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external override { require(owner != address(0x00), "ERR_ERC20_PERMIT_OWNER_ZERO_ADDRESS"); require(spender != address(0x00), "ERR_ERC20_PERMIT_SPENDER_ZERO_ADDRESS"); require(deadline >= block.timestamp, "ERR_ERC20_PERMIT_EXPIRED"); /* It's safe to use the "+" operator here because the nonce cannot realistically overflow, ever. */ bytes32 hashStruct = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, amount, nonces[owner]++, deadline)); bytes32 digest = keccak256(abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR, hashStruct)); address recoveredOwner = ecrecover(digest, v, r, s); require(recoveredOwner != address(0x00), "ERR_ERC20_PERMIT_RECOVERED_OWNER_ZERO_ADDRESS"); require(recoveredOwner == owner, "ERR_ERC20_PERMIT_INVALID_SIGNATURE"); approveInternal(owner, spender, amount); } }
/* SPDX-License-Identifier: MIT */ /* solhint-disable var-name-mixedcase */ pragma solidity ^0.7.0; import "./Erc20PermitStorage.sol"; /** * @notice Erc20PermitInterface * @author Paul Razvan Berg */ abstract contract Erc20PermitInterface is Erc20PermitStorage { /** * NON-CONSTANT FUNCTIONS */ function permit( address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external virtual; }
/* SPDX-License-Identifier: MIT */ /* solhint-disable var-name-mixedcase */ pragma solidity ^0.7.0; /** * @notice Erc20PermitStorage * @author Paul Razvan Berg */ abstract contract Erc20PermitStorage { /** * @notice The Eip712 domain's keccak256 hash. */ bytes32 public DOMAIN_SEPARATOR; /** * @notice keccak256("Permit(address owner,address spender,uint256 amount,uint256 nonce,uint256 deadline)"); */ bytes32 public constant PERMIT_TYPEHASH = 0xfc77c2b9d30fe91687fd39abb7d16fcdfe1472d065740051ab8b13e4bf4a617f; /** * @notice Provides replay protection. */ mapping(address => uint256) public nonces; /** * @notice Eip712 version of this implementation. */ string public constant version = "1"; }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./Admin.sol"; import "./Erc20Interface.sol"; import "./Erc20RecoverInterface.sol"; import "./SafeErc20.sol"; /** * @title Erc20Recover * @author Paul Razvan Berg * @notice Gives the administrator the ability to recover the Erc20 tokens that * had been sent (accidentally, or not) to the contract. */ abstract contract Erc20Recover is Erc20RecoverInterface, /* one dependency */ Admin /* two dependencies */ { using SafeErc20 for Erc20Interface; /** * @notice Sets the tokens that this contract cannot recover. * * @dev Emits a {SetNonRecoverableTokens} event. * * Requirements: * * - The caller must be the administrator. * - The contract must be non-initialized. * - The array of given tokens cannot be empty. * * @param tokens The array of tokens to set as non-recoverable. */ function _setNonRecoverableTokens(Erc20Interface[] calldata tokens) external override onlyAdmin { /* Checks */ require(isRecoverInitialized == false, "ERR_INITALIZED"); /* Iterate over the token list, sanity check each and update the mapping. */ uint256 length = tokens.length; for (uint256 i = 0; i < length; i += 1) { tokens[i].symbol(); nonRecoverableTokens.push(tokens[i]); } /* Effects: prevent this function from ever being called again. */ isRecoverInitialized = true; emit SetNonRecoverableTokens(admin, tokens); } /** * @notice Recover Erc20 tokens sent to this contract (by accident or otherwise). * @dev Emits a {RecoverToken} event. * * Requirements: * * - The caller must be the administrator. * - The contract must be initialized. * - The amount to recover cannot be zero. * - The token to recover cannot be among the non-recoverable tokens. * * @param token The token to make the recover for. * @param recoverAmount The uint256 amount to recover, specified in the token's decimal system. */ function _recover(Erc20Interface token, uint256 recoverAmount) external override onlyAdmin { /* Checks */ require(isRecoverInitialized == true, "ERR_NOT_INITALIZED"); require(recoverAmount > 0, "ERR_RECOVER_ZERO"); bytes32 tokenSymbolHash = keccak256(bytes(token.symbol())); uint256 length = nonRecoverableTokens.length; /** * We iterate over the non-recoverable token array and check that: * * 1. The addresses of the tokens are not the same * 2. The symbols of the tokens are not the same * * It is true that the second check may lead to a false positive, but * there is no better way to fend off against proxied tokens. */ for (uint256 i = 0; i < length; i += 1) { require( address(token) != address(nonRecoverableTokens[i]) && tokenSymbolHash != keccak256(bytes(nonRecoverableTokens[i].symbol())), "ERR_RECOVER_NON_RECOVERABLE_TOKEN" ); } /* Interactions */ token.safeTransfer(admin, recoverAmount); emit Recover(admin, token, recoverAmount); } }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./Erc20Interface.sol"; import "./Erc20RecoverStorage.sol"; abstract contract Erc20RecoverInterface is Erc20RecoverStorage { /** * NON-CONSTANT FUNCTIONS */ function _recover(Erc20Interface token, uint256 recoverAmount) external virtual; function _setNonRecoverableTokens(Erc20Interface[] calldata tokens) external virtual; /** * EVENTS */ event Recover(address indexed admin, Erc20Interface token, uint256 recoverAmount); event SetNonRecoverableTokens(address indexed admin, Erc20Interface[] nonRecoverableTokens); }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./Erc20Interface.sol"; abstract contract Erc20RecoverStorage { /** * @notice The tokens that can be recovered cannot be in this mapping. */ Erc20Interface[] public nonRecoverableTokens; /** * @dev A flag that signals whether the the non-recoverable tokens were set or not. */ bool internal isRecoverInitialized; }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; /** * @title ExponentialStorage * @author Paul Razvan Berg * @notice The storage interface ancillary to an Erc20 contract. */ abstract contract Erc20Storage { /** * @notice Returns the number of decimals used to get its user representation. */ uint8 public decimals; /** * @notice Returns the name of the token. */ string public name; /** * @notice Returns the symbol of the token, usually a shorter version of * the name. */ string public symbol; /** * @notice Returns the amount of tokens in existence. */ uint256 public totalSupply; mapping(address => mapping(address => uint256)) internal allowances; mapping(address => uint256) internal balances; }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./CarefulMath.sol"; import "./ExponentialStorage.sol"; /** * @title Exponential module for storing fixed-precision decimals. * @author Paul Razvan Berg * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places. * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is: `Exp({mantissa: 5100000000000000000})`. * @dev Forked from Compound * https://github.com/compound-finance/compound-protocol/blob/v2.6/contracts/Exponential.sol */ abstract contract Exponential is CarefulMath, /* no dependency */ ExponentialStorage /* no dependency */ { /** * @dev Adds two exponentials, returning a new exponential. */ function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) { (MathError error, uint256 result) = addUInt(a.mantissa, b.mantissa); return (error, Exp({ mantissa: result })); } /** * @dev Divides two exponentials, returning a new exponential. * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b. * NOTE: Returns an error if (`num` * 10e18) > MAX_INT, or if `denom` is zero. */ function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) { (MathError err0, uint256 scaledNumerator) = mulUInt(a.mantissa, expScale); if (err0 != MathError.NO_ERROR) { return (err0, Exp({ mantissa: 0 })); } (MathError err1, uint256 rational) = divUInt(scaledNumerator, b.mantissa); if (err1 != MathError.NO_ERROR) { return (err1, Exp({ mantissa: 0 })); } return (MathError.NO_ERROR, Exp({ mantissa: rational })); } /** * @dev Multiplies two exponentials, returning a new exponential. */ function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) { (MathError err0, uint256 doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa); if (err0 != MathError.NO_ERROR) { return (err0, Exp({ mantissa: 0 })); } /* * We add half the scale before dividing so that we get rounding instead of truncation. * See "Listing 6" and text above it at https://accu.org/index.php/journals/1717 * Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18. */ (MathError err1, uint256 doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct); if (err1 != MathError.NO_ERROR) { return (err1, Exp({ mantissa: 0 })); } (MathError err2, uint256 product) = divUInt(doubleScaledProductWithHalfScale, expScale); /* The only possible error `div` is MathError.DIVISION_BY_ZERO but we control `expScale` and it's not zero. */ assert(err2 == MathError.NO_ERROR); return (MathError.NO_ERROR, Exp({ mantissa: product })); } /** * @dev Multiplies three exponentials, returning a new exponential. */ function mulExp3( Exp memory a, Exp memory b, Exp memory c ) internal pure returns (MathError, Exp memory) { (MathError err, Exp memory ab) = mulExp(a, b); if (err != MathError.NO_ERROR) { return (err, ab); } return mulExp(ab, c); } /** * @dev Subtracts two exponentials, returning a new exponential. */ function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) { (MathError error, uint256 result) = subUInt(a.mantissa, b.mantissa); return (error, Exp({ mantissa: result })); } }
/* SPDX-License-Identifier: LPGL-3.0-or-later */ pragma solidity ^0.7.0; /** * @title ExponentialStorage * @author Paul Razvan Berg * @notice The storage interface ancillary to an Exponential contract. */ abstract contract ExponentialStorage { struct Exp { uint256 mantissa; } /** * @dev In Exponential denomination, 1e18 is 1. */ uint256 internal constant expScale = 1e18; uint256 internal constant halfExpScale = expScale / 2; uint256 internal constant mantissaOne = expScale; }
/* SPDX-License-Identifier: LPGL-3.0-or-later */ pragma solidity ^0.7.0; import "./FintrollerStorage.sol"; import "./FyTokenInterface.sol"; import "./ChainlinkOperatorInterface.sol"; abstract contract FintrollerInterface is FintrollerStorage { /** * CONSTANT FUNCTIONS */ function getBond(FyTokenInterface fyToken) external view virtual returns ( uint256 debtCeiling, uint256 collateralizationRatioMantissa, bool isBorrowAllowed, bool isDepositCollateralAllowed, bool isLiquidateBorrowAllowed, bool isListed, bool isRedeemFyTokenAllowed, bool isRepayBorrowAllowed, bool isSupplyUnderlyingAllowed ); function getBorrowAllowed(FyTokenInterface fyToken) external view virtual returns (bool); function getBondCollateralizationRatio(FyTokenInterface fyToken) external view virtual returns (uint256); function getBondDebtCeiling(FyTokenInterface fyToken) external view virtual returns (uint256); function getDepositCollateralAllowed(FyTokenInterface fyToken) external view virtual returns (bool); function getLiquidateBorrowAllowed(FyTokenInterface fyToken) external view virtual returns (bool); function getRedeemFyTokensAllowed(FyTokenInterface fyToken) external view virtual returns (bool); function getRepayBorrowAllowed(FyTokenInterface fyToken) external view virtual returns (bool); function getSupplyUnderlyingAllowed(FyTokenInterface fyToken) external view virtual returns (bool); /** * NON-CONSTANT FUNCTIONS */ function listBond(FyTokenInterface fyToken) external virtual returns (bool); function setBondCollateralizationRatio(FyTokenInterface fyToken, uint256 newCollateralizationRatioMantissa) external virtual returns (bool); function setBondDebtCeiling(FyTokenInterface fyToken, uint256 newDebtCeiling) external virtual returns (bool); function setBorrowAllowed(FyTokenInterface fyToken, bool state) external virtual returns (bool); function setDepositCollateralAllowed(FyTokenInterface fyToken, bool state) external virtual returns (bool); function setLiquidateBorrowAllowed(FyTokenInterface fyToken, bool state) external virtual returns (bool); function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external virtual returns (bool); function setOracle(ChainlinkOperatorInterface newOracle) external virtual returns (bool); function setRedeemFyTokensAllowed(FyTokenInterface fyToken, bool state) external virtual returns (bool); function setRepayBorrowAllowed(FyTokenInterface fyToken, bool state) external virtual returns (bool); function setSupplyUnderlyingAllowed(FyTokenInterface fyToken, bool state) external virtual returns (bool); /** * EVENTS */ event ListBond(address indexed admin, FyTokenInterface indexed fyToken); event SetBorrowAllowed(address indexed admin, FyTokenInterface indexed fyToken, bool state); event SetBondCollateralizationRatio( address indexed admin, FyTokenInterface indexed fyToken, uint256 oldCollateralizationRatio, uint256 newCollateralizationRatio ); event SetBondDebtCeiling( address indexed admin, FyTokenInterface indexed fyToken, uint256 oldDebtCeiling, uint256 newDebtCeiling ); event SetDepositCollateralAllowed(address indexed admin, FyTokenInterface indexed fyToken, bool state); event SetLiquidateBorrowAllowed(address indexed admin, FyTokenInterface indexed fyToken, bool state); event SetLiquidationIncentive( address indexed admin, uint256 oldLiquidationIncentive, uint256 newLiquidationIncentive ); event SetRedeemFyTokensAllowed(address indexed admin, FyTokenInterface indexed fyToken, bool state); event SetRepayBorrowAllowed(address indexed admin, FyTokenInterface indexed fyToken, bool state); event SetOracle(address indexed admin, address oldOracle, address newOracle); event SetSupplyUnderlyingAllowed(address indexed admin, FyTokenInterface indexed fyToken, bool state); }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./Exponential.sol"; import "./FyTokenInterface.sol"; import "./ChainlinkOperatorInterface.sol"; /** * @title FintrollerStorage * @author Hifi */ abstract contract FintrollerStorage is Exponential { struct Bond { Exp collateralizationRatio; uint256 debtCeiling; bool isBorrowAllowed; bool isDepositCollateralAllowed; bool isLiquidateBorrowAllowed; bool isListed; bool isRedeemFyTokenAllowed; bool isRepayBorrowAllowed; bool isSupplyUnderlyingAllowed; } /** * @dev Maps the fyToken address to the Bond structs. */ mapping(FyTokenInterface => Bond) internal bonds; /** * @notice The contract that provides price data for the collateral and the underlying asset. */ ChainlinkOperatorInterface public oracle; /** * @notice Multiplier representing the discount on collateral that a liquidator receives. */ uint256 public liquidationIncentiveMantissa; /** * @dev The threshold below which the collateralization ratio cannot be set, equivalent to 100%. */ uint256 internal constant collateralizationRatioLowerBoundMantissa = 1.0e18; /** * @dev The threshold above which the collateralization ratio cannot be set, equivalent to 10,000%. */ uint256 internal constant collateralizationRatioUpperBoundMantissa = 1.0e20; /** * @dev The dafault collateralization ratio set when a new bond is listed, equivalent to 150%. */ uint256 internal constant defaultCollateralizationRatioMantissa = 1.5e18; /** * @dev The threshold below which the liquidation incentive cannot be set, equivalent to 100%. */ uint256 internal constant liquidationIncentiveLowerBoundMantissa = 1.0e18; /** * @dev The threshold above which the liquidation incentive cannot be set, equivalent to 150%. */ uint256 internal constant liquidationIncentiveUpperBoundMantissa = 1.5e18; /** * @notice Indicator that this is a Fintroller contract, for inspection. */ bool public constant isFintroller = true; }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./Erc20Interface.sol"; import "./FyTokenStorage.sol"; /** * @title FyTokenInterface * @author Hifi */ abstract contract FyTokenInterface is FyTokenStorage, /* no dependency */ Erc20Interface /* one dependency */ { /** * CONSTANT FUNCTIONS */ function isMatured() public view virtual returns (bool); /** * NON-CONSTANT FUNCTIONS */ function borrow(uint256 borrowAmount) external virtual returns (bool); function burn(address holder, uint256 burnAmount) external virtual returns (bool); function liquidateBorrow(address borrower, uint256 repayAmount) external virtual returns (bool); function mint(address beneficiary, uint256 mintAmount) external virtual returns (bool); function repayBorrow(uint256 repayAmount) external virtual returns (bool); function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (bool); function _setFintroller(FintrollerInterface newFintroller) external virtual returns (bool); /** * EVENTS */ event Borrow(address indexed borrower, uint256 borrowAmount); event LiquidateBorrow( address indexed liquidator, address indexed borrower, uint256 repayAmount, uint256 clutchedCollateralAmount ); event RepayBorrow(address indexed payer, address indexed borrower, uint256 repayAmount, uint256 newDebt); event SetFintroller(address indexed admin, FintrollerInterface oldFintroller, FintrollerInterface newFintroller); }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./Erc20Interface.sol"; import "./BalanceSheetInterface.sol"; import "./FintrollerInterface.sol"; import "./RedemptionPoolInterface.sol"; /** * @title FyTokenStorage * @author Hifi */ abstract contract FyTokenStorage { /** * STORAGE PROPERTIES */ /** * @notice The global debt registry. */ BalanceSheetInterface public balanceSheet; /** * @notice The Erc20 asset that backs the borrows of this fyToken. */ Erc20Interface public collateral; /** * @notice The ratio between mantissa precision (1e18) and the collateral precision. */ uint256 public collateralPrecisionScalar; /** * @notice Unix timestamp in seconds for when this token expires. */ uint256 public expirationTime; /** * @notice The unique Fintroller associated with this contract. */ FintrollerInterface public fintroller; /** * @notice The unique Redemption Pool associated with this contract. */ RedemptionPoolInterface public redemptionPool; /** * @notice The Erc20 underlying, or target, asset for this fyToken. */ Erc20Interface public underlying; /** * @notice The ratio between mantissa precision (1e18) and the underlying precision. */ uint256 public underlyingPrecisionScalar; /** * @notice Indicator that this is a FyToken contract, for inspection. */ bool public constant isFyToken = true; }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./Admin.sol"; import "./CarefulMath.sol"; import "./Erc20Interface.sol"; import "./Erc20Recover.sol"; import "./SafeErc20.sol"; import "./ReentrancyGuard.sol"; import "./FintrollerInterface.sol"; import "./RedemptionPoolInterface.sol"; /** * @title RedemptionPool * @author Hifi * @notice Mints 1 fyToken in exhchange for 1 underlying before maturation and burns 1 fyToken * in exchange for 1 underlying after maturation. * @dev Instantiated by the fyToken in its constructor. */ contract RedemptionPool is CarefulMath, /* no dependency */ ReentrancyGuard, /* no dependency */ RedemptionPoolInterface, /* one dependency */ Admin, /* two dependencies */ Erc20Recover /* five dependencies */ { using SafeErc20 for Erc20Interface; /** * @param fintroller_ The address of the Fintroller contract. * @param fyToken_ The address of the fyToken contract. */ constructor(FintrollerInterface fintroller_, FyTokenInterface fyToken_) Admin() { /* Set the Fintroller contract and sanity check it. */ fintroller = fintroller_; fintroller.isFintroller(); /** * Set the fyToken contract. It cannot be sanity-checked because the fyToken creates this * contract in its own constructor and contracts cannot be called while initializing. */ fyToken = fyToken_; } struct RedeemFyTokensLocalVars { MathError mathErr; uint256 newUnderlyingTotalSupply; uint256 underlyingPrecisionScalar; uint256 underlyingAmount; } /** * @notice Pays the token holder the face value at maturation time. * * @dev Emits a {RedeemFyTokens} event. * * Requirements: * * - Must be called after maturation. * - The amount to redeem cannot be zero. * - The Fintroller must allow this action to be performed. * - There must be enough liquidity in the Redemption Pool. * * @param fyTokenAmount The amount of fyTokens to redeem for the underlying asset. * @return bool true = success, otherwise it reverts. */ function redeemFyTokens(uint256 fyTokenAmount) external override nonReentrant returns (bool) { RedeemFyTokensLocalVars memory vars; /* Checks: maturation time. */ require(block.timestamp >= fyToken.expirationTime(), "ERR_BOND_NOT_MATURED"); /* Checks: the zero edge case. */ require(fyTokenAmount > 0, "ERR_REDEEM_FYTOKENS_ZERO"); /* Checks: the Fintroller allows this action to be performed. */ require(fintroller.getRedeemFyTokensAllowed(fyToken), "ERR_REDEEM_FYTOKENS_NOT_ALLOWED"); /** * fyTokens always have 18 decimals so the underlying amount needs to be downscaled. * If the precision scalar is 1, it means that the underlying also has 18 decimals. */ vars.underlyingPrecisionScalar = fyToken.underlyingPrecisionScalar(); if (vars.underlyingPrecisionScalar != 1) { (vars.mathErr, vars.underlyingAmount) = divUInt(fyTokenAmount, vars.underlyingPrecisionScalar); require(vars.mathErr == MathError.NO_ERROR, "ERR_REDEEM_FYTOKENS_MATH_ERROR"); } else { vars.underlyingAmount = fyTokenAmount; } /* Checks: there is enough liquidity. */ require(vars.underlyingAmount <= totalUnderlyingSupply, "ERR_REDEEM_FYTOKENS_INSUFFICIENT_UNDERLYING"); /* Effects: decrease the remaining supply of underlying. */ (vars.mathErr, vars.newUnderlyingTotalSupply) = subUInt(totalUnderlyingSupply, vars.underlyingAmount); assert(vars.mathErr == MathError.NO_ERROR); totalUnderlyingSupply = vars.newUnderlyingTotalSupply; /* Interactions: burn the fyTokens. */ require(fyToken.burn(msg.sender, fyTokenAmount), "ERR_SUPPLY_UNDERLYING_CALL_BURN"); /* Interactions: perform the Erc20 transfer. */ fyToken.underlying().safeTransfer(msg.sender, vars.underlyingAmount); emit RedeemFyTokens(msg.sender, fyTokenAmount, vars.underlyingAmount); return true; } struct SupplyUnderlyingLocalVars { MathError mathErr; uint256 fyTokenAmount; uint256 newUnderlyingTotalSupply; uint256 underlyingPrecisionScalar; } /** * @notice An alternative to the usual minting method that does not involve taking on debt. * * @dev Emits a {SupplyUnderlying} event. * * Requirements: * * - Must be called prior to maturation. * - The amount to supply cannot be zero. * - The Fintroller must allow this action to be performed. * - The caller must have allowed this contract to spend `underlyingAmount` tokens. * * @param underlyingAmount The amount of underlying to supply to the Redemption Pool. * @return bool true = success, otherwise it reverts. */ function supplyUnderlying(uint256 underlyingAmount) external override nonReentrant returns (bool) { SupplyUnderlyingLocalVars memory vars; /* Checks: maturation time. */ require(block.timestamp < fyToken.expirationTime(), "ERR_BOND_MATURED"); /* Checks: the zero edge case. */ require(underlyingAmount > 0, "ERR_SUPPLY_UNDERLYING_ZERO"); /* Checks: the Fintroller allows this action to be performed. */ require(fintroller.getSupplyUnderlyingAllowed(fyToken), "ERR_SUPPLY_UNDERLYING_NOT_ALLOWED"); /* Effects: update storage. */ (vars.mathErr, vars.newUnderlyingTotalSupply) = addUInt(totalUnderlyingSupply, underlyingAmount); require(vars.mathErr == MathError.NO_ERROR, "ERR_SUPPLY_UNDERLYING_MATH_ERROR"); totalUnderlyingSupply = vars.newUnderlyingTotalSupply; /** * fyTokens always have 18 decimals so the underlying amount needs to be upscaled. * If the precision scalar is 1, it means that the underlying also has 18 decimals. */ vars.underlyingPrecisionScalar = fyToken.underlyingPrecisionScalar(); if (vars.underlyingPrecisionScalar != 1) { (vars.mathErr, vars.fyTokenAmount) = mulUInt(underlyingAmount, vars.underlyingPrecisionScalar); require(vars.mathErr == MathError.NO_ERROR, "ERR_SUPPLY_UNDERLYING_MATH_ERROR"); } else { vars.fyTokenAmount = underlyingAmount; } /* Interactions: mint the fyTokens. */ require(fyToken.mint(msg.sender, vars.fyTokenAmount), "ERR_SUPPLY_UNDERLYING_CALL_MINT"); /* Interactions: perform the Erc20 transfer. */ fyToken.underlying().safeTransferFrom(msg.sender, address(this), underlyingAmount); emit SupplyUnderlying(msg.sender, underlyingAmount, vars.fyTokenAmount); return true; } }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./RedemptionPoolStorage.sol"; /** * @title RedemptionPoolInterface * @author Hifi */ abstract contract RedemptionPoolInterface is RedemptionPoolStorage { /** * NON-CONSTANT FUNCTIONS */ function redeemFyTokens(uint256 fyTokenAmount) external virtual returns (bool); function supplyUnderlying(uint256 underlyingAmount) external virtual returns (bool); /** * EVENTS */ event RedeemFyTokens(address indexed account, uint256 fyTokenAmount, uint256 underlyingAmount); event SupplyUnderlying(address indexed account, uint256 underlyingAmount, uint256 fyTokenAmount); }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; import "./FintrollerInterface.sol"; import "./FyTokenInterface.sol"; /** * @title RedemptionPoolStorage * @author Hifi */ abstract contract RedemptionPoolStorage { /** * @notice The unique Fintroller associated with this contract. */ FintrollerInterface public fintroller; /** * @notice The amount of the underlying asset available to be redeemed after maturation. */ uint256 public totalUnderlyingSupply; /** * The unique fyToken associated with this Redemption Pool. */ FyTokenInterface public fyToken; /** * @notice Indicator that this is a Redemption Pool contract, for inspection. */ bool public constant isRedemptionPool = true; }
/* SPDX-License-Identifier: LGPL-3.0-or-later */ pragma solidity ^0.7.0; /** * @title ReentrancyGuard * @author Paul Razvan Berg * @notice Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * @dev Forked from OpenZeppelin * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.1.0/contracts/math/ReentrancyGuard.sol */ abstract contract ReentrancyGuard { bool private notEntered; /* * Storing an initial non-zero value makes deployment a bit more expensive * but in exchange the refund on every call to nonReentrant will be lower * in amount. Since refunds are capped to a percetange of the total * transaction's gas, it is best to keep them low in cases like this * one, to increase the likelihood of the full refund coming into effect. */ constructor() { notEntered = true; } /** * @notice Prevents a contract from calling itself, directly or indirectly. * @dev Calling a `nonReentrant` function from another `nonReentrant` function * is not supported. It is possible to prevent this from happening by making * the `nonReentrant` function external, and make it call a `private` * function that does the actual work. */ modifier nonReentrant() { /* On the first call to nonReentrant, _notEntered will be true. */ require(notEntered, "ERR_REENTRANT_CALL"); /* Any calls to nonReentrant after this point will fail. */ notEntered = false; _; /* * By storing the original value once again, a refund is triggered (see * https://eips.ethereum.org/EIPS/eip-2200). */ notEntered = true; } }
/* SPDX-License-Identifier: MIT */ pragma solidity ^0.7.0; import "./Erc20Interface.sol"; import "./Address.sol"; /** * @title SafeErc20.sol * @author Paul Razvan Berg * @notice Wraps around Erc20 operations that throw on failure (when the token contract * returns false). Tokens that return no value (and instead revert or throw * on failure) are also supported, non-reverting calls are assumed to be successful. * * To use this library you can add a `using SafeErc20 for Erc20Interface;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. * * @dev Forked from OpenZeppelin * https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-contracts/v3.1.0/contracts/utils/Address.sol */ library SafeErc20 { using Address for address; /** * INTERNAL FUNCTIONS */ function safeTransfer( Erc20Interface token, address to, uint256 amount ) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, amount)); } function safeTransferFrom( Erc20Interface token, address from, address to, uint256 amount ) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, amount)); } /** * PRIVATE FUNCTIONS */ /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it cannot be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(Erc20Interface token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = functionCall(address(token), data, "ERR_SAFE_ERC20_LOW_LEVEL_CALL"); if (returndata.length > 0) { /* Return data is optional. */ require(abi.decode(returndata, (bool)), "ERR_SAFE_ERC20_ERC20_OPERATION"); } } function functionCall( address target, bytes memory data, string memory errorMessage ) private returns (bytes memory) { require(target.isContract(), "ERR_SAFE_ERC20_CALL_TO_NON_CONTRACT"); /* solhint-disable-next-line avoid-low-level-calls */ (bool success, bytes memory returndata) = target.call(data); 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); } } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint256","name":"expirationTime_","type":"uint256"},{"internalType":"contract FintrollerInterface","name":"fintroller_","type":"address"},{"internalType":"contract BalanceSheetInterface","name":"balanceSheet_","type":"address"},{"internalType":"contract Erc20Interface","name":"underlying_","type":"address"},{"internalType":"contract Erc20Interface","name":"collateral_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"borrowAmount","type":"uint256"}],"name":"Borrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":false,"internalType":"uint256","name":"burnAmount","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidator","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"repayAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"clutchedCollateralAmount","type":"uint256"}],"name":"LiquidateBorrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"contract Erc20Interface","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"recoverAmount","type":"uint256"}],"name":"Recover","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"repayAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDebt","type":"uint256"}],"name":"RepayBorrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"contract FintrollerInterface","name":"oldFintroller","type":"address"},{"indexed":false,"internalType":"contract FintrollerInterface","name":"newFintroller","type":"address"}],"name":"SetFintroller","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"contract Erc20Interface[]","name":"nonRecoverableTokens","type":"address[]"}],"name":"SetNonRecoverableTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":true,"internalType":"address","name":"newAdmin","type":"address"}],"name":"TransferAdmin","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract Erc20Interface","name":"token","type":"address"},{"internalType":"uint256","name":"recoverAmount","type":"uint256"}],"name":"_recover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_renounceAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract FintrollerInterface","name":"newFintroller","type":"address"}],"name":"_setFintroller","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Erc20Interface[]","name":"tokens","type":"address[]"}],"name":"_setNonRecoverableTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"_transferAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceSheet","outputs":[{"internalType":"contract BalanceSheetInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"borrowAmount","type":"uint256"}],"name":"borrow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"uint256","name":"burnAmount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateral","outputs":[{"internalType":"contract Erc20Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralPrecisionScalar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expirationTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fintroller","outputs":[{"internalType":"contract FintrollerInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isFyToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMatured","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"liquidateBorrow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"mintAmount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nonRecoverableTokens","outputs":[{"internalType":"contract Erc20Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redemptionPool","outputs":[{"internalType":"contract RedemptionPoolInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrow","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"borrower","type":"address"},{"internalType":"uint256","name":"repayAmount","type":"uint256"}],"name":"repayBorrowBehalf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"underlying","outputs":[{"internalType":"contract Erc20Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"underlyingPrecisionScalar","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061023d5760003560e01c80637ecebe001161013b578063cab364f1116100b8578063dde4bec01161007c578063dde4bec014610677578063e6abb5ae146106e5578063e6e0d75c1461070b578063ede4c0cc14610737578063f851a4401461073f5761023d565b8063cab364f1146105e0578063d505accf146105e8578063d8dfeb4514610639578063da284dcc14610641578063dd62ed3e146106495761023d565b8063a457c2d7116100ff578063a457c2d71461055b578063a9059cbb14610587578063b2bc5ef9146105b3578063bfa25308146105bb578063c5ebeaec146105c35761023d565b80637ecebe00146104dc5780637f2b6a0d1461050257806395d89b411461050a5780639dc29fac146105125780639e6ae5a01461053e5761023d565b80632608f818116101c957806340c10f191161018d57806340c10f191461047257806354fd4d501461049e5780636f307dc3146104a657806370a08231146104ae5780637c4950c7146104d45761023d565b80632608f818146103ec57806330adf81f14610418578063313ce567146104205780633644e5151461043e57806339509351146104465761023d565b80631a0de6fa116102105780631a0de6fa146103365780631c2872aa1461033e5780631eabf00d1461036c57806322285cf61461039257806323b872dd146103b65761023d565b806306fdde0314610242578063095ea7b3146102bf5780630e752702146102ff57806318160ddd1461031c575b600080fd5b61024a610747565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561028457818101518382015260200161026c565b50505050905090810190601f1680156102b15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102eb600480360360408110156102d557600080fd5b506001600160a01b0381351690602001356107d5565b604080519115158252519081900360200190f35b6102eb6004803603602081101561031557600080fd5b50356107eb565b61032461092e565b60408051918252519081900360200190f35b610324610934565b61036a6004803603604081101561035457600080fd5b506001600160a01b03813516906020013561093a565b005b6102eb6004803603602081101561038257600080fd5b50356001600160a01b0316610d9d565b61039a610f1c565b604080516001600160a01b039092168252519081900360200190f35b6102eb600480360360608110156103cc57600080fd5b506001600160a01b03813581169160208101359091169060400135610f30565b6102eb6004803603604081101561040257600080fd5b506001600160a01b038135169060200135610fd5565b61032461111b565b61042861113f565b6040805160ff9092168252519081900360200190f35b610324611148565b6102eb6004803603604081101561045c57600080fd5b506001600160a01b03813516906020013561114e565b6102eb6004803603604081101561048857600080fd5b506001600160a01b0381351690602001356111e5565b61024a61132e565b61039a61134b565b610324600480360360208110156104c457600080fd5b50356001600160a01b031661135a565b61039a611375565b610324600480360360208110156104f257600080fd5b50356001600160a01b0316611384565b6102eb611396565b61024a61139f565b6102eb6004803603604081101561052857600080fd5b506001600160a01b0381351690602001356113fa565b61039a6004803603602081101561055457600080fd5b5035611543565b6102eb6004803603604081101561057157600080fd5b506001600160a01b03813516906020013561156d565b6102eb6004803603604081101561059d57600080fd5b506001600160a01b0381351690602001356115ee565b6103246115fb565b61036a611601565b6102eb600480360360208110156105d957600080fd5b50356116a5565b6102eb611e9f565b61036a600480360360e08110156105fe57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135611ea4565b61039a612159565b610324612168565b6103246004803603604081101561065f57600080fd5b506001600160a01b038135811691602001351661216e565b61036a6004803603602081101561068d57600080fd5b810190602081018135600160201b8111156106a757600080fd5b8201836020820111156106b957600080fd5b803590602001918460208302840111600160201b831117156106da57600080fd5b509092509050612199565b61036a600480360360208110156106fb57600080fd5b50356001600160a01b0316612460565b6102eb6004803603604081101561072157600080fd5b506001600160a01b038135169060200135612576565b61039a612aca565b61039a612ad9565b600b805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107cd5780601f106107a2576101008083540402835291602001916107cd565b820191906000526020600020905b8154815290600101906020018083116107b057829003601f168201915b505050505081565b60006107e2338484612aed565b50600192915050565b6000805460408051632d3caa7360e21b815230600482015233602482018190529151919261010090046001600160a01b03169163b4f2a9cc91604480820192602092909190829003018186803b15801561084457600080fd5b505afa158015610858573d6000803e3d6000fd5b505050506040513d602081101561086e57600080fd5b50516108b6576040805162461bcd60e51b815260206004820152601260248201527122a9292fab20aaa62a2fa727aa2fa7a822a760711b604482015290519081900360640190fd5b60005460ff16610902576040805162461bcd60e51b815260206004820152601260248201527111549497d4915153951490539517d0d0531360721b604482015290519081900360640190fd5b6000805460ff19169055610917338085612bd9565b60019150506000805460ff19166001179055919050565b600d5481565b60075481565b60115461010090046001600160a01b0316331461098e576040805162461bcd60e51b815260206004820152600d60248201526c22a9292fa727aa2fa0a226a4a760991b604482015290519081900360640190fd5b60115460ff1615156001146109df576040805162461bcd60e51b815260206004820152601260248201527111549497d393d517d253925510531256915160721b604482015290519081900360640190fd5b60008111610a27576040805162461bcd60e51b815260206004820152601060248201526f4552525f5245434f5645525f5a45524f60801b604482015290519081900360640190fd5b6000826001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015610a6257600080fd5b505afa158015610a76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015610a9f57600080fd5b8101908080516040519392919084600160201b821115610abe57600080fd5b908301906020820185811115610ad357600080fd5b8251600160201b811182820188101715610aec57600080fd5b82525081516020918201929091019080838360005b83811015610b19578181015183820152602001610b01565b50505050905090810190601f168015610b465780820380516001836020036101000a031916815260200191505b506040525050508051906020012090506000601080549050905060005b81811015610d275760108181548110610b7857fe5b6000918252602090912001546001600160a01b03868116911614801590610ce4575060108181548110610ba757fe5b6000918252602082200154604080516395d89b4160e01b815290516001600160a01b03909216926395d89b4192600480840193829003018186803b158015610bee57600080fd5b505afa158015610c02573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015610c2b57600080fd5b8101908080516040519392919084600160201b821115610c4a57600080fd5b908301906020820185811115610c5f57600080fd5b8251600160201b811182820188101715610c7857600080fd5b82525081516020918201929091019080838360005b83811015610ca5578181015183820152602001610c8d565b50505050905090810190601f168015610cd25780820380516001836020036101000a031916815260200191505b50604052505050805190602001208314155b610d1f5760405162461bcd60e51b815260040180806020018281038252602181526020018061380d6021913960400191505060405180910390fd5b600101610b63565b50601154610d47906001600160a01b038681169161010090041685612f81565b601154604080516001600160a01b03878116825260208201879052825161010090940416927ff6891c84a6c6af32a6d052172a8acc4c631b1d5057ffa2bc1da268b6938ea2da929181900390910190a250505050565b60115460009061010090046001600160a01b03163314610df4576040805162461bcd60e51b815260206004820152600d60248201526c22a9292fa727aa2fa0a226a4a760991b604482015290519081900360640190fd5b816001600160a01b03166358f25c506040518163ffffffff1660e01b815260040160206040518083038186803b158015610e2d57600080fd5b505afa158015610e41573d6000803e3d6000fd5b505050506040513d6020811015610e5757600080fd5b5051610eaa576040805162461bcd60e51b815260206004820152601d60248201527f4552525f5345545f46494e54524f4c4c45525f494e5350454354494f4e000000604482015290519081900360640190fd5b600480546001600160a01b038481166001600160a01b0319831681179093556011546040805193831680855260208501959095528051610100909204909216927f05f5eff078a94c026377ab6c6bdc6d2ad1932a3e4971fd7473348af3609ec57a92908290030190a250600192915050565b60005461010090046001600160a01b031681565b6000610f3d848484612fd8565b6001600160a01b0384166000908152600e602090815260408083203384529091528120548190610f6d908561316c565b90925090506000826004811115610f8057fe5b14610fbc5760405162461bcd60e51b815260040180806020018281038252602e815260200180613873602e913960400191505060405180910390fd5b610fc7863383612aed565b6001925050505b9392505050565b6000805460408051632d3caa7360e21b81523060048201526001600160a01b0386811660248301529151869361010090049092169163b4f2a9cc91604480820192602092909190829003018186803b15801561103057600080fd5b505afa158015611044573d6000803e3d6000fd5b505050506040513d602081101561105a57600080fd5b50516110a2576040805162461bcd60e51b815260206004820152601260248201527122a9292fab20aaa62a2fa727aa2fa7a822a760711b604482015290519081900360640190fd5b60005460ff166110ee576040805162461bcd60e51b815260206004820152601260248201527111549497d4915153951490539517d0d0531360721b604482015290519081900360640190fd5b6000805460ff19169055611103338585612bd9565b60019150506000805460ff1916600117905592915050565b7ffc77c2b9d30fe91687fd39abb7d16fcdfe1472d065740051ab8b13e4bf4a617f81565b600a5460ff1681565b60085481565b336000908152600e602090815260408083206001600160a01b0386168452909152812054819081906111809085613192565b9092509050600082600481111561119357fe5b146111cf5760405162461bcd60e51b81526004018080602001828103825260258152602001806138f16025913960400191505060405180910390fd5b6111da338683612aed565b506001949350505050565b6000805460ff16611232576040805162461bcd60e51b815260206004820152601260248201527111549497d4915153951490539517d0d0531360721b604482015290519081900360640190fd5b6000805460ff191690556005546001600160a01b0316331461129b576040805162461bcd60e51b815260206004820152601760248201527f4552525f4d494e545f4e4f545f415554484f52495a4544000000000000000000604482015290519081900360640190fd5b600082116112e0576040805162461bcd60e51b815260206004820152600d60248201526c4552525f4d494e545f5a45524f60981b604482015290519081900360640190fd5b6112ea83836131b8565b6040805183815290516001600160a01b0385169130916000805160206139c98339815191529181900360200190a35060016000805460ff1916600117905592915050565b604051806040016040528060018152602001603160f81b81525081565b6006546001600160a01b031681565b6001600160a01b03166000908152600f602052604090205490565b6005546001600160a01b031681565b60096020526000908152604090205481565b60035442101590565b600c805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107cd5780601f106107a2576101008083540402835291602001916107cd565b6000805460ff16611447576040805162461bcd60e51b815260206004820152601260248201527111549497d4915153951490539517d0d0531360721b604482015290519081900360640190fd5b6000805460ff191690556005546001600160a01b031633146114b0576040805162461bcd60e51b815260206004820152601760248201527f4552525f4255524e5f4e4f545f415554484f52495a4544000000000000000000604482015290519081900360640190fd5b600082116114f5576040805162461bcd60e51b815260206004820152600d60248201526c4552525f4255524e5f5a45524f60981b604482015290519081900360640190fd5b6114ff8383613306565b60408051838152905130916001600160a01b038616916000805160206139c98339815191529181900360200190a35060016000805460ff1916600117905592915050565b6010818154811061155357600080fd5b6000918252602090912001546001600160a01b0316905081565b336000908152600e602090815260408083206001600160a01b03861684529091528120548190819061159f908561316c565b909250905060008260048111156115b257fe5b146111cf5760405162461bcd60e51b81526004018080602001828103825260268152602001806137e76026913960400191505060405180910390fd5b60006107e2338484612fd8565b60025481565b60115461010090046001600160a01b03163314611655576040805162461bcd60e51b815260206004820152600d60248201526c22a9292fa727aa2fa0a226a4a760991b604482015290519081900360640190fd5b60115460405160009161010090046001600160a01b0316907fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf80908390a360118054610100600160a81b0319169055565b6000805460408051632d3caa7360e21b815230600482015233602482018190529151919261010090046001600160a01b03169163b4f2a9cc91604480820192602092909190829003018186803b1580156116fe57600080fd5b505afa158015611712573d6000803e3d6000fd5b505050506040513d602081101561172857600080fd5b5051611770576040805162461bcd60e51b815260206004820152601260248201527122a9292fab20aaa62a2fa727aa2fa7a822a760711b604482015290519081900360640190fd5b60005460ff166117bc576040805162461bcd60e51b815260206004820152601260248201527111549497d4915153951490539517d0d0531360721b604482015290519081900360640190fd5b6000805460ff191690556117ce6136e0565b6117d6611396565b1561181b576040805162461bcd60e51b815260206004820152601060248201526f11549497d093d39117d350551554915160821b604482015290519081900360640190fd5b60008411611862576040805162461bcd60e51b815260206004820152600f60248201526e4552525f424f52524f575f5a45524f60881b604482015290519081900360640190fd5b60048054604080516381a7bc9760e01b81523093810193909352516001600160a01b03909116916381a7bc97916024808301926020929190829003018186803b1580156118ae57600080fd5b505afa1580156118c2573d6000803e3d6000fd5b505050506040513d60208110156118d857600080fd5b5051611924576040805162461bcd60e51b815260206004820152601660248201527511549497d093d49493d5d7d393d517d0531313d5d15160521b604482015290519081900360640190fd5b611930600d5485613192565b60a083018190528282600481111561194457fe5b600481111561194f57fe5b905250600090508151600481111561196357fe5b146119ad576040805162461bcd60e51b815260206004820152601560248201527422a9292fa127a92927abafa6a0aa242fa2a92927a960591b604482015290519081900360640190fd5b600480546040805163d010b00f60e01b81523093810193909352516001600160a01b039091169163d010b00f916024808301926020929190829003018186803b1580156119f957600080fd5b505afa158015611a0d573d6000803e3d6000fd5b505050506040513d6020811015611a2357600080fd5b50516040820181905260a08201511115611a84576040805162461bcd60e51b815260206004820181905260248201527f4552525f424f52524f575f444542545f4345494c494e475f4f564552464c4f57604482015290519081900360640190fd5b6000546040805163bbd7edc560e01b815230600482015233602482015290516101009092046001600160a01b03169163bbd7edc591604480820192608092909190829003018186803b158015611ad957600080fd5b505afa158015611aed573d6000803e3d6000fd5b505050506040513d6080811015611b0357600080fd5b508051604090910151606083018190526020830191909152611b565760405162461bcd60e51b8152600401808060200182810382526021815260200180613a2d6021913960400191505060405180910390fd5b611b64816020015185613192565b60c0830181905282826004811115611b7857fe5b6004811115611b8357fe5b9052506000905081516004811115611b9757fe5b14611be1576040805162461bcd60e51b815260206004820152601560248201527422a9292fa127a92927abafa6a0aa242fa2a92927a960591b604482015290519081900360640190fd5b600054606082015160c08301516040805163d8e51dfb60e01b815230600482015233602482015260448101939093526064830191909152516101009092046001600160a01b03169163d8e51dfb91608480820192602092909190829003018186803b158015611c4f57600080fd5b505afa158015611c63573d6000803e3d6000fd5b505050506040513d6020811015611c7957600080fd5b50516080820152600480546040805163351da44160e21b81523093810193909352516001600160a01b039091169163d4769104916024808301926020929190829003018186803b158015611ccc57600080fd5b505afa158015611ce0573d6000803e3d6000fd5b505050506040513d6020811015611cf657600080fd5b505160e0820181905260808201511015611d415760405162461bcd60e51b81526004018080602001828103825260218152602001806137756021913960400191505060405180910390fd5b611d4b33856131b8565b604080518581529051339130916000805160206139c98339815191529181900360200190a36000805460c083015160408051630b9d2cc360e41b81523060048201523360248201526044810192909252516101009092046001600160a01b03169263b9d2cc30926064808401936020939083900390910190829087803b158015611dd457600080fd5b505af1158015611de8573d6000803e3d6000fd5b505050506040513d6020811015611dfe57600080fd5b5051611e51576040805162461bcd60e51b815260206004820152601e60248201527f4552525f424f52524f575f43414c4c5f5345545f5641554c545f444542540000604482015290519081900360640190fd5b60408051858152905133917fcbc04eca7e9da35cb1393a6135a199ca52e450d5e9251cbd99f7847d33a36750919081900360200190a26001925050506000805460ff19166001179055919050565b600181565b6001600160a01b038716611ee95760405162461bcd60e51b81526004018080602001828103825260238152602001806137526023913960400191505060405180910390fd5b6001600160a01b038616611f2e5760405162461bcd60e51b815260040180806020018281038252602581526020018061395d6025913960400191505060405180910390fd5b42841015611f83576040805162461bcd60e51b815260206004820152601860248201527f4552525f45524332305f5045524d49545f455850495245440000000000000000604482015290519081900360640190fd5b6001600160a01b0380881660008181526009602090815260408083208054600180820190925582517ffc77c2b9d30fe91687fd39abb7d16fcdfe1472d065740051ab8b13e4bf4a617f8186015280840196909652958c166060860152608085018b905260a085019590955260c08085018a90528151808603909101815260e08501825280519083012060085461190160f01b61010087015261010286015261012280860182905282518087039091018152610142860180845281519185019190912090859052610162860180845281905260ff8a166101828701526101a286018990526101c2860188905291519095919491926101e2808401939192601f1981019281900390910190855afa1580156120a0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166120f25760405162461bcd60e51b815260040180806020018281038252602d8152602001806137ba602d913960400191505060405180910390fd5b896001600160a01b0316816001600160a01b0316146121425760405162461bcd60e51b81526004018080602001828103825260228152602001806139e96022913960400191505060405180910390fd5b61214d8a8a8a612aed565b50505050505050505050565b6001546001600160a01b031681565b60035481565b6001600160a01b039182166000908152600e6020908152604080832093909416825291909152205490565b60115461010090046001600160a01b031633146121ed576040805162461bcd60e51b815260206004820152600d60248201526c22a9292fa727aa2fa0a226a4a760991b604482015290519081900360640190fd5b60115460ff1615612236576040805162461bcd60e51b815260206004820152600e60248201526d11549497d253925510531256915160921b604482015290519081900360640190fd5b8060005b818110156123d35783838281811061224e57fe5b905060200201356001600160a01b03166001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b15801561229657600080fd5b505afa1580156122aa573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156122d357600080fd5b8101908080516040519392919084600160201b8211156122f257600080fd5b90830190602082018581111561230757600080fd5b8251600160201b81118282018810171561232057600080fd5b82525081516020918201929091019080838360005b8381101561234d578181015183820152602001612335565b50505050905090810190601f16801561237a5780820380516001836020036101000a031916815260200191505b5060405250505050601084848381811061239057fe5b835460018181018655600095865260209586902090910180546001600160a01b0319166001600160a01b039690930294909401359490941617909155500161223a565b5060118054600160ff1990911617908190556040805160208082528082018690526101009093046001600160a01b0316927fd877543bef27da9036243421e623413c8fdd78d7d183cc93d8f3cddbd657a2ed928792879290918291908201908590850280828437600083820152604051601f909101601f19169092018290039550909350505050a2505050565b60115461010090046001600160a01b031633146124b4576040805162461bcd60e51b815260206004820152600d60248201526c22a9292fa727aa2fa0a226a4a760991b604482015290519081900360640190fd5b6001600160a01b03811661250f576040805162461bcd60e51b815260206004820152601a60248201527f4552525f5345545f41444d494e5f5a45524f5f41444452455353000000000000604482015290519081900360640190fd5b6011546040516001600160a01b0380841692610100900416907fbdd36143ee09de60bdefca70680e0f71189b2ed7acee364b53917ad433fdaf8090600090a3601180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b6000805460408051632d3caa7360e21b81523060048201526001600160a01b0386811660248301529151869361010090049092169163b4f2a9cc91604480820192602092909190829003018186803b1580156125d157600080fd5b505afa1580156125e5573d6000803e3d6000fd5b505050506040513d60208110156125fb57600080fd5b5051612643576040805162461bcd60e51b815260206004820152601260248201527122a9292fab20aaa62a2fa727aa2fa7a822a760711b604482015290519081900360640190fd5b60005460ff1661268f576040805162461bcd60e51b815260206004820152601260248201527111549497d4915153951490539517d0d0531360721b604482015290519081900360640190fd5b6000805460ff191690556126a1613726565b336001600160a01b03861614156126ff576040805162461bcd60e51b815260206004820152601960248201527f4552525f4c49515549444154455f424f52524f575f53454c4600000000000000604482015290519081900360640190fd5b60008411612754576040805162461bcd60e51b815260206004820152601960248201527f4552525f4c49515549444154455f424f52524f575f5a45524f00000000000000604482015290519081900360640190fd5b6004805460408051632ec8fffb60e21b81523093810193909352516001600160a01b039091169163bb23ffec916024808301926020929190829003018186803b1580156127a057600080fd5b505afa1580156127b4573d6000803e3d6000fd5b505050506040513d60208110156127ca57600080fd5b505161281d576040805162461bcd60e51b815260206004820181905260248201527f4552525f4c49515549444154455f424f52524f575f4e4f545f414c4c4f574544604482015290519081900360640190fd5b612825611396565b6129085760005460408051639ee91d1f60e01b81523060048201526001600160a01b038881166024830152915161010090930490911691639ee91d1f91604480820192602092909190829003018186803b15801561288257600080fd5b505afa158015612896573d6000803e3d6000fd5b505050506040513d60208110156128ac57600080fd5b5051151560608201819052612908576040805162461bcd60e51b815260206004820152601a60248201527f4552525f4143434f554e545f4e4f545f554e4445525741544552000000000000604482015290519081900360640190fd5b612913338686612bd9565b600080546040805163464b048560e01b81523060048201526024810188905290516101009092046001600160a01b03169163464b048591604480820192602092909190829003018186803b15801561296a57600080fd5b505afa15801561297e573d6000803e3d6000fd5b505050506040513d602081101561299457600080fd5b50516000805460408051630e496ef360e01b81523060048201523360248201526001600160a01b038b811660448301526064820186905291519495506101009092041692630e496ef392608480840193602093929083900390910190829087803b158015612a0157600080fd5b505af1158015612a15573d6000803e3d6000fd5b505050506040513d6020811015612a2b57600080fd5b5051612a685760405162461bcd60e51b815260040180806020018281038252602b8152602001806138a1602b913960400191505060405180910390fd5b604080518681526020810183905281516001600160a01b0389169233927f08b197b6ae66d18ee6fa20a826a84579a925b9e646a3bf19e96f59ed568c2688929081900390910190a3600193505050506000805460ff1916600117905592915050565b6004546001600160a01b031681565b60115461010090046001600160a01b031681565b6001600160a01b038316612b325760405162461bcd60e51b8152600401808060200182810382526023815260200180613a796023913960400191505060405180910390fd5b6001600160a01b038216612b775760405162461bcd60e51b815260040180806020018281038252602181526020018061382e6021913960400191505060405180910390fd5b6001600160a01b038084166000818152600e6020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60008111612c26576040805162461bcd60e51b81526020600482015260156024820152744552525f52455041595f424f52524f575f5a45524f60581b604482015290519081900360640190fd5b600480546040805163e60f077360e01b81523093810193909352516001600160a01b039091169163e60f0773916024808301926020929190829003018186803b158015612c7257600080fd5b505afa158015612c86573d6000803e3d6000fd5b505050506040513d6020811015612c9c57600080fd5b5051612cef576040805162461bcd60e51b815260206004820152601c60248201527f4552525f52455041595f424f52524f575f4e4f545f414c4c4f57454400000000604482015290519081900360640190fd5b6000805460408051638a0695fd60e01b81523060048201526001600160a01b038681166024830152915161010090930490911691638a0695fd91604480820192602092909190829003018186803b158015612d4957600080fd5b505afa158015612d5d573d6000803e3d6000fd5b505050506040513d6020811015612d7357600080fd5b5051905081811015612db65760405162461bcd60e51b815260040180806020018281038252602281526020018061393b6022913960400191505060405180910390fd5b81612dc08561135a565b1015612dfd5760405162461bcd60e51b81526004018080602001828103825260258152602001806139166025913960400191505060405180910390fd5b612e078483613306565b60408051838152905130916001600160a01b038716916000805160206139c98339815191529181900360200190a3600080612e42838561316c565b90925090506000826004811115612e5557fe5b14612e5c57fe5b6000805460408051630b9d2cc360e41b81523060048201526001600160a01b0389811660248301526044820186905291516101009093049091169263b9d2cc30926064808401936020939083900390910190829087803b158015612ebf57600080fd5b505af1158015612ed3573d6000803e3d6000fd5b505050506040513d6020811015612ee957600080fd5b5051612f265760405162461bcd60e51b81526004018080602001828103825260248152602001806139826024913960400191505060405180910390fd5b846001600160a01b0316866001600160a01b03167fa9a154237a69922f8860321d1fec1624a5dbe8a8af89a3dd3d7a759f6c8080d88684604051808381526020018281526020019250505060405180910390a3505050505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612fd3908490613454565b505050565b6001600160a01b03831661301d5760405162461bcd60e51b815260040180806020018281038252602481526020018061384f6024913960400191505060405180910390fd5b6001600160a01b0382166130625760405162461bcd60e51b8152600401808060200182810382526022815260200180613a0b6022913960400191505060405180910390fd5b6001600160a01b0383166000908152600f602052604081205481908190613089908561316c565b9093509150600083600481111561309c57fe5b146130d85760405162461bcd60e51b815260040180806020018281038252602b815260200180613a4e602b913960400191505060405180910390fd5b6001600160a01b038087166000908152600f6020526040808220859055918716815220546131069085613192565b9093509050600083600481111561311957fe5b1461312057fe5b6001600160a01b038086166000818152600f60209081526040918290208590558151888152915192938a16926000805160206139c98339815191529281900390910190a3505050505050565b60008083831161318357506000905081830361318b565b506003905060005b9250929050565b6000808383018481106131aa5760009250905061318b565b60026000925092505061318b565b6001600160a01b0382166000908152600f6020526040812054819081906131df9085613192565b909350915060008360048111156131f257fe5b14613244576040805162461bcd60e51b815260206004820152601f60248201527f4552525f45524332305f4d494e545f42414c414e43455f4f564552464c4f5700604482015290519081900360640190fd5b6001600160a01b0385166000908152600f60205260409020829055600d5461326c9085613192565b9093509050600083600481111561327f57fe5b146132bb5760405162461bcd60e51b81526004018080602001828103825260248152602001806137966024913960400191505060405180910390fd5b600d8190556040805185815290516001600160a01b038716917f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885919081900360200190a25050505050565b6001600160a01b0382166000908152600f60205260408120548190819061332d908561316c565b9093509150600083600481111561334057fe5b14613392576040805162461bcd60e51b815260206004820181905260248201527f4552525f45524332305f4255524e5f42414c414e43455f554e444552464c4f57604482015290519081900360640190fd5b6001600160a01b0385166000908152600f60205260409020829055600d546133ba908561316c565b909350905060008360048111156133cd57fe5b146134095760405162461bcd60e51b81526004018080602001828103825260258152602001806138cc6025913960400191505060405180910390fd5b600d8190556040805185815290516001600160a01b038716917fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5919081900360200190a25050505050565b600061349683836040518060400160405280601d81526020017f4552525f534146455f45524332305f4c4f575f4c4556454c5f43414c4c000000815250613508565b805190915015612fd3578080602001905160208110156134b557600080fd5b5051612fd3576040805162461bcd60e51b815260206004820152601e60248201527f4552525f534146455f45524332305f45524332305f4f5045524154494f4e0000604482015290519081900360640190fd5b606061351c846001600160a01b03166136a4565b6135575760405162461bcd60e51b81526004018080602001828103825260238152602001806139a66023913960400191505060405180910390fd5b600080856001600160a01b0316856040518082805190602001908083835b602083106135945780518252601f199092019160209182019101613575565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146135f6576040519150601f19603f3d011682016040523d82523d6000602084013e6135fb565b606091505b5091509150811561360f579150610fce9050565b80511561361f5780518082602001fd5b8360405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613669578181015183820152602001613651565b50505050905090810190601f1680156136965780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906136d857508115155b949350505050565b6040805161010081019091528060008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604080516080810190915280600081526020016000815260200160008152602001600015158152509056fe4552525f45524332305f5045524d49545f4f574e45525f5a45524f5f414444524553534552525f42454c4f575f434f4c4c41544552414c495a4154494f4e5f524154494f4552525f45524332305f4d494e545f544f54414c5f535550504c595f4f564552464c4f574552525f45524332305f5045524d49545f5245434f56455245445f4f574e45525f5a45524f5f414444524553534552525f45524332305f44454352454153455f414c4c4f57414e43455f554e444552464c4f574552525f5245434f5645525f4e4f4e5f5245434f56455241424c455f544f4b454e4552525f45524332305f415050524f56455f544f5f5a45524f5f414444524553534552525f45524332305f5452414e534645525f46524f4d5f5a45524f5f414444524553534552525f45524332305f5452414e534645525f46524f4d5f494e53554646494349454e545f414c4c4f57414e43454552525f4c49515549444154455f424f52524f575f43414c4c5f434c555443485f434f4c4c41544552414c4552525f45524332305f4255524e5f544f54414c5f535550504c595f554e444552464c4f574552525f45524332305f494e4352454153455f414c4c4f57414e43455f4f564552464c4f574552525f52455041595f424f52524f575f494e53554646494349454e545f42414c414e43454552525f52455041595f424f52524f575f494e53554646494349454e545f444542544552525f45524332305f5045524d49545f5350454e4445525f5a45524f5f414444524553534552525f52455041595f424f52524f575f43414c4c5f5345545f5641554c545f444542544552525f534146455f45524332305f43414c4c5f544f5f4e4f4e5f434f4e5452414354ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4552525f45524332305f5045524d49545f494e56414c49445f5349474e41545552454552525f45524332305f5452414e534645525f544f5f5a45524f5f414444524553534552525f424f52524f575f4c4f434b45445f434f4c4c41544552414c5f5a45524f4552525f45524332305f5452414e534645525f53454e4445525f42414c414e43455f554e444552464c4f574552525f45524332305f415050524f56455f46524f4d5f5a45524f5f41444452455353a26469706673582212208cee194c7873c76d0f278e0c8b44232bda5b534513841a90b49f26680b23561664736f6c63430007060033
Deployed Bytecode Sourcemap
515:15959:23:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;416:18:18;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3133:173:10;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;3133:173:10;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;12888:206:23;;;;;;;;;;;;;;;;-1:-1:-1;12888:206:23;;:::i;652:26:18:-;;;:::i;:::-;;;;;;;;;;;;;;;;1357:40:25;;;:::i;2117:1196:15:-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;2117:1196:15;;;;;;;;:::i;:::-;;14360:473:23;;;;;;;;;;;;;;;;-1:-1:-1;14360:473:23;-1:-1:-1;;;;;14360:473:23;;:::i;408:41:25:-;;;:::i;:::-;;;;-1:-1:-1;;;;;408:41:25;;;;;;;;;;;;;;6316:522:10;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;6316:522:10;;;;;;;;;;;;;;;;;:::i;13677:270:23:-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;13677:270:23;;;;;;;;:::i;444:108:14:-;;;:::i;326:21:18:-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;277:31:14;;;:::i;4627:418:10:-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;4627:418:10;;;;;;;;:::i;11680:574:23:-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;11680:574:23;;;;;;;;:::i;736:36:14:-;;;:::i;1213:32:25:-;;;:::i;2219:124:10:-;;;;;;;;;;;;;;;;-1:-1:-1;2219:124:10;-1:-1:-1;;;;;2219:124:10;;:::i;1073:45:25:-;;;:::i;618:41:14:-;;;;;;;;;;;;;;;;-1:-1:-1;618:41:14;-1:-1:-1;;;;;618:41:14;;:::i;3754:114:23:-;;;:::i;551:20:18:-;;;:::i;7866:540:23:-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;7866:540:23;;;;;;;;:::i;227:44:17:-;;;;;;;;;;;;;;;;-1:-1:-1;227:44:17;;:::i;3809:429:10:-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;3809:429:10;;;;;;;;:::i;5419:179::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;5419:179:10;;;;;;;;:::i;687:40:25:-;;;:::i;1615:150:1:-;;;:::i;4975:2370:23:-;;;;;;;;;;;;;;;;-1:-1:-1;4975:2370:23;;:::i;1494:37:25:-;;;:::i;1868:1054:12:-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;1868:1054:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;543:32:25:-;;;:::i;820:29::-;;;:::i;1983:150:10:-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;1983:150:10;;;;;;;;;;:::i;934:625:15:-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;934:625:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;934:625:15;;;;;;;;;;-1:-1:-1;934:625:15;;-1:-1:-1;934:625:15;-1:-1:-1;934:625:15;:::i;1969:230:1:-;;;;;;;;;;;;;;;;-1:-1:-1;1969:230:1;-1:-1:-1;;;;;1969:230:1;;:::i;9512:1622:23:-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;9512:1622:23;;;;;;;;:::i;940:37:25:-;;;:::i;182:20:3:-;;;:::i;416:18:18:-;;;;;;;;;;;;;;;-1:-1:-1;;416:18:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;3133:173:10:-;3218:4;3234:44;3250:10;3262:7;3271:6;3234:15;:44::i;:::-;-1:-1:-1;3295:4:10;3133:173;;;;:::o;12888:206:23:-;12994:4;872:12;;:39;;;-1:-1:-1;;;872:39:23;;897:4;872:39;;;;12960:10;872:39;;;;;;;;12960:10;;872:12;;;-1:-1:-1;;;;;872:12:23;;:24;;:39;;;;;;;;;;;;;;;:12;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;872:39:23;864:70;;;;;-1:-1:-1;;;864:70:23;;;;;;;;;;;;-1:-1:-1;;;864:70:23;;;;;;;;;;;;;;;1817:10:29::1;::::0;::::1;;1809:41;;;::::0;;-1:-1:-1;;;1809:41:29;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;1809:41:29;;;;;;;;;;;;;::::1;;1942:5;1929:18:::0;;-1:-1:-1;;1929:18:29::1;::::0;;13010:56:23::2;13030:10;::::0;13054:11;13010:19:::2;:56::i;:::-;13083:4;13076:11;;-1:-1:-1::0;2126:10:29::1;:17:::0;;-1:-1:-1;;2126:17:29::1;2139:4;2126:17;::::0;;12888:206:23;;-1:-1:-1;12888:206:23:o;652:26:18:-;;;;:::o;1357:40:25:-;;;;:::o;2117:1196:15:-;931:5:1;;;;;-1:-1:-1;;;;;931:5:1;940:10;931:19;923:45;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;;;;2247:20:15::1;::::0;::::1;;:28;;:20:::0;:28:::1;2239:59;;;::::0;;-1:-1:-1;;;2239:59:15;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;2239:59:15;;;;;;;;;;;;;::::1;;2332:1;2316:13;:17;2308:46;;;::::0;;-1:-1:-1;;;2308:46:15;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;2308:46:15;;;;;;;;;;;;;::::1;;2365:23;2407:5;-1:-1:-1::0;;;;;2407:12:15::1;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;2407:14:15::1;::::0;::::1;;::::0;::::1;::::0;::::1;;;;;::::0;::::1;;;;;;;;;;;;;;;-1:-1:-1::0;;;2407:14:15::1;;;;;;::::0;::::1;;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;;;;;::::0;::::1;;::::0;;-1:-1:-1;;;2407:14:15;::::1;::::0;;::::1;::::0;-1:-1:-1;2407:14:15::1;;;;;::::0;::::1;;::::0;;-1:-1:-1;2407:14:15;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;::::1;;;;;;;;::::0;;::::1;::::0;;;::::1;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;2391:32;;;;;;2365:58;;2433:14;2450:20;:27;;;;2433:44;;2882:9;2877:300;2901:6;2897:1;:10;2877:300;;;2982:20;3003:1;2982:23;;;;;;;;;::::0;;;::::1;::::0;;;::::1;::::0;-1:-1:-1;;;;;2956:50:15;;::::1;2982:23:::0;::::1;2956:50;::::0;::::1;::::0;:143:::1;;;3065:20;3086:1;3065:23;;;;;;;;;::::0;;;::::1;::::0;;::::1;::::0;:32:::1;::::0;;-1:-1:-1;;;3065:32:15;;;;-1:-1:-1;;;;;3065:23:15;;::::1;::::0;:30:::1;::::0;:32:::1;::::0;;::::1;::::0;;;;;;:23;:32;::::1;;::::0;::::1;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;3065:32:15::1;::::0;::::1;;::::0;::::1;::::0;::::1;;;;;::::0;::::1;;;;;;;;;;;;;;;-1:-1:-1::0;;;3065:32:15::1;;;;;;::::0;::::1;;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;;;;;::::0;::::1;;::::0;;-1:-1:-1;;;3065:32:15;::::1;::::0;;::::1;::::0;-1:-1:-1;3065:32:15::1;;;;;::::0;::::1;;::::0;;-1:-1:-1;3065:32:15;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;::::1;;;;;;;;::::0;;::::1;::::0;;;::::1;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;3049:50;;;;;;3030:15;:69;;2956:143;2931:235;;;;-1:-1:-1::0;;;2931:235:15::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2914:1;2909:6;2877:300;;;-1:-1:-1::0;3233:5:15::1;::::0;3214:40:::1;::::0;-1:-1:-1;;;;;3214:18:15;;::::1;::::0;3233:5:::1;::::0;::::1;;3240:13:::0;3214:18:::1;:40::i;:::-;3278:5;::::0;3270:36:::1;::::0;;-1:-1:-1;;;;;3270:36:15;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;3278:5:::1;::::0;;::::1;;::::0;3270:36:::1;::::0;;;;;;;;;::::1;978:1:1;;2117:1196:15::0;;:::o;14360:473:23:-;931:5:1;;14456:4:23;;931:5:1;;;-1:-1:-1;;;;;931:5:1;940:10;931:19;923:45;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;;;;14544:13:23::1;-1:-1:-1::0;;;;;14544:26:23::1;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;::::0;::::1;;-1:-1:-1::0;14544:28:23;14536:70:::1;;;::::0;;-1:-1:-1;;;14536:70:23;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;14692:10;::::0;;-1:-1:-1;;;;;14712:26:23;;::::1;-1:-1:-1::0;;;;;;14712:26:23;::::1;::::0;::::1;::::0;;;14768:5:::1;::::0;14754:50:::1;::::0;;14692:10;;::::1;14754:50:::0;;;::::1;::::0;::::1;::::0;;;;;;14692:10:::1;14768:5:::0;;::::1;::::0;;::::1;::::0;14754:50:::1;::::0;;;;;;;::::1;-1:-1:-1::0;14822:4:23::1;::::0;14360:473;-1:-1:-1;;14360:473:23:o;408:41:25:-;;;;;;-1:-1:-1;;;;;408:41:25;;:::o;6316:522:10:-;6454:4;6470:43;6487:6;6495:9;6506:6;6470:16;:43::i;:::-;-1:-1:-1;;;;;6614:18:10;;6523:17;6614:18;;;:10;:18;;;;;;;;6633:10;6614:30;;;;;;;;6523:17;;6606:47;;6646:6;6606:7;:47::i;:::-;6580:73;;-1:-1:-1;6580:73:10;-1:-1:-1;6682:18:10;6671:7;:29;;;;;;;;;6663:88;;;;-1:-1:-1;;;6663:88:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6761:49;6777:6;6785:10;6797:12;6761:15;:49::i;:::-;6827:4;6820:11;;;;6316:522;;;;;;:::o;13677:270:23:-;13845:4;872:12;;:39;;;-1:-1:-1;;;872:39:23;;897:4;872:39;;;;-1:-1:-1;;;;;872:39:23;;;;;;;;;;;:12;;;;;;;:24;;:39;;;;;;;;;;;;;;;:12;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;872:39:23;864:70;;;;;-1:-1:-1;;;864:70:23;;;;;;;;;;;;-1:-1:-1;;;864:70:23;;;;;;;;;;;;;;;1817:10:29::1;::::0;::::1;;1809:41;;;::::0;;-1:-1:-1;;;1809:41:29;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;1809:41:29;;;;;;;;;;;;;::::1;;1942:5;1929:18:::0;;-1:-1:-1;;1929:18:29::1;::::0;;13865:54:23::2;13885:10;13897:8:::0;13907:11;13865:19:::2;:54::i;:::-;13936:4;13929:11;;-1:-1:-1::0;2126:10:29::1;:17:::0;;-1:-1:-1;;2126:17:29::1;2139:4;2126:17;::::0;;13677:270:23;;-1:-1:-1;;13677:270:23:o;444:108:14:-;486:66;444:108;:::o;326:21:18:-;;;;;;:::o;277:31:14:-;;;;:::o;4627:418:10:-;4835:10;4717:4;4824:22;;;:10;:22;;;;;;;;-1:-1:-1;;;;;4824:31:10;;;;;;;;;;4717:4;;;;4816:52;;4857:10;4816:7;:52::i;:::-;4790:78;;-1:-1:-1;4790:78:10;-1:-1:-1;4897:18:10;4886:7;:29;;;;;;;;;4878:79;;;;-1:-1:-1;;;4878:79:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4967:50;4983:10;4995:7;5004:12;4967:15;:50::i;:::-;-1:-1:-1;5034:4:10;;4627:418;-1:-1:-1;;;;4627:418:10:o;11680:574:23:-;11775:4;1817:10:29;;;;1809:41;;;;;-1:-1:-1;;;1809:41:29;;;;;;;;;;;;-1:-1:-1;;;1809:41:29;;;;;;;;;;;;;;;1942:5;1929:18;;-1:-1:-1;;1929:18:29;;;11878:14:23::1;::::0;-1:-1:-1;;;;;11878:14:23::1;11856:10;:37;11848:73;;;::::0;;-1:-1:-1;;;11848:73:23;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;11995:1;11982:10;:14;11974:40;;;::::0;;-1:-1:-1;;;11974:40:23;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;11974:40:23;;;;;;;;;;;;;::::1;;12087:37;12100:11;12113:10;12087:12;:37::i;:::-;12177:48;::::0;;;;;;;-1:-1:-1;;;;;12177:48:23;::::1;::::0;12194:4:::1;::::0;-1:-1:-1;;;;;;;;;;;12177:48:23;;;;::::1;::::0;;::::1;-1:-1:-1::0;12243:4:23::1;2126:10:29::0;:17;;-1:-1:-1;;2126:17:29;2139:4;2126:17;;;11680:574:23;;-1:-1:-1;;11680:574:23:o;736:36:14:-;;;;;;;;;;;;;;-1:-1:-1;;;736:36:14;;;;:::o;1213:32:25:-;;;-1:-1:-1;;;;;1213:32:25;;:::o;2219:124:10:-;-1:-1:-1;;;;;2319:17:10;2293:7;2319:17;;;:8;:17;;;;;;;2219:124::o;1073:45:25:-;;;-1:-1:-1;;;;;1073:45:25;;:::o;618:41:14:-;;;;;;;;;;;;;:::o;3754:114:23:-;3847:14;;3828:15;:33;;3754:114;:::o;551:20:18:-;;;;;;;;;;;;;;;-1:-1:-1;;551:20:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7866:540:23;7956:4;1817:10:29;;;;1809:41;;;;;-1:-1:-1;;;1809:41:29;;;;;;;;;;;;-1:-1:-1;;;1809:41:29;;;;;;;;;;;;;;;1942:5;1929:18;;-1:-1:-1;;1929:18:29;;;8059:14:23::1;::::0;-1:-1:-1;;;;;8059:14:23::1;8037:10;:37;8029:73;;;::::0;;-1:-1:-1;;;8029:73:23;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;8176:1;8163:10;:14;8155:40;;;::::0;;-1:-1:-1;;;8155:40:23;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;8155:40:23;;;;;;;;;;;;;::::1;;8249:32;8262:6;8270:10;8249:12;:32::i;:::-;8334:43;::::0;;;;;;;8359:4:::1;::::0;-1:-1:-1;;;;;8334:43:23;::::1;::::0;-1:-1:-1;;;;;;;;;;;8334:43:23;;;;::::1;::::0;;::::1;-1:-1:-1::0;8395:4:23::1;2126:10:29::0;:17;;-1:-1:-1;;2126:17:29;2139:4;2126:17;;;7866:540:23;;-1:-1:-1;;7866:540:23:o;227:44:17:-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;227:44:17;;-1:-1:-1;227:44:17;:::o;3809:429:10:-;4022:10;3904:4;4011:22;;;:10;:22;;;;;;;;-1:-1:-1;;;;;4011:31:10;;;;;;;;;;3904:4;;;;4003:57;;4044:15;4003:7;:57::i;:::-;3977:83;;-1:-1:-1;3977:83:10;-1:-1:-1;4089:18:10;4078:7;:29;;;;;;;;;4070:80;;;;-1:-1:-1;;;4070:80:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5419:179;5507:4;5523:47;5540:10;5552:9;5563:6;5523:16;:47::i;687:40:25:-;;;;:::o;1615:150:1:-;931:5;;;;;-1:-1:-1;;;;;931:5:1;940:10;931:19;923:45;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;;;;1706:5:::1;::::0;1692:35:::1;::::0;1721:4:::1;::::0;1706:5:::1;::::0;::::1;-1:-1:-1::0;;;;;1706:5:1::1;::::0;1692:35:::1;::::0;1721:4;;1692:35:::1;1737:5;:21:::0;;-1:-1:-1;;;;;;1737:21:1::1;::::0;;1615:150::o;4975:2370:23:-;5075:4;872:12;;:39;;;-1:-1:-1;;;872:39:23;;897:4;872:39;;;;5041:10;872:39;;;;;;;;5041:10;;872:12;;;-1:-1:-1;;;;;872:12:23;;:24;;:39;;;;;;;;;;;;;;;:12;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;872:39:23;864:70;;;;;-1:-1:-1;;;864:70:23;;;;;;;;;;;;-1:-1:-1;;;864:70:23;;;;;;;;;;;;;;;1817:10:29::1;::::0;::::1;;1809:41;;;::::0;;-1:-1:-1;;;1809:41:29;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;1809:41:29;;;;;;;;;;;;;::::1;;1942:5;1929:18:::0;;-1:-1:-1;;1929:18:29::1;::::0;;5091:27:23::2;;:::i;:::-;5177:11;:9;:11::i;:::-;:20;5169:49;;;::::0;;-1:-1:-1;;;5169:49:23;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;5169:49:23;;;;;;;;;;;;;::::2;;5294:1;5279:12;:16;5271:44;;;::::0;;-1:-1:-1;;;5271:44:23;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;5271:44:23;;;;;;;;;;;;;::::2;;5407:10;::::0;;:33:::2;::::0;;-1:-1:-1;;;5407:33:23;;5435:4:::2;5407:33:::0;;::::2;::::0;;;;;-1:-1:-1;;;;;5407:10:23;;::::2;::::0;:27:::2;::::0;:33;;;;;::::2;::::0;;;;;;;;:10;:33;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;5407:33:23;5399:68:::2;;;::::0;;-1:-1:-1;;;5399:68:23;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;5399:68:23;;;;;;;;;;;;;::::2;;5561:34;5569:11;;5582:12;5561:7;:34::i;:::-;5529:28;::::0;::::2;5514:81:::0;;;5515:4;5514:81;::::2;::::0;::::2;;;;;;;;;;;;;;::::0;;-1:-1:-1;5629:18:23::2;::::0;-1:-1:-1;5613:12:23;;:34:::2;::::0;::::2;;;;;;;5605:68;;;::::0;;-1:-1:-1;;;5605:68:23;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;5605:68:23;;;;;;;;;;;;;::::2;;5702:10;::::0;;:35:::2;::::0;;-1:-1:-1;;;5702:35:23;;5732:4:::2;5702:35:::0;;::::2;::::0;;;;;-1:-1:-1;;;;;5702:10:23;;::::2;::::0;:29:::2;::::0;:35;;;;;::::2;::::0;;;;;;;;:10;:35;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;5702:35:23;5683:16:::2;::::0;::::2;:54:::0;;;5755:28:::2;::::0;::::2;::::0;:48:::2;;5747:93;;;::::0;;-1:-1:-1;;;5747:93:23;;::::2;;::::0;::::2;::::0;;;;;;;::::2;::::0;;;;;;;;;;;;;::::2;;5968:12;::::0;:39:::2;::::0;;-1:-1:-1;;;5968:39:23;;5990:4:::2;5968:39;::::0;::::2;::::0;5996:10:::2;5968:39:::0;;;;;;:12:::2;::::0;;::::2;-1:-1:-1::0;;;;;5968:12:23::2;::::0;:21:::2;::::0;:39;;;;;::::2;::::0;;;;;;;;;:12;:39;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;5968:39:23;;;;;;;;5941:21;::::2;5927:80:::0;;;5968:39:::2;5928:9:::0;::::2;5927:80:::0;;;;6017:71:::2;;;;-1:-1:-1::0;;;6017:71:23::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6129:32;6137:4;:9;;;6148:12;6129:7;:32::i;:::-;6113:12;::::0;::::2;6098:63:::0;;;6099:4;6098:63;::::2;::::0;::::2;;;;;;;;;;;;;;::::0;;-1:-1:-1;6195:18:23::2;::::0;-1:-1:-1;6179:12:23;;:34:::2;::::0;::::2;;;;;;;6171:68;;;::::0;;-1:-1:-1;;;6171:68:23;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;-1:-1:-1;;;6171:68:23;;;;;;;;;;;;;::::2;;6387:12;::::0;6493:21:::2;::::0;::::2;::::0;6528:12:::2;::::0;::::2;::::0;6387:163:::2;::::0;;-1:-1:-1;;;6387:163:23;;6451:4:::2;6387:163;::::0;::::2;::::0;6469:10:::2;6387:163:::0;;;;;;;;;;;;;;;;;;;:12:::2;::::0;;::::2;-1:-1:-1::0;;;;;6387:12:23::2;::::0;:50:::2;::::0;:163;;;;;::::2;::::0;;;;;;;;;:12;:163;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;6387:163:23;6337:47:::2;::::0;::::2;:213:::0;6607:10:::2;::::0;;:46:::2;::::0;;-1:-1:-1;;;6607:46:23;;6648:4:::2;6607:46:::0;;::::2;::::0;;;;;-1:-1:-1;;;;;6607:10:23;;::::2;::::0;:40:::2;::::0;:46;;;;;6387:163:::2;::::0;6607:46;;;;;;;:10;:46;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;6607:46:23;6560:44:::2;::::0;::::2;:93:::0;;;6684:47:::2;::::0;::::2;::::0;:95:::2;;6663:175;;;;-1:-1:-1::0;;;6663:175:23::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6911:38;6924:10;6936:12;6911;:38::i;:::-;7002:49;::::0;;;;;;;7026:10:::2;::::0;7019:4:::2;::::0;-1:-1:-1;;;;;;;;;;;7002:49:23;;;;::::2;::::0;;::::2;7141:12;::::0;;7185::::2;::::0;::::2;::::0;7141:57:::2;::::0;;-1:-1:-1;;;7141:57:23;;7167:4:::2;7141:57;::::0;::::2;::::0;7173:10:::2;7141:57:::0;;;;;;;;;;;;:12:::2;::::0;;::::2;-1:-1:-1::0;;;;;7141:12:23::2;::::0;:25:::2;::::0;:57;;;;;::::2;::::0;;;;;;;;;;;:12;:57;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;7141:57:23;7133:100:::2;;;::::0;;-1:-1:-1;;;7133:100:23;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;7284:32;::::0;;;;;;;7291:10:::2;::::0;7284:32:::2;::::0;;;;;::::2;::::0;;::::2;7334:4;7327:11;;;-1:-1:-1::0;2126:10:29::1;:17:::0;;-1:-1:-1;;2126:17:29::1;2139:4;2126:17;::::0;;4975:2370:23;;-1:-1:-1;4975:2370:23:o;1494:37:25:-;1527:4;1494:37;:::o;1868:1054:12:-;-1:-1:-1;;;;;2079:22:12;;2071:70;;;;-1:-1:-1;;;2071:70:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2159:24:12;;2151:74;;;;-1:-1:-1;;;2151:74:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2255:15;2243:8;:27;;2235:64;;;;;-1:-1:-1;;;2235:64:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2501:13:12;;;2418:18;2501:13;;;:6;:13;;;;;;;;:15;;;;;;;;;2449:78;;486:66:14;2449:78:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2439:89;;;;;;2594:16;;-1:-1:-1;;;2565:58:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2555:69;;;;;;;;;2659:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2439:89;;2555:69;;2501:15;;2659:26;;;;;2501:13;;-1:-1:-1;;2659:26:12;;;;;;;;;;2501:15;2659:26;;;;;;;;;;;;;;;-1:-1:-1;;2659:26:12;;-1:-1:-1;;2659:26:12;;;-1:-1:-1;;;;;;;2704:31:12;;2696:89;;;;-1:-1:-1;;;2696:89:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2821:5;-1:-1:-1;;;;;2803:23:12;:14;-1:-1:-1;;;;;2803:23:12;;2795:70;;;;-1:-1:-1;;;2795:70:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2876:39;2892:5;2899:7;2908:6;2876:15;:39::i;:::-;1868:1054;;;;;;;;;;:::o;543:32:25:-;;;-1:-1:-1;;;;;543:32:25;;:::o;820:29::-;;;;:::o;1983:150:10:-;-1:-1:-1;;;;;2100:17:10;;;2074:7;2100:17;;;:10;:17;;;;;;;;:26;;;;;;;;;;;;;1983:150::o;934:625:15:-;931:5:1;;;;;-1:-1:-1;;;;;931:5:1;940:10;931:19;923:45;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;;;;1069:20:15::1;::::0;::::1;;:29;1061:56;;;::::0;;-1:-1:-1;;;1061:56:15;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;1061:56:15;;;;;;;;;;;;;::::1;;1230:6:::0;1213:14:::1;1253:133;1277:6;1273:1;:10;1253:133;;;1307:6;;1314:1;1307:9;;;;;;;;;;;;;-1:-1:-1::0;;;;;1307:9:15::1;-1:-1:-1::0;;;;;1307:16:15::1;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;1307:18:15::1;::::0;::::1;;::::0;::::1;::::0;::::1;;;;;::::0;::::1;;;;;;;;;;;;;;;-1:-1:-1::0;;;1307:18:15::1;;;;;;::::0;::::1;;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;;;;;::::0;::::1;;::::0;;-1:-1:-1;;;1307:18:15;::::1;::::0;;::::1;::::0;-1:-1:-1;1307:18:15::1;;;;;::::0;::::1;;::::0;;-1:-1:-1;1307:18:15;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;::::1;;;;;;;;::::0;;::::1;::::0;;;::::1;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;1339:20;1365:6;;1372:1;1365:9;;;;;;;1339:36:::0;;::::1;::::0;;::::1;::::0;;-1:-1:-1;1339:36:15;;;1365:9:::1;1339:36:::0;;;;;;::::1;::::0;;-1:-1:-1;;;;;;1339:36:15::1;-1:-1:-1::0;;;;;1365:9:15;;;::::1;::::0;;;::::1;;::::0;;;::::1;1339:36;::::0;;;-1:-1:-1;1285:6:15::1;1253:133;;;-1:-1:-1::0;1471:20:15::1;:27:::0;;1494:4:::1;-1:-1:-1::0;;1471:27:15;;::::1;;::::0;;;;1514:38:::1;::::0;;::::1;::::0;;;;;::::1;::::0;;;1471:27:::1;1538:5:::0;;::::1;-1:-1:-1::0;;;;;1538:5:15::1;::::0;1514:38:::1;::::0;1545:6;;1514:38;;;;;;;;;;1545:6;;1514:38;::::1;::::0;1545:6;1514:38;::::1;;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;-1:-1:-1::0;;1514:38:15::1;::::0;;::::1;::::0;;::::1;::::0;-1:-1:-1;1514:38:15;;-1:-1:-1;;;;1514:38:15::1;978:1:1;934:625:15::0;;:::o;1969:230:1:-;931:5;;;;;-1:-1:-1;;;;;931:5:1;940:10;931:19;923:45;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;-1:-1:-1;;;923:45:1;;;;;;;;;;;;;;;-1:-1:-1;;;;;2065:25:1;::::1;2057:64;;;::::0;;-1:-1:-1;;;2057:64:1;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;2150:5;::::0;2136:30:::1;::::0;-1:-1:-1;;;;;2136:30:1;;::::1;::::0;2150:5:::1;::::0;::::1;;::::0;2136:30:::1;::::0;;;::::1;2176:5;:16:::0;;-1:-1:-1;;;;;2176:16:1;;::::1;;;-1:-1:-1::0;;;;;;2176:16:1;;::::1;::::0;;;::::1;::::0;;1969:230::o;9512:1622:23:-;9678:4;872:12;;:39;;;-1:-1:-1;;;872:39:23;;897:4;872:39;;;;-1:-1:-1;;;;;872:39:23;;;;;;;;;;;:12;;;;;;;:24;;:39;;;;;;;;;;;;;;;:12;:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;872:39:23;864:70;;;;;-1:-1:-1;;;864:70:23;;;;;;;;;;;;-1:-1:-1;;;864:70:23;;;;;;;;;;;;;;;1817:10:29::1;::::0;::::1;;1809:41;;;::::0;;-1:-1:-1;;;1809:41:29;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;1809:41:29;;;;;;;;;;;;;::::1;;1942:5;1929:18:::0;;-1:-1:-1;;1929:18:29::1;::::0;;9698:37:23::2;;:::i;:::-;9809:10;-1:-1:-1::0;;;;;9809:22:23;::::2;;;9801:60;;;::::0;;-1:-1:-1;;;9801:60:23;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;9936:1;9922:11;:15;9914:53;;;::::0;;-1:-1:-1;;;9914:53:23;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;10059:10;::::0;;:42:::2;::::0;;-1:-1:-1;;;10059:42:23;;10096:4:::2;10059:42:::0;;::::2;::::0;;;;;-1:-1:-1;;;;;10059:10:23;;::::2;::::0;:36:::2;::::0;:42;;;;;::::2;::::0;;;;;;;;:10;:42;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;10059:42:23;10051:87:::2;;;::::0;;-1:-1:-1;;;10051:87:23;;::::2;;::::0;::::2;::::0;;;;;;;::::2;::::0;;;;;;;;;;;;;::::2;;10255:11;:9;:11::i;:::-;10251:292;;10407:12;::::0;:48:::2;::::0;;-1:-1:-1;;;10407:48:23;;10440:4:::2;10407:48;::::0;::::2;::::0;-1:-1:-1;;;;;10407:48:23;;::::2;::::0;;;;;;:12:::2;::::0;;::::2;::::0;;::::2;::::0;:32:::2;::::0;:48;;;;;::::2;::::0;;;;;;;;;:12;:48;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;10407:48:23;10380:75:::2;;:24;::::0;::::2;:75:::0;;;10469:63:::2;;;::::0;;-1:-1:-1;;;10469:63:23;;::::2;;::::0;::::2;::::0;::::2;::::0;;;;::::2;::::0;;;;;;;;;;;;;::::2;;10618:54;10638:10;10650:8;10660:11;10618:19;:54::i;:::-;10734:34;10771:12:::0;;:55:::2;::::0;;-1:-1:-1;;;10771:55:23;;10808:4:::2;10771:55;::::0;::::2;::::0;;;;;;;;;:12:::2;::::0;;::::2;-1:-1:-1::0;;;;;10771:12:23::2;::::0;:36:::2;::::0;:55;;;;;::::2;::::0;;;;;;;;;:12;:55;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;10771:55:23;10857:12:::2;::::0;;:85:::2;::::0;;-1:-1:-1;;;10857:85:23;;10887:4:::2;10857:85;::::0;::::2;::::0;10893:10:::2;10857:85:::0;;;;-1:-1:-1;;;;;10857:85:23;;::::2;::::0;;;;;;;;;;;;10771:55;;-1:-1:-1;10857:12:23::2;::::0;;::::2;;::::0;:29:::2;::::0;:85;;;;;10771:55:::2;::::0;10857:85;;;;;;;;;;;:12;:85;::::2;;::::0;::::2;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;::::0;::::2;;-1:-1:-1::0;10857:85:23;10836:175:::2;;;;-1:-1:-1::0;;;10836:175:23::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11027:78;::::0;;;;;::::2;::::0;::::2;::::0;;;;;-1:-1:-1;;;;;11027:78:23;::::2;::::0;11043:10:::2;::::0;11027:78:::2;::::0;;;;;;;;;::::2;11123:4;11116:11;;;;-1:-1:-1::0;2126:10:29::1;:17:::0;;-1:-1:-1;;2126:17:29::1;2139:4;2126:17;::::0;;9512:1622:23;;-1:-1:-1;;9512:1622:23:o;940:37:25:-;;;-1:-1:-1;;;;;940:37:25;;:::o;182:20:3:-;;;;;;-1:-1:-1;;;;;182:20:3;;:::o;7314:380:10:-;-1:-1:-1;;;;;7452:22:10;;7444:70;;;;-1:-1:-1;;;7444:70:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7532:24:10;;7524:70;;;;-1:-1:-1;;;7524:70:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7605:17:10;;;;;;;:10;:17;;;;;;;;:26;;;;;;;;;;;;;:35;;;7655:32;;;;;;;;;;;;;;;;;7314:380;;;:::o;14991:1481:23:-;15187:1;15173:11;:15;15165:49;;;;;-1:-1:-1;;;15165:49:23;;;;;;;;;;;;-1:-1:-1;;;15165:49:23;;;;;;;;;;;;;;;15306:10;;;:38;;;-1:-1:-1;;;15306:38:23;;15339:4;15306:38;;;;;;;;-1:-1:-1;;;;;15306:10:23;;;;:32;;:38;;;;;;;;;;;;;;:10;:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15306:38:23;15298:79;;;;;-1:-1:-1;;;15298:79:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;15438:12;15453;;:41;;;-1:-1:-1;;;15453:41:23;;15479:4;15453:41;;;;-1:-1:-1;;;;;15453:41:23;;;;;;;;;:12;;;;;;;;:25;;:41;;;;;;;;;;;;;;;:12;:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15453:41:23;;-1:-1:-1;15512:19:23;;;;15504:66;;;;-1:-1:-1;;;15504:66:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15662:11;15642:16;15652:5;15642:9;:16::i;:::-;:31;;15634:81;;;;-1:-1:-1;;;15634:81:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15768:32;15781:5;15788:11;15768:12;:32::i;:::-;15853:43;;;;;;;;15877:4;;-1:-1:-1;;;;;15853:43:23;;;-1:-1:-1;;;;;;;;;;;15853:43:23;;;;;;;;15961:17;15988:15;16034:26;16042:4;16048:11;16034:7;:26::i;:::-;16013:47;;-1:-1:-1;16013:47:23;-1:-1:-1;16163:18:23;16152:7;:29;;;;;;;;;16145:37;;;;16263:12;;;:50;;;-1:-1:-1;;;16263:50:23;;16289:4;16263:50;;;;-1:-1:-1;;;;;16263:50:23;;;;;;;;;;;;;;;:12;;;;;;;;:25;;:50;;;;;;;;;;;;;;;;;:12;:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16263:50:23;16255:99;;;;-1:-1:-1;;;16255:99:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16434:8;-1:-1:-1;;;;;16415:50:23;16427:5;-1:-1:-1;;;;;16415:50:23;;16444:11;16457:7;16415:50;;;;;;;;;;;;;;;;;;;;;;;;14991:1481;;;;;;:::o;857:214:30:-;1004:59;;;-1:-1:-1;;;;;1004:59:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1004:59:30;-1:-1:-1;;;1004:59:30;;;978:86;;997:5;;978:18;:86::i;:::-;857:214;;;:::o;10212:838:10:-;-1:-1:-1;;;;;10354:23:10;;10346:72;;;;-1:-1:-1;;;10346:72:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10436:26:10;;10428:73;;;;-1:-1:-1;;;10428:73:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10649:16:10;;10512:17;10649:16;;;:8;:16;;;;;;10512:17;;;;10641:33;;10667:6;10641:7;:33::i;:::-;10611:63;;-1:-1:-1;10611:63:10;-1:-1:-1;10703:18:10;10692:7;:29;;;;;;;;;10684:85;;;;-1:-1:-1;;;10684:85:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;10779:16:10;;;;;;;:8;:16;;;;;;:35;;;10866:19;;;;;;;10858:36;;10887:6;10858:7;:36::i;:::-;10825:69;;-1:-1:-1;10825:69:10;-1:-1:-1;10922:18:10;10911:7;:29;;;;;;;;;10904:37;;;;-1:-1:-1;;;;;10951:19:10;;;;;;;:8;:19;;;;;;;;;:41;;;11008:35;;;;;;;10951:19;;11008:35;;;-1:-1:-1;;;;;;;;;;;11008:35:10;;;;;;;;;10212:838;;;;;;:::o;2701:239:7:-;2763:9;2774:7;2802:1;2797;:6;2793:141;;-1:-1:-1;2827:18:7;;-1:-1:-1;2847:5:7;;;2819:34;;2793:141;-1:-1:-1;2892:27:7;;-1:-1:-1;2921:1:7;2793:141;2701:239;;;;;:::o;587:262::-;649:9;;691:5;;;711:6;;;707:136;;741:18;;-1:-1:-1;761:1:7;-1:-1:-1;733:30:7;;707:136;802:26;830:1;794:38;;;;;;;9012:718:10;-1:-1:-1;;;;;9268:21:10;;9094:17;9268:21;;;:8;:21;;;;;;9094:17;;;;9260:42;;9291:10;9260:7;:42::i;:::-;9225:77;;-1:-1:-1;9225:77:10;-1:-1:-1;9331:18:10;9320:7;:29;;;;;;;;;9312:73;;;;;-1:-1:-1;;;9312:73:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;9395:21:10;;;;;;:8;:21;;;;;:45;;;9528:11;;9520:32;;9541:10;9520:7;:32::i;:::-;9492:60;;-1:-1:-1;9492:60:10;-1:-1:-1;9581:18:10;9570:7;:29;;;;;;;;;9562:78;;;;-1:-1:-1;;;9562:78:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9650:11;:28;;;9694:29;;;;;;;;-1:-1:-1;;;;;9694:29:10;;;;;;;;;;;;;9012:718;;;;;:::o;8006:683::-;-1:-1:-1;;;;;8247:16:10;;8083:17;8247:16;;;:8;:16;;;;;;8083:17;;;;8239:37;;8265:10;8239:7;:37::i;:::-;8209:67;;-1:-1:-1;8209:67:10;-1:-1:-1;8305:18:10;8294:7;:29;;;;;;;;;8286:74;;;;;-1:-1:-1;;;8286:74:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;8370:16:10;;;;;;:8;:16;;;;;:35;;;8491:11;;8483:32;;8504:10;8483:7;:32::i;:::-;8455:60;;-1:-1:-1;8455:60:10;-1:-1:-1;8544:18:10;8533:7;:29;;;;;;;;;8525:79;;;;-1:-1:-1;;;8525:79:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8614:11;:28;;;8658:24;;;;;;;;-1:-1:-1;;;;;8658:24:10;;;;;;;;;;;;;8006:683;;;;;:::o;1750:702:30:-;2175:23;2201:67;2222:5;2230:4;2201:67;;;;;;;;;;;;;;;;;:12;:67::i;:::-;2282:17;;2175:93;;-1:-1:-1;2282:21:30;2278:168;;2381:10;2370:30;;;;;;;;;;;;;;;-1:-1:-1;2370:30:30;2362:73;;;;;-1:-1:-1;;;2362:73:30;;;;;;;;;;;;;;;;;;;;;;;;;;;2458:961;2590:12;2622:19;:6;-1:-1:-1;;;;;2622:17:30;;:19::i;:::-;2614:67;;;;-1:-1:-1;;;2614:67:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2755:12;2769:23;2796:6;-1:-1:-1;;;;;2796:11:30;2808:4;2796:17;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2796:17:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2754:59;;;;2827:7;2823:590;;;2857:10;-1:-1:-1;2850:17:30;;-1:-1:-1;2850:17:30;2823:590;2971:17;;:21;2967:436;;3236:10;3230:17;3296:15;3283:10;3279:2;3275:19;3268:44;3185:145;3375:12;3368:20;;-1:-1:-1;;;3368:20:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;911:634:0;971:4;1448:20;;1278:66;1495:23;;;;;;:42;;-1:-1:-1;1522:15:0;;;1495:42;1487:51;911:634;-1:-1:-1;;;;911:634:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://504e7960f16a46f68ab102d0a6c00cc3b4e3021515e5b688b79030739924e0a9
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ 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.