My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xda3beeb33156ef1ca26d4be6d052a82a29df4ef3bd801ff299175718b33b5c24 | Update Supply Va... | 29131539 | 422 days 4 hrs ago | Tarot: Deployer | IN | Tarot: Supply Vault Strategy V3 | 0 FTM | 0.05091647136 | |
0x39d54c5d84c6dd1f4aa7ac021bc18c48c844c9b3a9e17ca57f972a3f8fef05b6 | Authorize Many | 28959723 | 424 days 12 mins ago | Tarot: Deployer | IN | Tarot: Supply Vault Strategy V3 | 0 FTM | 0.061692937319 | |
0x2e4fa1cb16f71196b4dbdfe0b60704e4d99d14b55c755c04b7f7b3ad8245c4d8 | 0x60806040 | 28959552 | 424 days 15 mins ago | Tarot: Deployer | IN | Create: SupplyVaultStrategyV3 | 0 FTM | 0.95086804888 |
[ Download CSV Export ]
Latest 1 internal transaction
Parent Txn Hash | Block | From | To | Value | |||
---|---|---|---|---|---|---|---|
0x2e4fa1cb16f71196b4dbdfe0b60704e4d99d14b55c755c04b7f7b3ad8245c4d8 | 28959552 | 424 days 15 mins ago | Tarot: Deployer | Contract Creation | 0 FTM |
[ Download CSV Export ]
Contract Name:
SupplyVaultStrategyV3
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 SupplyVaultStrategyV3 is ISupplyVaultStrategy, Ownable { using SafeMath for uint256; using SafeERC20 for IERC20; using BorrowableHelpers for IBorrowable; using BorrowableDetailHelpers for BorrowableDetail; struct SupplyVaultInfo { uint256 additionalDeallocAmount; uint256 minAllocAmount; } mapping(ISupplyVault => SupplyVaultInfo) public supplyVaultInfo; function updateSupplyVaultInfo( ISupplyVault supplyVault, uint256 additionalDeallocAmount, uint256 minAllocAmount ) external onlyOwner { require(isAuthorized[supplyVault], "SupplyVaultStrategyV3: INVALID_VAULT"); supplyVaultInfo[supplyVault].additionalDeallocAmount = additionalDeallocAmount; supplyVaultInfo[supplyVault].minAllocAmount = minAllocAmount; } struct BorrowableOption { IBorrowable borrowable; uint256 underlyingAmount; uint256 borrowableAmount; uint256 minLoss; uint256 maxGain; } mapping(ISupplyVault => bool) public isAuthorized; function _authorize(ISupplyVault supplyVault) private { require(!isAuthorized[supplyVault], "SupplyVaultStrategyV3: 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)], "SupplyVaultStrategyV3: 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, "SupplyVaultStrategyV3: 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, "SupplyVaultStrategyV3: NO_BORROWABLES"); for (uint256 i = 0; i < numBorrowables; i++) { IBorrowable borrowable = supplyVault.borrowables(i); if (!supplyVault.getBorrowableEnabled(borrowable)) { continue; } uint256 exchangeRate = borrowable.exchangeRate(); uint256 borrowableMinUnderlying = exchangeRate.div(1E18).add(1); if (amount < borrowableMinUnderlying) { continue; } BorrowableDetail memory detail = borrowable.getBorrowableDetail(); uint256 underlyingBalance = borrowable.balanceOf(address(supplyVault)).mul(exchangeRate).div(1E18); (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)); if (amount < supplyVaultInfo[supplyVault].minAllocAmount) { return; } _allocate(amount); } struct DeallocOption { uint256 withdrawBorrowableAmount; uint256 withdrawBorrowableAmountAsUnderlying; uint256 exchangeRate; uint256 vaultBorrowableBalance; } /** * 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); DeallocOption memory option; option.exchangeRate = borrowable.exchangeRate(); { option.vaultBorrowableBalance = borrowable.balanceOf(address(supplyVault)); if (option.vaultBorrowableBalance == 0) { continue; } uint256 borrowableUnderlyingBalance = underlying.balanceOf(address(borrowable)); uint256 borrowableUnderlyingBalanceAsBorrowable = borrowableUnderlyingBalance.mul(1E18).div( option.exchangeRate ); if (borrowableUnderlyingBalanceAsBorrowable == 0) { continue; } uint256 needAmountAsBorrowableIn = needAmount.mul(1E18).div(option.exchangeRate).add(1); option.withdrawBorrowableAmount = MathHelpers.min( needAmountAsBorrowableIn, option.vaultBorrowableBalance, borrowableUnderlyingBalanceAsBorrowable ); option.withdrawBorrowableAmountAsUnderlying = option .withdrawBorrowableAmount .mul(option.exchangeRate) .div(1E18); } if (option.withdrawBorrowableAmountAsUnderlying == 0) { continue; } BorrowableDetail memory detail = borrowable.getBorrowableDetail(); uint256 underlyingBalance = option.vaultBorrowableBalance.mul(option.exchangeRate).div(1E18); (uint256 gain, uint256 loss) = detail.getMyNetInterest( underlyingBalance, 0, option.withdrawBorrowableAmountAsUnderlying ); uint256 lossPerUnderlying = loss.mul(1e18).div(option.withdrawBorrowableAmountAsUnderlying); uint256 gainPerUnderlying = gain.mul(1e18).div(option.withdrawBorrowableAmountAsUnderlying); if (gainPerUnderlying > best.maxGain || (best.maxGain == 0 && lossPerUnderlying < best.minLoss)) { best.borrowable = borrowable; best.minLoss = lossPerUnderlying; best.maxGain = gainPerUnderlying; best.borrowableAmount = option.withdrawBorrowableAmount; best.underlyingAmount = option.withdrawBorrowableAmountAsUnderlying; } } require(best.minLoss < type(uint256).max, "SupplyVaultStrategyV3: 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, "SupplyVaultStrategyV3: ZERO_AMOUNT"); ISupplyVault supplyVault = ISupplyVault(msg.sender); IERC20 underlying = supplyVault.underlying(); needAmount = needAmount.add(supplyVaultInfo[supplyVault].additionalDeallocAmount); 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, "SupplyVaultStrategyV3: SAME_IN_OUT"); } else { require(false, "SupplyVaultStrategyV3: INVALID_DATA"); } } function reallocate(uint256 _underlyingAmount, bytes calldata _data) external override onlyAuthorized { require(_underlyingAmount > 0, "SupplyVaultStrategyV3: 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":[{"internalType":"contract ISupplyVault","name":"","type":"address"}],"name":"isAuthorized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","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":"contract ISupplyVault","name":"","type":"address"}],"name":"supplyVaultInfo","outputs":[{"internalType":"uint256","name":"additionalDeallocAmount","type":"uint256"},{"internalType":"uint256","name":"minAllocAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISupplyVault","name":"supplyVault","type":"address"},{"internalType":"uint256","name":"additionalDeallocAmount","type":"uint256"},{"internalType":"uint256","name":"minAllocAmount","type":"uint256"}],"name":"updateSupplyVaultInfo","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50600061001b61006a565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35061006e565b3390565b612b0f806200007e6000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c80638670d9dc1161008c578063abaa991611610066578063abaa991614610191578063b6a5d7de14610199578063f2fde38b146101ac578063fe9fbb80146101bf576100cf565b80638670d9dc146101565780638da5cb5b146101695780639685e7161461017e576100cf565b80632813a737146100d45780634dc0ed9b146100e957806357a43bd3146100fc5780636f6c441f14610126578063715018a61461013957806384bdc9a814610141575b600080fd5b6100e76100e236600461251d565b6101df565b005b6100e76100f736600461240f565b610282565b61010f61010a3660046123d7565b610302565b60405161011d929190612ab6565b60405180910390f35b6100e76101343660046125ab565b61031b565b6100e76104cd565b610149610556565b60405161011d9190612aad565b6100e76101643660046125db565b610802565b610171610b2b565b60405161011d9190612652565b61017161018c3660046123d7565b610b3a565b6100e7610dcf565b6100e76101a73660046123d7565b610f30565b6100e76101ba3660046123d7565b610f7b565b6101d26101cd3660046123d7565b61103b565b60405161011d9190612666565b6101e7611050565b6001600160a01b03166101f8610b2b565b6001600160a01b0316146102275760405162461bcd60e51b815260040161021e9061295f565b60405180910390fd5b6001600160a01b03831660009081526002602052604090205460ff1661025f5760405162461bcd60e51b815260040161021e906126cf565b6001600160a01b0390921660009081526001602081905260409091209182550155565b61028a611050565b6001600160a01b031661029b610b2b565b6001600160a01b0316146102c15760405162461bcd60e51b815260040161021e9061295f565b60005b818110156102fd576102f58383838181106102db57fe5b90506020020160208101906102f091906123d7565b611054565b6001016102c4565b505050565b6001602081905260009182526040909120805491015482565b3360009081526002602052604090205460ff1661034a5760405162461bcd60e51b815260040161021e9061268a565b6000811161036a5760405162461bcd60e51b815260040161021e9061291d565b60003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156103aa57600080fd5b505afa1580156103be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e291906123f3565b6001600160a01b0383166000908152600160205260409020549091506104099084906110b1565b92506000826001600160a01b031663821beaf56040518163ffffffff1660e01b815260040160206040518083038186803b15801561044657600080fd5b505afa15801561045a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061047e91906125c3565b90505b600061048f848385886110df565b90508481106104a157600094506104ae565b6104ab85826116a9565b94505b846104b957506104bf565b50610481565b83156104c757fe5b50505050565b6104d5611050565b6001600160a01b03166104e6610b2b565b6001600160a01b03161461050c5760405162461bcd60e51b815260040161021e9061295f565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b3360009081526002602052604081205460ff166105855760405162461bcd60e51b815260040161021e9061268a565b60003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156105c557600080fd5b505afa1580156105d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105fd91906123f3565b90506000816001600160a01b03166370a08231846040518263ffffffff1660e01b815260040161062d9190612652565b60206040518083038186803b15801561064557600080fd5b505afa158015610659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067d91906125c3565b9050600080846001600160a01b031663821beaf56040518163ffffffff1660e01b815260040160206040518083038186803b1580156106bb57600080fd5b505afa1580156106cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f391906125c3565b905060005b818110156107e65760405163ade37c1360e01b81526000906001600160a01b0388169063ade37c139061072f908590600401612aad565b60206040518083038186803b15801561074757600080fd5b505afa15801561075b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077f91906123f3565b905060006107966001600160a01b038316896116d1565b905080156107dc5760006107b2836001600160a01b0316611758565b509091506107cc90506107c58383611787565b87906110b1565b95506107d887836110b1565b9650505b50506001016106f8565b5082156107fa576107f782846117c1565b95505b505050505090565b3360009081526002602052604090205460ff166108315760405162461bcd60e51b815260040161021e9061268a565b600083116108515760405162461bcd60e51b815260040161021e9061291d565b61085961232a565b61086383836117f3565b905060003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b1580156108a557600080fd5b505afa1580156108b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108dd91906123f3565b90506000816001600160a01b03166370a08231846040518263ffffffff1660e01b815260040161090d9190612652565b60206040518083038186803b15801561092557600080fd5b505afa158015610939573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095d91906125c3565b905086811015610a1257600061097388836116a9565b85519091506001600160a01b031615610a0757845160009061099e906001600160a01b031683611873565b865160405163f26a584560e01b81529192506001600160a01b0387169163f26a5845916109cf918590600401612671565b600060405180830381600087803b1580156109e957600080fd5b505af11580156109fd573d6000803e3d6000fd5b5050505050610a10565b610a108161031b565b505b6000610a9988846001600160a01b03166370a08231876040518263ffffffff1660e01b8152600401610a449190612652565b60206040518083038186803b158015610a5c57600080fd5b505afa158015610a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9491906125c3565b611917565b60208601519091506001600160a01b031615610b18576020850151604051635a01cecf60e11b81526001600160a01b0386169163b4039d9e91610ae191908590600401612671565b600060405180830381600087803b158015610afb57600080fd5b505af1158015610b0f573d6000803e3d6000fd5b50505050610b21565b610b218161192e565b5050505050505050565b6000546001600160a01b031690565b3360009081526002602052604081205460ff16610b695760405162461bcd60e51b815260040161021e9061268a565b60003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610ba957600080fd5b505afa158015610bbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be191906123f3565b905060008060007335c052bbf8338b06351782a565aa9aad173432ea6001600160a01b0316630572bf5f886040518263ffffffff1660e01b8152600401610c289190612652565b60a06040518083038186803b158015610c4057600080fd5b505afa158015610c54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c78919061249e565b94509450505092508215610db257836001600160a01b0316826001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610cc957600080fd5b505afa158015610cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0191906123f3565b6001600160a01b03161415610d1c57509350610dca92505050565b836001600160a01b0316816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610d5f57600080fd5b505afa158015610d73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d9791906123f3565b6001600160a01b03161415610db2579450610dca9350505050565b60405162461bcd60e51b815260040161021e90612994565b919050565b3360009081526002602052604090205460ff16610dfe5760405162461bcd60e51b815260040161021e9061268a565b60003390506000816001600160a01b0316636f307dc36040518163ffffffff1660e01b815260040160206040518083038186803b158015610e3e57600080fd5b505afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7691906123f3565b90506000816001600160a01b03166370a08231846040518263ffffffff1660e01b8152600401610ea69190612652565b60206040518083038186803b158015610ebe57600080fd5b505afa158015610ed2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ef691906125c3565b6001600160a01b03841660009081526001602081905260409091200154909150811015610f2557505050610f2e565b6102fd8161192e565b565b610f38611050565b6001600160a01b0316610f49610b2b565b6001600160a01b031614610f6f5760405162461bcd60e51b815260040161021e9061295f565b610f7881611054565b50565b610f83611050565b6001600160a01b0316610f94610b2b565b6001600160a01b031614610fba5760405162461bcd60e51b815260040161021e9061295f565b6001600160a01b038116610fe05760405162461bcd60e51b815260040161021e90612756565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60026020526000908152604090205460ff1681565b3390565b6001600160a01b03811660009081526002602052604090205460ff161561108d5760405162461bcd60e51b815260040161021e90612a1f565b6001600160a01b03166000908152600260205260409020805460ff19166001179055565b6000828201838110156110d65760405162461bcd60e51b815260040161021e9061279c565b90505b92915050565b60006110e9612341565b600019606082015260005b858110156114df5760405163ade37c1360e01b81526000906001600160a01b0389169063ade37c139061112b908590600401612aad565b60206040518083038186803b15801561114357600080fd5b505afa158015611157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117b91906123f3565b9050611185612379565b816001600160a01b0316633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156111c057600080fd5b505af11580156111d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f891906125c3565b604080830191909152516370a0823160e01b81526001600160a01b038316906370a082319061122b908c90600401612652565b60206040518083038186803b15801561124357600080fd5b505afa158015611257573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061127b91906125c3565b6060820181905261128d5750506114d7565b6040516370a0823160e01b81526000906001600160a01b038916906370a08231906112bc908690600401612652565b60206040518083038186803b1580156112d457600080fd5b505afa1580156112e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061130c91906125c3565b905060006113398360400151611333670de0b6b3a76400008561178790919063ffffffff16565b906117c1565b90508061134957505050506114d7565b600061137960016113738660400151611333670de0b6b3a76400008e61178790919063ffffffff16565b906110b1565b905061138a81856060015184611d1d565b80855260408501516113aa91670de0b6b3a7640000916113339190611787565b60208501819052151592506113c39150505750506114d7565b6113cb6123a1565b6113dd836001600160a01b0316611d2d565b90506000611408670de0b6b3a76400006113338560400151866060015161178790919063ffffffff16565b9050600080611429836000876020015187612012909392919063ffffffff16565b9150915060006114528660200151611333670de0b6b3a76400008561178790919063ffffffff16565b905060006114798760200151611333670de0b6b3a76400008761178790919063ffffffff16565b9050896080015181118061149d575060808a015115801561149d5750896060015182105b156114ce576001600160a01b0388168a5260608a0182905260808a01819052865160408b0152602080880151908b01525b50505050505050505b6001016110f4565b506000198160600151106115055760405162461bcd60e51b815260040161021e9061285d565b6040516370a0823160e01b81526000906001600160a01b038616906370a0823190611534908a90600401612652565b60206040518083038186803b15801561154c57600080fd5b505afa158015611560573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158491906125c3565b8251604080850151905163f26a584560e01b81529293506001600160a01b038a169263f26a5845926115ba929091600401612671565b600060405180830381600087803b1580156115d457600080fd5b505af11580156115e8573d6000803e3d6000fd5b50506040516370a0823160e01b8152600092506001600160a01b03881691506370a082319061161b908b90600401612652565b60206040518083038186803b15801561163357600080fd5b505afa158015611647573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166b91906125c3565b602084015190915061167d82846116a9565b1461169a5760405162461bcd60e51b815260040161021e90612833565b50506020015195945050505050565b6000828211156116cb5760405162461bcd60e51b815260040161021e906127fc565b50900390565b60006110d683846001600160a01b03166370a08231856040518263ffffffff1660e01b81526004016117039190612652565b60206040518083038186803b15801561171b57600080fd5b505afa15801561172f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061175391906125c3565b6120f8565b60008060006117656123a1565b61176e85611d2d565b905061177981612194565b935093509350509193909250565b600082611796575060006110d9565b828202828482816117a357fe5b04146110d65760405162461bcd60e51b815260040161021e906128dc565b60008082116117e25760405162461bcd60e51b815260040161021e906128a5565b8183816117eb57fe5b049392505050565b6117fb61232a565b81611805576110d9565b604082141561185b5761181a82840184612551565b905080602001516001600160a01b031681600001516001600160a01b031614156118565760405162461bcd60e51b815260040161021e906129dd565b6110d9565b60405162461bcd60e51b815260040161021e90612713565b600081611882575060006110d9565b6000836001600160a01b0316633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118bf57600080fd5b505af11580156118d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f791906125c3565b905061190f8161133385670de0b6b3a7640000611787565b949350505050565b6000818310156119285750816110d9565b50919050565b338161193a5750610f78565b611942612341565b6000198160600181815250506000826001600160a01b031663821beaf56040518163ffffffff1660e01b815260040160206040518083038186803b15801561198957600080fd5b505afa15801561199d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c191906125c3565b9050600081116119e35760405162461bcd60e51b815260040161021e90612a68565b60005b81811015611caf5760405163ade37c1360e01b81526000906001600160a01b0386169063ade37c1390611a1d908590600401612aad565b60206040518083038186803b158015611a3557600080fd5b505afa158015611a49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6d91906123f3565b604051631aca889d60e31b81529091506001600160a01b0386169063d65444e890611a9c908490600401612652565b60206040518083038186803b158015611ab457600080fd5b505afa158015611ac8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aec919061247e565b611af65750611ca7565b6000816001600160a01b0316633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b3357600080fd5b505af1158015611b47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6b91906125c3565b90506000611b86600161137384670de0b6b3a76400006117c1565b905080881015611b9857505050611ca7565b611ba06123a1565b611bb2846001600160a01b0316611d2d565b90506000611c48670de0b6b3a764000061133386886001600160a01b03166370a082318e6040518263ffffffff1660e01b8152600401611bf29190612652565b60206040518083038186803b158015611c0a57600080fd5b505afa158015611c1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4291906125c3565b90611787565b9050600080611c5984848e84612012565b915091508960800151821180611c7f575060808a0151158015611c7f5750896060015181105b15611c9f576001600160a01b0387168a5260808a0182905260608a018190525b505050505050505b6001016119e6565b5081516001600160a01b0316156104c7578151604051635a01cecf60e11b81526001600160a01b0385169163b4039d9e91611cef91908890600401612671565b600060405180830381600087803b158015611d0957600080fd5b505af1158015610b21573d6000803e3d6000fd5b600061190f84610a948585611917565b611d356123a1565b816001600160a01b03166347bd37186040518163ffffffff1660e01b815260040160206040518083038186803b158015611d6e57600080fd5b505afa158015611d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da691906125c3565b816000018181525050816001600160a01b031663ad7a672f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611de857600080fd5b505afa158015611dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2091906125c3565b816020018181525050816001600160a01b0316631aebf12f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e6257600080fd5b505afa158015611e76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e9a91906125c3565b816040018181525050816001600160a01b03166391b427456040518163ffffffff1660e01b815260040160206040518083038186803b158015611edc57600080fd5b505afa158015611ef0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f1491906125c3565b816060018181525050816001600160a01b0316635b2b9d1a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f5657600080fd5b505afa158015611f6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8e91906125c3565b816080018181525050816001600160a01b0316634322b7146040518163ffffffff1660e01b815260040160206040518083038186803b158015611fd057600080fd5b505afa158015611fe4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200891906125c3565b60a0820152919050565b60008083151583151514156120395760405162461bcd60e51b815260040161021e906127d3565b600061204487612194565b50509050806000141561205e5750600091508190506120ef565b600061206b8887876121b2565b5050885160208a0151919250600091612083916110b1565b9050600061209289858461225c565b905060006120c16120ad896120a78d8d6110b1565b906116a9565b856120bc8b6120a7888f6110b1565b61225c565b9050818111156120dc576120d581836116a9565b96506120e9565b6120e682826116a9565b95505b50505050505b94509492505050565b600081612107575060006110d9565b6000836001600160a01b0316633ba0b9a96040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561214457600080fd5b505af1158015612158573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061217c91906125c3565b905061190f670de0b6b3a76400006113338584611787565b60008060006121a5846000806121b2565b9250925092509193909250565b600080808415806121c1575083155b6121dd5760405162461bcd60e51b815260040161021e906127d3565b6122148660000151612200866120a7898b602001516110b190919063ffffffff16565b886040015189606001518a60800151612278565b60a0880151919350915061225190670de0b6b3a7640000906113339061223b9083906116a9565b611c42670de0b6b3a76400006113338888611787565b925093509350939050565b600061190f8261133385611c42670de0b6b3a764000089611787565b6000808061228688886110b1565b905080156122a9576122a4816113338a670de0b6b3a7640000611787565b6122ac565b60005b9150858210156122cb576122c4866113338785611787565b925061231f565b60006122f86122e2670de0b6b3a7640000896116a9565b611333670de0b6b3a7640000611c42878c6116a9565b905061231b670de0b6b3a764000061133388611c428361137387838d60016116a9565b9350505b509550959350505050565b604080518082019091526000808252602082015290565b6040518060a0016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081525090565b6040518060800160405280600081526020016000815260200160008152602001600081525090565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6000602082840312156123e8578081fd5b81356110d681612ac4565b600060208284031215612404578081fd5b81516110d681612ac4565b60008060208385031215612421578081fd5b823567ffffffffffffffff80821115612438578283fd5b818501915085601f83011261244b578283fd5b813581811115612459578384fd5b866020808302850101111561246c578384fd5b60209290920196919550909350505050565b60006020828403121561248f578081fd5b815180151581146110d6578182fd5b600080600080600060a086880312156124b5578081fd5b855180151581146124c4578182fd5b602087015190955062ffffff811681146124dc578182fd5b60408701519094506124ed81612ac4565b60608701519093506124fe81612ac4565b608087015190925061250f81612ac4565b809150509295509295909350565b600080600060608486031215612531578283fd5b833561253c81612ac4565b95602085013595506040909401359392505050565b600060408284031215612562578081fd5b6040516040810181811067ffffffffffffffff82111715612581578283fd5b604052823561258f81612ac4565b8152602083013561259f81612ac4565b60208201529392505050565b6000602082840312156125bc578081fd5b5035919050565b6000602082840312156125d4578081fd5b5051919050565b6000806000604084860312156125ef578283fd5b83359250602084013567ffffffffffffffff8082111561260d578384fd5b818601915086601f830112612620578384fd5b81358181111561262e578485fd5b87602082850101111561263f578485fd5b6020830194508093505050509250925092565b6001600160a01b0391909116815260200190565b901515815260200190565b6001600160a01b03929092168252602082015260400190565b60208082526025908201527f537570706c795661756c74537472617465677956333a204e4f545f415554484f604082015264149256915160da1b606082015260800190565b60208082526024908201527f537570706c795661756c74537472617465677956333a20494e56414c49445f566040820152631055531560e21b606082015260800190565b60208082526023908201527f537570706c795661756c74537472617465677956333a20494e56414c49445f4460408201526241544160e81b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600f908201526e42483a20494e564c445f44454c544160881b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526010908201526f088cad8e8c240daeae6e840dac2e8c6d60831b604082015260600190565b60208082526028908201527f537570706c795661756c74537472617465677956333a20494e5355464649434960408201526708a9ca8be8682a6960c31b606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526022908201527f537570706c795661756c74537472617465677956333a205a45524f5f414d4f55604082015261139560f21b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f537570706c795661756c74537472617465677956333a20494e56414c49445f426040820152684f52524f5741424c4560b81b606082015260800190565b60208082526022908201527f537570706c795661756c74537472617465677956333a2053414d455f494e5f4f604082015261155560f21b606082015260800190565b60208082526029908201527f537570706c795661756c74537472617465677956333a20414c52454144595f4160408201526815551213d49256915160ba1b606082015260800190565b60208082526025908201527f537570706c795661756c74537472617465677956333a204e4f5f424f52524f5760408201526441424c455360d81b606082015260800190565b90815260200190565b918252602082015260400190565b6001600160a01b0381168114610f7857600080fdfea264697066735822122020ece92012122a7800e850414b108df5f59a87e82e6ad35ae7e11563480684ef64736f6c634300060c0033
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.