My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xcb5e3ba435a1d40f46bd6cced89e910107736574b89d2dbe4295a72bdf556d03 | Authorize | 24571240 | 469 days 8 hrs ago | Tarot: Deployer | IN | Tarot: Supply Vault Strategy V2 | 0 FTM | 0.01050522402 | |
0x558ec1c21a7d82e0930ded29951e4e80068397b668e6131832a680aaea7b7e64 | Authorize | 24571119 | 469 days 8 hrs ago | Tarot: Deployer | IN | Tarot: Supply Vault Strategy V2 | 0 FTM | 0.010630796031 | |
0x2e51de3428ecb9c19284dbcdb94b2ff35c18cc8831d030ab9fb63b3844a6af17 | Authorize Many | 23991123 | 475 days 6 hrs ago | Tarot: Deployer | IN | Tarot: Supply Vault Strategy V2 | 0 FTM | 0.039847501747 | |
0x2f7fe74fd75de4c06ac8ef954e5edcbe2e77aaa47669dfd3c80c6dea0f0beaf0 | 0x60806040 | 23991057 | 475 days 6 hrs ago | Tarot: Deployer | IN | Create: SupplyVaultStrategyV2 | 0 FTM | 0.837597883601 |
[ Download CSV Export ]
Latest 1 internal transaction
Parent Txn Hash | Block | From | To | Value | |||
---|---|---|---|---|---|---|---|
0x2f7fe74fd75de4c06ac8ef954e5edcbe2e77aaa47669dfd3c80c6dea0f0beaf0 | 23991057 | 475 days 6 hrs ago | Tarot: Deployer | Contract Creation | 0 FTM |
[ Download CSV Export ]
Contract Name:
SupplyVaultStrategyV2
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.6.12; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "./libraries/StringHelpers.sol"; import "./libraries/MathHelpers.sol"; import "./libraries/BorrowableHelpers02.sol"; import "./interfaces/ISupplyVaultStrategy.sol"; import "./interfaces/IBorrowable.sol"; import "./interfaces/ISupplyVault.sol"; import "./interfaces/IFactory.sol"; contract SupplyVaultStrategyV2 is ISupplyVaultStrategy, Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; using BorrowableHelpers for IBorrowable; using BorrowableDetailHelpers for BorrowableDetail; struct BorrowableOption { IBorrowable borrowable; uint256 underlyingAmount; uint256 borrowableAmount; uint256 minLoss; uint256 maxGain; } mapping(ISupplyVault => bool) private isAuthorized; function _authorize(ISupplyVault supplyVault) private { require(!isAuthorized[supplyVault], "SupplyVaultStrategyV2: ALREADY_AUTHORIZED"); isAuthorized[supplyVault] = true; } function authorize(ISupplyVault supplyVault) external onlyOwner { _authorize(supplyVault); } function authorizeMany(ISupplyVault[] calldata supplyVaultList) external onlyOwner { for (uint256 i = 0; i < supplyVaultList.length; i++) { _authorize(supplyVaultList[i]); } } modifier onlyAuthorized() { require(isAuthorized[ISupplyVault(msg.sender)], "SupplyVaultStrategyV2: NOT_AUTHORIZED"); _; } IFactory constant TAROT_FACTORY = IFactory(0x35C052bBf8338b06351782A565aa9AaD173432eA); function getBorrowable(address _address) external view override onlyAuthorized returns (IBorrowable) { ISupplyVault supplyVault = ISupplyVault(msg.sender); address underlying = address(supplyVault.underlying()); // Treating _address as a UniswapV2Pair, try to get the lending pool from the known factory adress (bool initialized, , , address borrowable0, address borrowable1) = TAROT_FACTORY.getLendingPool(_address); if (initialized) { if (IBorrowable(borrowable0).underlying() == underlying) { return IBorrowable(borrowable0); } if (IBorrowable(borrowable1).underlying() == underlying) { return IBorrowable(borrowable1); } } require(false, "SupplyVaultStrategyV2: INVALID_BORROWABLE"); } function getSupplyRate() external override onlyAuthorized returns (uint256 supplyRate_) { ISupplyVault supplyVault = ISupplyVault(msg.sender); IERC20 underlying = supplyVault.underlying(); uint256 totalUnderlying = underlying.balanceOf(address(supplyVault)); uint256 weightedSupplyRate = 0; // Underlying has a supply rate of zero uint256 numBorrowables = supplyVault.getBorrowablesLength(); for (uint256 i = 0; i < numBorrowables; i++) { IBorrowable borrowable = supplyVault.borrowables(i); uint256 borrowableUnderlyingBalance = borrowable.underlyingBalanceOf(address(supplyVault)); if (borrowableUnderlyingBalance > 0) { (uint256 borrowableSupplyRate, , ) = borrowable.getCurrentSupplyRate(); weightedSupplyRate = weightedSupplyRate.add(borrowableUnderlyingBalance.mul(borrowableSupplyRate)); totalUnderlying = totalUnderlying.add(borrowableUnderlyingBalance); } } if (totalUnderlying != 0) { supplyRate_ = weightedSupplyRate.div(totalUnderlying); } } function _allocate(uint256 amount) private { ISupplyVault supplyVault = ISupplyVault(msg.sender); if (amount == 0) { // Nothing to allocate return; } BorrowableOption memory best; best.minLoss = type(uint256).max; uint256 numBorrowables = supplyVault.getBorrowablesLength(); require(numBorrowables > 0, "SupplyVaultStrategyV2: NO_BORROWABLES"); for (uint256 i = 0; i < numBorrowables; i++) { IBorrowable borrowable = supplyVault.borrowables(i); if (!supplyVault.getBorrowableEnabled(borrowable)) { continue; } uint256 borrowableMinUnderlying = borrowable.exchangeRate().div(1E18).add(1); if (amount < borrowableMinUnderlying) { continue; } BorrowableDetail memory detail = borrowable.getBorrowableDetail(); uint256 underlyingBalance = borrowable.underlyingBalanceOf(address(supplyVault)); (uint256 gain, uint256 loss) = detail.getMyNetInterest(underlyingBalance, amount, 0); if (gain > best.maxGain || (best.maxGain == 0 && loss < best.minLoss)) { best.borrowable = borrowable; best.maxGain = gain; best.minLoss = loss; } } if (address(best.borrowable) != address(0)) { supplyVault.allocateIntoBorrowable(best.borrowable, amount); } } function allocate() public override onlyAuthorized { ISupplyVault supplyVault = ISupplyVault(msg.sender); IERC20 underlying = supplyVault.underlying(); uint256 amount = underlying.balanceOf(address(supplyVault)); _allocate(amount); } /** * Deallocate from the least performing borrowable either: * 1) The amount of that borrowable to generate at least needAmount of underlying * 2) The maximum amount that can be withdrawn from that borrowable at this time */ function _deallocateFromLowestSupplyRate( ISupplyVault supplyVault, uint256 numBorrowables, IERC20 underlying, uint256 needAmount ) private returns (uint256 deallocatedAmount) { BorrowableOption memory best; best.minLoss = type(uint256).max; for (uint256 i = 0; i < numBorrowables; i++) { IBorrowable borrowable = supplyVault.borrowables(i); uint256 withdrawBorrowableAmount; uint256 withdrawBorrowableAmountAsUnderlying; { uint256 vaultBorrowableBalance = borrowable.balanceOf(address(supplyVault)); if (vaultBorrowableBalance == 0) { continue; } uint256 borrowableUnderlyingBalance = underlying.balanceOf(address(borrowable)); uint256 borrowableUnderlyingBalanceAsBorrowable = borrowable.borrowableValueOf( borrowableUnderlyingBalance ); if (borrowableUnderlyingBalanceAsBorrowable == 0) { continue; } uint256 needAmountAsBorrowableIn = borrowable.borrowableValueOf(needAmount).add(1); withdrawBorrowableAmount = MathHelpers.min( needAmountAsBorrowableIn, vaultBorrowableBalance, borrowableUnderlyingBalanceAsBorrowable ); withdrawBorrowableAmountAsUnderlying = borrowable.underlyingValueOf(withdrawBorrowableAmount); } if (withdrawBorrowableAmountAsUnderlying == 0) { continue; } BorrowableDetail memory detail = borrowable.getBorrowableDetail(); uint256 underlyingBalance = borrowable.underlyingBalanceOf(address(supplyVault)); (uint256 gain, uint256 loss) = detail.getMyNetInterest(underlyingBalance, 0, withdrawBorrowableAmountAsUnderlying); uint256 lossPerUnderlying = loss.mul(1e18).div(withdrawBorrowableAmountAsUnderlying); uint256 gainPerUnderlying = gain.mul(1e18).div(withdrawBorrowableAmountAsUnderlying); if (gainPerUnderlying > best.maxGain || (best.maxGain == 0 && lossPerUnderlying < best.minLoss)) { best.borrowable = borrowable; best.minLoss = lossPerUnderlying; best.maxGain = gainPerUnderlying; best.borrowableAmount = withdrawBorrowableAmount; best.underlyingAmount = withdrawBorrowableAmountAsUnderlying; } } require(best.minLoss < type(uint256).max, "SupplyVaultStrategyV2: INSUFFICIENT_CASH"); uint256 beforeBalance = underlying.balanceOf(address(supplyVault)); supplyVault.deallocateFromBorrowable(best.borrowable, best.borrowableAmount); uint256 afterBalance = underlying.balanceOf(address(supplyVault)); require(afterBalance.sub(beforeBalance) == best.underlyingAmount, "Delta must match"); return best.underlyingAmount; } function deallocate(uint256 needAmount) public override onlyAuthorized { require(needAmount > 0, "SupplyVaultStrategyV2: ZERO_AMOUNT"); ISupplyVault supplyVault = ISupplyVault(msg.sender); IERC20 underlying = supplyVault.underlying(); uint256 numBorrowables = supplyVault.getBorrowablesLength(); do { // Withdraw as much as we can from the lowest supply or fail if none is available uint256 withdraw = _deallocateFromLowestSupplyRate(supplyVault, numBorrowables, underlying, needAmount); // If we get here then we made some progress if (withdraw >= needAmount) { // We unwound a bit more than we needed as deallocation had to round up needAmount = 0; } else { // Update the remaining amount that we desire needAmount = needAmount.sub(withdraw); } if (needAmount == 0) { // We have enough so we are done break; } // Keep going and try a different borrowable } while (true); assert(needAmount == 0); } struct ReallocateInfo { IBorrowable deallocFromBorrowable; IBorrowable allocIntoBorrowable; } function getReallocateInfo(bytes calldata _data) private pure returns (ReallocateInfo memory info) { if (_data.length == 0) { // Use default empty addresses } else if (_data.length == 64) { info = abi.decode(_data, (ReallocateInfo)); require(info.deallocFromBorrowable != info.allocIntoBorrowable, "SupplyVaultStrategyV2: SAME_IN_OUT"); } else { require(false, "SupplyVaultStrategyV2: INVALID_DATA"); } } function reallocate(uint256 _underlyingAmount, bytes calldata _data) external override onlyAuthorized { require(_underlyingAmount > 0, "SupplyVaultStrategyV2: ZERO_AMOUNT"); ReallocateInfo memory info = getReallocateInfo(_data); ISupplyVault supplyVault = ISupplyVault(msg.sender); IERC20 underlying = supplyVault.underlying(); uint256 underlyingBalance = underlying.balanceOf(address(supplyVault)); if (underlyingBalance < _underlyingAmount) { uint256 deallocateAmount = _underlyingAmount.sub(underlyingBalance); if (address(info.deallocFromBorrowable) != address(0)) { // Deallocate from this specific borrowable uint256 deallocateBorrowableAmount = info.deallocFromBorrowable.borrowableValueOf(deallocateAmount); supplyVault.deallocateFromBorrowable(info.deallocFromBorrowable, deallocateBorrowableAmount); } else { deallocate(deallocateAmount); } } uint256 allocateAmount = MathHelpers.min(_underlyingAmount, underlying.balanceOf(address(supplyVault))); if (address(info.allocIntoBorrowable) != address(0)) { // Allocate into this specific borrowable supplyVault.allocateIntoBorrowable(info.allocIntoBorrowable, allocateAmount); } else { _allocate(allocateAmount); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers 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 IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @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 must not 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(IERC20 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 = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
pragma solidity 0.6.12; library StringHelpers { function append(string memory a, string memory b) internal pure returns (string memory) { return string(abi.encodePacked(a, b)); } /** * Returns the first string if it is not-empty, otherwise the second. */ function orElse(string memory a, string memory b) internal pure returns (string memory) { if (bytes(a).length > 0) { return a; } return b; } }
pragma solidity 0.6.12; library MathHelpers { function min(uint256 a, uint256 b) internal pure returns (uint256) { if (a < b) { return a; } return b; } function min( uint256 a, uint256 b, uint256 c ) internal pure returns (uint256) { return min(a, min(b, c)); } function max(uint256 a, uint256 b) internal pure returns (uint256) { if (a > b) { return a; } return b; } function max( uint256 a, uint256 b, uint256 c ) internal pure returns (uint256) { return max(a, max(b, c)); } }
pragma solidity 0.6.12; import "@openzeppelin/contracts/math/SafeMath.sol"; import "../interfaces/IBorrowable.sol"; struct BorrowableDetail { uint256 totalBorrows; uint256 totalBalance; uint256 kinkUtilizationRate; uint256 kinkBorrowRate; uint256 kinkMultiplier; uint256 reserveFactor; } library BorrowableHelpers { using SafeMath for uint256; using BorrowableDetailHelpers for BorrowableDetail; function borrowableValueOf(IBorrowable borrowable, uint256 underlyingAmount) internal returns (uint256) { if (underlyingAmount == 0) { return 0; } uint256 exchangeRate = borrowable.exchangeRate(); return underlyingAmount.mul(1e18).div(exchangeRate); } function underlyingValueOf(IBorrowable borrowable, uint256 borrowableAmount) internal returns (uint256) { if (borrowableAmount == 0) { return 0; } uint256 exchangeRate = borrowable.exchangeRate(); return borrowableAmount.mul(exchangeRate).div(1e18); } function underlyingBalanceOf(IBorrowable borrowable, address account) internal returns (uint256) { return underlyingValueOf(borrowable, borrowable.balanceOf(account)); } function myUnderlyingBalance(IBorrowable borrowable) internal returns (uint256) { return underlyingValueOf(borrowable, borrowable.balanceOf(address(this))); } function getBorrowableDetail(IBorrowable borrowable) internal view returns (BorrowableDetail memory detail) { detail.totalBorrows = borrowable.totalBorrows(); detail.totalBalance = borrowable.totalBalance(); detail.kinkUtilizationRate = borrowable.kinkUtilizationRate(); detail.kinkBorrowRate = borrowable.kinkBorrowRate(); detail.kinkMultiplier = borrowable.KINK_MULTIPLIER(); detail.reserveFactor = borrowable.reserveFactor(); } function getCurrentSupplyRate(IBorrowable borrowable) internal view returns ( uint256 supplyRate_, uint256 borrowRate_, uint256 utilizationRate_ ) { BorrowableDetail memory detail = getBorrowableDetail(borrowable); return detail.getSupplyRate(); } } library BorrowableDetailHelpers { using SafeMath for uint256; uint256 private constant TEN_TO_18 = 1e18; function getBorrowRate(BorrowableDetail memory detail) internal pure returns (uint256 borrowRate_, uint256 utilizationRate_) { (borrowRate_, utilizationRate_) = getBorrowRate( detail.totalBorrows, detail.totalBalance, detail.kinkUtilizationRate, detail.kinkBorrowRate, detail.kinkMultiplier ); } function getBorrowRate( uint256 totalBorrows, uint256 totalBalance, uint256 kinkUtilizationRate, uint256 kinkBorrowRate, uint256 kinkMultiplier ) internal pure returns (uint256 borrowRate_, uint256 utilizationRate_) { uint256 actualBalance = totalBorrows.add(totalBalance); utilizationRate_ = actualBalance == 0 ? 0 : totalBorrows.mul(TEN_TO_18).div(actualBalance); if (utilizationRate_ < kinkUtilizationRate) { borrowRate_ = kinkBorrowRate.mul(utilizationRate_).div(kinkUtilizationRate); } else { uint256 overUtilization = (utilizationRate_.sub(kinkUtilizationRate)).mul(TEN_TO_18).div( TEN_TO_18.sub(kinkUtilizationRate) ); borrowRate_ = (((kinkMultiplier.sub(1)).mul(overUtilization)).add(TEN_TO_18)).mul(kinkBorrowRate).div( TEN_TO_18 ); } } function getSupplyRate(BorrowableDetail memory detail) internal pure returns ( uint256 supplyRate_, uint256 borrowRate_, uint256 utilizationRate_ ) { return getNextSupplyRate(detail, 0, 0); } function getNextSupplyRate( BorrowableDetail memory detail, uint256 depositAmount, uint256 withdrawAmount ) internal pure returns ( uint256 supplyRate_, uint256 borrowRate_, uint256 utilizationRate_ ) { require(depositAmount == 0 || withdrawAmount == 0, "BH: INVLD_DELTA"); (borrowRate_, utilizationRate_) = getBorrowRate( detail.totalBorrows, detail.totalBalance.add(depositAmount).sub(withdrawAmount), detail.kinkUtilizationRate, detail.kinkBorrowRate, detail.kinkMultiplier ); supplyRate_ = borrowRate_.mul(utilizationRate_).div(TEN_TO_18).mul(TEN_TO_18.sub(detail.reserveFactor)).div( TEN_TO_18 ); } function getInterest( uint256 balance, uint256 supplyRate, uint256 actualBalance ) internal pure returns (uint256) { return TEN_TO_18.mul(balance).mul(supplyRate).div(actualBalance); } function getMyNetInterest( BorrowableDetail memory detail, uint256 myBalance, uint256 depositAmount, uint256 withdrawAmount ) internal pure returns (uint256 gain_, uint256 loss_) { require(depositAmount > 0 != withdrawAmount > 0, "BH: INVLD_DELTA"); (uint256 currentSupplyRate, , ) = getSupplyRate(detail); if (currentSupplyRate == 0) { return (gain_ = 0, loss_ = 0); } (uint256 nextSupplyRate, , ) = getNextSupplyRate(detail, depositAmount, withdrawAmount); uint256 actualBalance = detail.totalBalance.add(detail.totalBorrows); uint256 currentInterest = getInterest(myBalance, currentSupplyRate, actualBalance); uint256 nextInterest = getInterest( myBalance.add(depositAmount).sub(withdrawAmount), nextSupplyRate, actualBalance.add(depositAmount).sub(withdrawAmount) ); if (nextInterest > currentInterest) { gain_ = nextInterest.sub(currentInterest); } else { loss_ = currentInterest.sub(nextInterest); } } }
pragma solidity >=0.5.0; import "./IBorrowable.sol"; import "./ISupplyVault.sol"; interface ISupplyVaultStrategy { function getBorrowable(address _address) external view returns (IBorrowable); function getSupplyRate() external returns (uint256 supplyRate_); function allocate() external; function deallocate(uint256 _underlyingAmount) external; function reallocate(uint256 _underlyingAmount, bytes calldata _data) external; }
pragma solidity >=0.5.0; interface IBorrowable { /*** Tarot ERC20 ***/ event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, address indexed spender, uint256 value ); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint256); function balanceOf(address owner) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transfer(address to, uint256 value) external returns (bool); function transferFrom( address from, address to, uint256 value ) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint256); function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /*** Pool Token ***/ event Mint( address indexed sender, address indexed minter, uint256 mintAmount, uint256 mintTokens ); event Redeem( address indexed sender, address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens ); event Sync(uint256 totalBalance); function underlying() external view returns (address); function factory() external view returns (address); function totalBalance() external view returns (uint256); function MINIMUM_LIQUIDITY() external pure returns (uint256); function exchangeRate() external returns (uint256); function mint(address minter) external returns (uint256 mintTokens); function redeem(address redeemer) external returns (uint256 redeemAmount); function skim(address to) external; function sync() external; function _setFactory() external; /*** Borrowable ***/ event BorrowApproval( address indexed owner, address indexed spender, uint256 value ); event Borrow( address indexed sender, address indexed borrower, address indexed receiver, uint256 borrowAmount, uint256 repayAmount, uint256 accountBorrowsPrior, uint256 accountBorrows, uint256 totalBorrows ); event Liquidate( address indexed sender, address indexed borrower, address indexed liquidator, uint256 seizeTokens, uint256 repayAmount, uint256 accountBorrowsPrior, uint256 accountBorrows, uint256 totalBorrows ); function BORROW_FEE() external pure returns (uint256); function collateral() external view returns (address); function reserveFactor() external view returns (uint256); function exchangeRateLast() external view returns (uint256); function borrowIndex() external view returns (uint256); function totalBorrows() external view returns (uint256); function borrowAllowance(address owner, address spender) external view returns (uint256); function borrowBalance(address borrower) external view returns (uint256); function borrowTracker() external view returns (address); function BORROW_PERMIT_TYPEHASH() external pure returns (bytes32); function borrowApprove(address spender, uint256 value) external returns (bool); function borrowPermit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; function borrow( address borrower, address receiver, uint256 borrowAmount, bytes calldata data ) external; function liquidate(address borrower, address liquidator) external returns (uint256 seizeTokens); function trackBorrow(address borrower) external; /*** Borrowable Interest Rate Model ***/ event AccrueInterest( uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows ); event CalculateKink(uint256 kinkRate); event CalculateBorrowRate(uint256 borrowRate); function KINK_BORROW_RATE_MAX() external pure returns (uint256); function KINK_BORROW_RATE_MIN() external pure returns (uint256); function KINK_MULTIPLIER() external pure returns (uint256); function borrowRate() external view returns (uint256); function kinkBorrowRate() external view returns (uint256); function kinkUtilizationRate() external view returns (uint256); function adjustSpeed() external view returns (uint256); function rateUpdateTimestamp() external view returns (uint32); function accrualTimestamp() external view returns (uint32); function accrueInterest() external; /*** Borrowable Setter ***/ event NewReserveFactor(uint256 newReserveFactor); event NewKinkUtilizationRate(uint256 newKinkUtilizationRate); event NewAdjustSpeed(uint256 newAdjustSpeed); event NewBorrowTracker(address newBorrowTracker); function RESERVE_FACTOR_MAX() external pure returns (uint256); function KINK_UR_MIN() external pure returns (uint256); function KINK_UR_MAX() external pure returns (uint256); function ADJUST_SPEED_MIN() external pure returns (uint256); function ADJUST_SPEED_MAX() external pure returns (uint256); function _initialize( string calldata _name, string calldata _symbol, address _underlying, address _collateral ) external; function _setReserveFactor(uint256 newReserveFactor) external; function _setKinkUtilizationRate(uint256 newKinkUtilizationRate) external; function _setAdjustSpeed(uint256 newAdjustSpeed) external; function _setBorrowTracker(address newBorrowTracker) external; }
pragma solidity >=0.5.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./IBorrowable.sol"; import "./ISupplyVaultStrategy.sol"; interface ISupplyVault { /* Vault */ function enter(uint256 _amount) external returns (uint256 share); function enterWithToken(address _tokenAddress, uint256 _tokenAmount) external returns (uint256 share); function leave(uint256 _share) external returns (uint256 underlyingAmount); function leaveInKind(uint256 _share) external; function applyFee() external; /** Read */ function getBorrowablesLength() external view returns (uint256); function getBorrowableEnabled(IBorrowable borrowable) external view returns (bool); function getBorrowableExists(IBorrowable borrowable) external view returns (bool); function indexOfBorrowable(IBorrowable borrowable) external view returns (uint256); function borrowables(uint256) external view returns (IBorrowable); function underlying() external view returns (IERC20); function strategy() external view returns (ISupplyVaultStrategy); function pendingStrategy() external view returns (ISupplyVaultStrategy); function pendingStrategyNotBefore() external view returns (uint256); function feeBps() external view returns (uint256); function feeTo() external view returns (address); function reallocateManager() external view returns (address); /* Read functions that are non-view due to updating exchange rates */ function underlyingBalanceForAccount(address _account) external returns (uint256 underlyingBalance); function shareValuedAsUnderlying(uint256 _share) external returns (uint256 underlyingAmount_); function underlyingValuedAsShare(uint256 _underlyingAmount) external returns (uint256 share_); function getTotalUnderlying() external returns (uint256 totalUnderlying); function getSupplyRate() external returns (uint256 supplyRate_); /* Only from strategy */ function allocateIntoBorrowable(IBorrowable borrowable, uint256 underlyingAmount) external; function deallocateFromBorrowable(IBorrowable borrowable, uint256 borrowableAmount) external; function reallocate(uint256 _share, bytes calldata _data) external; /* Only owner */ function addBorrowable(address _address) external; function addBorrowables(address[] calldata _addressList) external; function removeBorrowable(IBorrowable borrowable) external; function disableBorrowable(IBorrowable borrowable) external; function enableBorrowable(IBorrowable borrowable) external; function unwindBorrowable(IBorrowable borrowable, uint256 borowableAmount) external; function updatePendingStrategy(ISupplyVaultStrategy _newPendingStrategy, uint256 _notBefore) external; function updateStrategy() external; function updateFeeBps(uint256 _newFeeBps) external; function updateFeeTo(address _newFeeTo) external; function updateReallocateManager(address _newReallocateManager) external; function pause() external; function unpause() external; /* Voting */ function delegates(address delegator) external view returns (address); function delegate(address delegatee) external; function delegateBySig( address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s ) external; function getCurrentVotes(address account) external view returns (uint256); function getPriorVotes(address account, uint blockNumber) external view returns (uint256); /* Events */ event AddBorrowable(address indexed borrowable); event RemoveBorrowable(address indexed borrowable); event EnableBorrowable(address indexed borrowable); event DisableBorrowable(address indexed borrowable); event UpdatePendingStrategy(address indexed strategy, uint256 notBefore); event UpdateStrategy(address indexed strategy); event UpdateFeeBps(uint256 newFeeBps); event UpdateFeeTo(address indexed newFeeTo); event UpdateReallocateManager(address indexed newReallocateManager); event UnwindBorrowable(address indexed borrowable, uint256 underlyingAmount, uint256 borrowableAmount); event Enter( address indexed who, address indexed token, uint256 tokenAmount, uint256 underlyingAmount, uint256 share ); event Leave(address indexed who, uint256 share, uint256 underlyingAmount); event LeaveInKind(address indexed who, uint256 share); event Reallocate(address indexed sender, uint256 share); event AllocateBorrowable(address indexed borrowable, uint256 underlyingAmount, uint256 borrowableAmount); event DeallocateBorrowable(address indexed borrowable, uint256 borrowableAmount, uint256 underlyingAmount); event ApplyFee(address indexed feeTo, uint256 gain, uint256 fee, uint256 feeShare); event UpdateCheckpoint(uint256 checkpointBalance); }
pragma solidity >=0.5.0; interface IFactory { event LendingPoolInitialized(address indexed uniswapV2Pair, address indexed token0, address indexed token1, address collateral, address borrowable0, address borrowable1, uint lendingPoolId); event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin); event NewAdmin(address oldAdmin, address newAdmin); event NewReservesPendingAdmin(address oldReservesPendingAdmin, address newReservesPendingAdmin); event NewReservesAdmin(address oldReservesAdmin, address newReservesAdmin); event NewReservesManager(address oldReservesManager, address newReservesManager); function admin() external view returns (address); function pendingAdmin() external view returns (address); function reservesAdmin() external view returns (address); function reservesPendingAdmin() external view returns (address); function reservesManager() external view returns (address); function getLendingPool(address uniswapV2Pair) external view returns ( bool initialized, uint24 lendingPoolId, address collateral, address borrowable0, address borrowable1 ); function allLendingPools(uint) external view returns (address uniswapV2Pair); function allLendingPoolsLength() external view returns (uint); function bDeployer() external view returns (address); function cDeployer() external view returns (address); function tarotPriceOracle() external view returns (address); function createCollateral(address uniswapV2Pair) external returns (address collateral); function createBorrowable0(address uniswapV2Pair) external returns (address borrowable0); function createBorrowable1(address uniswapV2Pair) external returns (address borrowable1); function initializeLendingPool(address uniswapV2Pair) external; function _setPendingAdmin(address newPendingAdmin) external; function _acceptAdmin() external; function _setReservesPendingAdmin(address newPendingAdmin) external; function _acceptReservesAdmin() external; function _setReservesManager(address newReservesManager) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"allocate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISupplyVault","name":"supplyVault","type":"address"}],"name":"authorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISupplyVault[]","name":"supplyVaultList","type":"address[]"}],"name":"authorizeMany","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"needAmount","type":"uint256"}],"name":"deallocate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"getBorrowable","outputs":[{"internalType":"contract IBorrowable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSupplyRate","outputs":[{"internalType":"uint256","name":"supplyRate_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_underlyingAmount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"reallocate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50600061001b61006a565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061006e565b3390565b6127478061007d6000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c80638da5cb5b116100665780638da5cb5b146101045780639685e71614610119578063abaa99161461012c578063b6a5d7de14610134578063f2fde38b146101475761009e565b80634dc0ed9b146100a35780636f6c441f146100b8578063715018a6146100cb57806384bdc9a8146100d35780638670d9dc146100f1575b600080fd5b6100b66100b13660046120d8565b61015a565b005b6100b66100c6366004612240565b6101e3565b6100b661036e565b6100db6103f7565b6040516100e891906126f3565b60405180910390f35b6100b66100ff366004612270565b6106a3565b61010c6109cc565b6040516100e891906122e7565b61010c6101273660046120a0565b6109db565b6100b6610c70565b6100b66101423660046120a0565b610da2565b6100b66101553660046120a0565b610ded565b610162610ead565b6001600160a01b03166101736109cc565b6001600160a01b0316146101a25760405162461bcd60e51b815260040161019990612676565b60405180910390fd5b60005b818110156101de576101d68383838181106101bc57fe5b90506020020160208101906101d191906120a0565b610eb1565b6001016101a5565b505050565b3360009081526001602052604090205460ff166102125760405162461bcd60e51b8152600401610199906125ad565b600081116102325760405162461bcd60e51b81526004016101999061256b565b60003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561027257600080fd5b505afa158015610286573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102aa91906120bc565b90506000826001600160a01b031663821beaf56040518163ffffffff1660e01b815260040160206040518083038186803b1580156102e757600080fd5b505afa1580156102fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061031f9190612258565b90505b600061033084838588610f11565b9050848110610342576000945061034f565b61034c85826113ee565b94505b8461035a5750610360565b50610322565b831561036857fe5b50505050565b610376610ead565b6001600160a01b03166103876109cc565b6001600160a01b0316146103ad5760405162461bcd60e51b815260040161019990612676565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b3360009081526001602052604081205460ff166104265760405162461bcd60e51b8152600401610199906125ad565b60003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561046657600080fd5b505afa15801561047a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049e91906120bc565b90506000816001600160a01b03166370a08231846040518263ffffffff1660e01b81526004016104ce91906122e7565b60206040518083038186803b1580156104e657600080fd5b505afa1580156104fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051e9190612258565b9050600080846001600160a01b031663821beaf56040518163ffffffff1660e01b815260040160206040518083038186803b15801561055c57600080fd5b505afa158015610570573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105949190612258565b905060005b818110156106875760405163ade37c1360e01b81526000906001600160a01b0388169063ade37c13906105d09085906004016126f3565b60206040518083038186803b1580156105e857600080fd5b505afa1580156105fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061062091906120bc565b905060006106376001600160a01b0383168961141b565b9050801561067d576000610653836001600160a01b03166114a9565b5090915061066d905061066683836114d8565b8790611512565b95506106798783611512565b9650505b5050600101610599565b50821561069b576106988284611537565b95505b505050505090565b3360009081526001602052604090205460ff166106d25760405162461bcd60e51b8152600401610199906125ad565b600083116106f25760405162461bcd60e51b81526004016101999061256b565b6106fa61201b565b6107048383611569565b905060003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b15801561074657600080fd5b505afa15801561075a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077e91906120bc565b90506000816001600160a01b03166370a08231846040518263ffffffff1660e01b81526004016107ae91906122e7565b60206040518083038186803b1580156107c657600080fd5b505afa1580156107da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fe9190612258565b9050868110156108b357600061081488836113ee565b85519091506001600160a01b0316156108a857845160009061083f906001600160a01b0316836115e9565b865160405163f26a584560e01b81529192506001600160a01b0387169163f26a5845916108709185906004016122fb565b600060405180830381600087803b15801561088a57600080fd5b505af115801561089e573d6000803e3d6000fd5b50505050506108b1565b6108b1816101e3565b505b600061093a88846001600160a01b03166370a08231876040518263ffffffff1660e01b81526004016108e591906122e7565b60206040518083038186803b1580156108fd57600080fd5b505afa158015610911573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109359190612258565b61168d565b60208601519091506001600160a01b0316156109b9576020850151604051635a01cecf60e11b81526001600160a01b0386169163b4039d9e91610982919085906004016122fb565b600060405180830381600087803b15801561099c57600080fd5b505af11580156109b0573d6000803e3d6000fd5b505050506109c2565b6109c2816116a4565b5050505050505050565b6000546001600160a01b031690565b3360009081526001602052604081205460ff16610a0a5760405162461bcd60e51b8152600401610199906125ad565b60003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610a4a57600080fd5b505afa158015610a5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8291906120bc565b905060008060007335c052bbf8338b06351782a565aa9aad173432ea6001600160a01b0316630572bf5f886040518263ffffffff1660e01b8152600401610ac991906122e7565b60a06040518083038186803b158015610ae157600080fd5b505afa158015610af5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b199190612167565b94509450505092508215610c5357836001600160a01b0316826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610b6a57600080fd5b505afa158015610b7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba291906120bc565b6001600160a01b03161415610bbd57509350610c6b92505050565b836001600160a01b0316816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610c0057600080fd5b505afa158015610c14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3891906120bc565b6001600160a01b03161415610c53579450610c6b9350505050565b60405162461bcd60e51b8152600401610199906123da565b919050565b3360009081526001602052604090205460ff16610c9f5760405162461bcd60e51b8152600401610199906125ad565b60003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610cdf57600080fd5b505afa158015610cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1791906120bc565b90506000816001600160a01b03166370a08231846040518263ffffffff1660e01b8152600401610d4791906122e7565b60206040518083038186803b158015610d5f57600080fd5b505afa158015610d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d979190612258565b90506101de816116a4565b610daa610ead565b6001600160a01b0316610dbb6109cc565b6001600160a01b031614610de15760405162461bcd60e51b815260040161019990612676565b610dea81610eb1565b50565b610df5610ead565b6001600160a01b0316610e066109cc565b6001600160a01b031614610e2c5760405162461bcd60e51b815260040161019990612676565b6001600160a01b038116610e525760405162461bcd60e51b815260040161019990612314565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b3390565b6001600160a01b03811660009081526001602052604090205460ff1615610eea5760405162461bcd60e51b815260040161019990612391565b6001600160a01b03166000908152600160208190526040909120805460ff19169091179055565b6000610f1b612032565b600019606082015260005b858110156112245760405163ade37c1360e01b81526000906001600160a01b0389169063ade37c1390610f5d9085906004016126f3565b60206040518083038186803b158015610f7557600080fd5b505afa158015610f89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fad91906120bc565b90506000806000836001600160a01b03166370a082318c6040518263ffffffff1660e01b8152600401610fe091906122e7565b60206040518083038186803b158015610ff857600080fd5b505afa15801561100c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110309190612258565b905080611040575050505061121c565b6040516370a0823160e01b81526000906001600160a01b038b16906370a082319061106f9088906004016122e7565b60206040518083038186803b15801561108757600080fd5b505afa15801561109b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110bf9190612258565b905060006110d66001600160a01b038716836115e9565b9050806110e85750505050505061121c565b600061110860016111026001600160a01b038a168e6115e9565b90611512565b9050611115818584611a08565b955061112a6001600160a01b03881687611a18565b94505050505080600014156111415750505061121c565b61114961206a565b61115b846001600160a01b0316611ab4565b905060006111726001600160a01b0386168d61141b565b905060008061118384848388611d99565b909250905060006111a6866111a084670de0b6b3a76400006114d8565b90611537565b905060006111c0876111a086670de0b6b3a76400006114d8565b90508a608001518111806111e4575060808b01511580156111e457508a6060015182105b15611212576001600160a01b0389168b5260608b0182905260808b0181905260408b0188905260208b018790525b5050505050505050505b600101610f26565b5060001981606001511061124a5760405162461bcd60e51b8152600401610199906126ab565b6040516370a0823160e01b81526000906001600160a01b038616906370a0823190611279908a906004016122e7565b60206040518083038186803b15801561129157600080fd5b505afa1580156112a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c99190612258565b8251604080850151905163f26a584560e01b81529293506001600160a01b038a169263f26a5845926112ff9290916004016122fb565b600060405180830381600087803b15801561131957600080fd5b505af115801561132d573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b03881691506370a0823190611360908b906004016122e7565b60206040518083038186803b15801561137857600080fd5b505afa15801561138c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b09190612258565b60208401519091506113c282846113ee565b146113df5760405162461bcd60e51b815260040161019990612483565b50506020015195945050505050565b6000828211156114105760405162461bcd60e51b81526004016101999061244c565b508082035b92915050565b60006114a283846001600160a01b03166370a08231856040518263ffffffff1660e01b815260040161144d91906122e7565b60206040518083038186803b15801561146557600080fd5b505afa158015611479573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061149d9190612258565b611a18565b9392505050565b60008060006114b661206a565b6114bf85611ab4565b90506114ca81611e7f565b935093509350509193909250565b6000826114e757506000611415565b828202828482816114f457fe5b04146114a25760405162461bcd60e51b8152600401610199906125f2565b6000828201838110156114a25760405162461bcd60e51b81526004016101999061235a565b60008082116115585760405162461bcd60e51b8152600401610199906124ad565b81838161156157fe5b049392505050565b61157161201b565b8161157b57611415565b60408214156115d157611590828401846121e6565b905080602001516001600160a01b031681600001516001600160a01b031614156115cc5760405162461bcd60e51b8152600401610199906124e4565b611415565b60405162461bcd60e51b815260040161019990612633565b6000816115f857506000611415565b6000836001600160a01b0316633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561163557600080fd5b505af1158015611649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166d9190612258565b9050611685816111a085670de0b6b3a76400006114d8565b949350505050565b60008183101561169e575081611415565b50919050565b33816116b05750610dea565b6116b8612032565b6000198160600181815250506000826001600160a01b031663821beaf56040518163ffffffff1660e01b815260040160206040518083038186803b1580156116ff57600080fd5b505afa158015611713573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117379190612258565b9050600081116117595760405162461bcd60e51b815260040161019990612526565b60005b8181101561199a5760405163ade37c1360e01b81526000906001600160a01b0386169063ade37c13906117939085906004016126f3565b60206040518083038186803b1580156117ab57600080fd5b505afa1580156117bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e391906120bc565b604051631aca889d60e31b81529091506001600160a01b0386169063d65444e8906118129084906004016122e7565b60206040518083038186803b15801561182a57600080fd5b505afa15801561183e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118629190612147565b61186c5750611992565b60006118f26001611102670de0b6b3a7640000856001600160a01b0316633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118ba57600080fd5b505af11580156118ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a09190612258565b905080871015611903575050611992565b61190b61206a565b61191d836001600160a01b0316611ab4565b905060006119346001600160a01b0385168961141b565b905060008061194584848d84611d99565b91509150886080015182118061196b5750608089015115801561196b5750886060015181105b1561198b576001600160a01b038616895260808901829052606089018190525b5050505050505b60010161175c565b5081516001600160a01b031615610368578151604051635a01cecf60e11b81526001600160a01b0385169163b4039d9e916119da919088906004016122fb565b600060405180830381600087803b1580156119f457600080fd5b505af11580156109c2573d6000803e3d6000fd5b600061168584610935858561168d565b600081611a2757506000611415565b6000836001600160a01b0316633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611a6457600080fd5b505af1158015611a78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9c9190612258565b9050611685670de0b6b3a76400006111a085846114d8565b611abc61206a565b816001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b158015611af557600080fd5b505afa158015611b09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2d9190612258565b816000018181525050816001600160a01b031663ad7a672f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b6f57600080fd5b505afa158015611b83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ba79190612258565b816020018181525050816001600160a01b0316631aebf12f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611be957600080fd5b505afa158015611bfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c219190612258565b816040018181525050816001600160a01b03166391b427456040518163ffffffff1660e01b815260040160206040518083038186803b158015611c6357600080fd5b505afa158015611c77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9b9190612258565b816060018181525050816001600160a01b0316635b2b9d1a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cdd57600080fd5b505afa158015611cf1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d159190612258565b816080018181525050816001600160a01b0316634322b7146040518163ffffffff1660e01b815260040160206040518083038186803b158015611d5757600080fd5b505afa158015611d6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8f9190612258565b60a0820152919050565b6000808315158315151415611dc05760405162461bcd60e51b815260040161019990612423565b6000611dcb87611e7f565b505090508060001415611de5575060009150819050611e76565b6000611df2888787611e9d565b5050885160208a0151919250600091611e0a91611512565b90506000611e19898584611f4d565b90506000611e48611e3489611e2e8d8d611512565b906113ee565b85611e438b611e2e888f611512565b611f4d565b905081811115611e6357611e5c81836113ee565b9650611e70565b611e6d82826113ee565b95505b50505050505b94509492505050565b6000806000611e9084600080611e9d565b9250925092509193909250565b60008080841580611eac575083155b611ec85760405162461bcd60e51b815260040161019990612423565b611eff8660000151611eeb86611e2e898b6020015161151290919063ffffffff16565b886040015189606001518a60800151611f69565b60a08801519193509150611f4290670de0b6b3a7640000906111a090611f269083906113ee565b611f3c670de0b6b3a76400006111a088886114d8565b906114d8565b925093509350939050565b6000611685826111a085611f3c670de0b6b3a7640000896114d8565b60008080611f778888611512565b90508015611f9a57611f95816111a08a670de0b6b3a76400006114d8565b611f9d565b60005b915085821015611fbc57611fb5866111a087856114d8565b9250612010565b6000611fe9611fd3670de0b6b3a7640000896113ee565b6111a0670de0b6b3a7640000611f3c878c6113ee565b905061200c670de0b6b3a76400006111a088611f3c8361110287838d60016113ee565b9350505b509550959350505050565b604080518082019091526000808252602082015290565b6040518060a0016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000602082840312156120b1578081fd5b81356114a2816126fc565b6000602082840312156120cd578081fd5b81516114a2816126fc565b600080602083850312156120ea578081fd5b823567ffffffffffffffff80821115612101578283fd5b818501915085601f830112612114578283fd5b813581811115612122578384fd5b8660208083028501011115612135578384fd5b60209290920196919550909350505050565b600060208284031215612158578081fd5b815180151581146114a2578182fd5b600080600080600060a0868803121561217e578081fd5b8551801515811461218d578182fd5b602087015190955062ffffff811681146121a5578182fd5b60408701519094506121b6816126fc565b60608701519093506121c7816126fc565b60808701519092506121d8816126fc565b809150509295509295909350565b6000604082840312156121f7578081fd5b6040516040810181811067ffffffffffffffff82111715612216578283fd5b6040528235612224816126fc565b81526020830135612234816126fc565b60208201529392505050565b600060208284031215612251578081fd5b5035919050565b600060208284031215612269578081fd5b5051919050565b600080600060408486031215612284578283fd5b83359250602084013567ffffffffffffffff808211156122a2578384fd5b818601915086601f8301126122b5578384fd5b8135818111156122c3578485fd5b8760208285010111156122d4578485fd5b6020830194508093505050509250925092565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526029908201527f537570706c795661756c74537472617465677956323a20414c52454144595f4160408201526815551213d49256915160ba1b606082015260800190565b60208082526029908201527f537570706c795661756c74537472617465677956323a20494e56414c49445f426040820152684f52524f5741424c4560b81b606082015260800190565b6020808252600f908201526e42483a20494e564c445f44454c544160881b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526010908201526f088cad8e8c240daeae6e840dac2e8c6d60831b604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526022908201527f537570706c795661756c74537472617465677956323a2053414d455f494e5f4f604082015261155560f21b606082015260800190565b60208082526025908201527f537570706c795661756c74537472617465677956323a204e4f5f424f52524f5760408201526441424c455360d81b606082015260800190565b60208082526022908201527f537570706c795661756c74537472617465677956323a205a45524f5f414d4f55604082015261139560f21b606082015260800190565b60208082526025908201527f537570706c795661756c74537472617465677956323a204e4f545f415554484f604082015264149256915160da1b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526023908201527f537570706c795661756c74537472617465677956323a20494e56414c49445f4460408201526241544160e81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526028908201527f537570706c795661756c74537472617465677956323a20494e5355464649434960408201526708a9ca8be8682a6960c31b606082015260800190565b90815260200190565b6001600160a01b0381168114610dea57600080fdfea26469706673582212200c4393fbe165fbc4daf266dcffc467be5a5ac55a6f16b3543dc182c59ad4439764736f6c634300060c0033
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Validator ID :
0 FTM
Amount Staked
0
Amount Delegated
0
Staking Total
0
Staking Start Epoch
0
Staking Start Time
0
Proof of Importance
0
Origination Score
0
Validation Score
0
Active
0
Online
0
Downtime
0 s
Address | Amount | claimed Rewards | Created On Epoch | Created On |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.