Overview
S Balance
0 S
S Value
-More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
434294 | 20 days ago | Contract Creation | 0 S |
Loading...
Loading
Contract Name:
FluidVaultT1Admin
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 10000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { Variables } from "../common/variables.sol"; import { Events } from "./events.sol"; import { ErrorTypes } from "../../errorTypes.sol"; import { Error } from "../../error.sol"; import { IFluidVaultT1 } from "../../interfaces/iVaultT1.sol"; import { BigMathMinified } from "../../../../libraries/bigMathMinified.sol"; import { TickMath } from "../../../../libraries/tickMath.sol"; import { SafeTransfer } from "../../../../libraries/safeTransfer.sol"; /// @notice Fluid Vault protocol Admin Module contract. /// Implements admin related methods to set configs such as liquidation params, rates /// oracle address etc. /// Methods are limited to be called via delegateCall only. Vault CoreModule ("VaultT1" contract) /// is expected to call the methods implemented here after checking the msg.sender is authorized. /// All methods update the exchange prices in storage before changing configs. contract FluidVaultT1Admin is Variables, Events, Error { uint private constant X8 = 0xff; uint private constant X10 = 0x3ff; uint private constant X16 = 0xffff; uint private constant X19 = 0x7ffff; uint private constant X24 = 0xffffff; uint internal constant X64 = 0xffffffffffffffff; uint private constant X96 = 0xffffffffffffffffffffffff; address private constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address private immutable addressThis; constructor() { addressThis = address(this); } modifier _verifyCaller() { if (address(this) == addressThis) { revert FluidVaultError(ErrorTypes.VaultAdmin__OnlyDelegateCallAllowed); } _; } /// @dev updates exchange price on storage, called on all admin methods in combination with _verifyCaller modifier so /// only called by authorized delegatecall modifier _updateExchangePrice() { IFluidVaultT1(address(this)).updateExchangePricesOnStorage(); _; } function _checkLiquidationMaxLimitAndPenalty(uint liquidationMaxLimit_, uint liquidationPenalty_) private pure { // liquidation max limit with penalty should not go above 99.7% // As liquidation with penalty can happen from liquidation Threshold to max limit // If it goes above 100% than that means liquidator is getting more collateral than user's available if ((liquidationMaxLimit_ + liquidationPenalty_) > 9970) { revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); } } /// @notice updates the supply rate magnifier to `supplyRateMagnifier_`. Input in 1e2 (1% = 100, 100% = 10_000). function updateSupplyRateMagnifier(uint supplyRateMagnifier_) public _updateExchangePrice _verifyCaller { emit LogUpdateSupplyRateMagnifier(supplyRateMagnifier_); if (supplyRateMagnifier_ > X16) revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); vaultVariables2 = (vaultVariables2 & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000) | supplyRateMagnifier_; } /// @notice updates the borrow rate magnifier to `borrowRateMagnifier_`. Input in 1e2 (1% = 100, 100% = 10_000). function updateBorrowRateMagnifier(uint borrowRateMagnifier_) public _updateExchangePrice _verifyCaller { emit LogUpdateBorrowRateMagnifier(borrowRateMagnifier_); if (borrowRateMagnifier_ > X16) revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); vaultVariables2 = (vaultVariables2 & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff) | (borrowRateMagnifier_ << 16); } /// @notice updates the collateral factor to `collateralFactor_`. Input in 1e2 (1% = 100, 100% = 10_000). function updateCollateralFactor(uint collateralFactor_) public _updateExchangePrice _verifyCaller { emit LogUpdateCollateralFactor(collateralFactor_); uint vaultVariables2_ = vaultVariables2; uint liquidationThreshold_ = ((vaultVariables2_ >> 42) & X10); collateralFactor_ = collateralFactor_ / 10; if (collateralFactor_ >= liquidationThreshold_) revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); vaultVariables2 = (vaultVariables2_ & 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffc00ffffffff) | (collateralFactor_ << 32); } /// @notice updates the liquidation threshold to `liquidationThreshold_`. Input in 1e2 (1% = 100, 100% = 10_000). function updateLiquidationThreshold(uint liquidationThreshold_) public _updateExchangePrice _verifyCaller { emit LogUpdateLiquidationThreshold(liquidationThreshold_); uint vaultVariables2_ = vaultVariables2; uint collateralFactor_ = ((vaultVariables2_ >> 32) & X10); uint liquidationMaxLimit_ = ((vaultVariables2_ >> 52) & X10); liquidationThreshold_ = liquidationThreshold_ / 10; if ((collateralFactor_ >= liquidationThreshold_) || (liquidationThreshold_ >= liquidationMaxLimit_)) revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); vaultVariables2 = (vaultVariables2_ & 0xfffffffffffffffffffffffffffffffffffffffffffffffffff003ffffffffff) | (liquidationThreshold_ << 42); } /// @notice updates the liquidation max limit to `liquidationMaxLimit_`. Input in 1e2 (1% = 100, 100% = 10_000). function updateLiquidationMaxLimit(uint liquidationMaxLimit_) public _updateExchangePrice _verifyCaller { emit LogUpdateLiquidationMaxLimit(liquidationMaxLimit_); uint vaultVariables2_ = vaultVariables2; uint liquidationThreshold_ = ((vaultVariables2_ >> 42) & X10); uint liquidationPenalty_ = ((vaultVariables2_ >> 72) & X10); // both are in 1e2 decimals (1e2 = 1%) _checkLiquidationMaxLimitAndPenalty(liquidationMaxLimit_, liquidationPenalty_); liquidationMaxLimit_ = liquidationMaxLimit_ / 10; if (liquidationThreshold_ >= liquidationMaxLimit_) revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); vaultVariables2 = (vaultVariables2_ & 0xffffffffffffffffffffffffffffffffffffffffffffffffc00fffffffffffff) | (liquidationMaxLimit_ << 52); } /// @notice updates the withdrawal gap to `withdrawGap_`. Input in 1e2 (1% = 100, 100% = 10_000). function updateWithdrawGap(uint withdrawGap_) public _updateExchangePrice _verifyCaller { emit LogUpdateWithdrawGap(withdrawGap_); withdrawGap_ = withdrawGap_ / 10; // withdrawGap must not be > 100% if (withdrawGap_ > 1000) revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); vaultVariables2 = (vaultVariables2 & 0xffffffffffffffffffffffffffffffffffffffffffffff003fffffffffffffff) | (withdrawGap_ << 62); } /// @notice updates the liquidation penalty to `liquidationPenalty_`. Input in 1e2 (1% = 100, 100% = 10_000). function updateLiquidationPenalty(uint liquidationPenalty_) public _updateExchangePrice _verifyCaller { emit LogUpdateLiquidationPenalty(liquidationPenalty_); uint vaultVariables2_ = vaultVariables2; uint liquidationMaxLimit_ = ((vaultVariables2_ >> 52) & X10); // Converting liquidationMaxLimit_ in 1e2 decimals (1e2 = 1%) _checkLiquidationMaxLimitAndPenalty((liquidationMaxLimit_ * 10), liquidationPenalty_); if (liquidationPenalty_ > X10) revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); vaultVariables2 = (vaultVariables2_ & 0xfffffffffffffffffffffffffffffffffffffffffffc00ffffffffffffffffff) | (liquidationPenalty_ << 72); } /// @notice updates the borrow fee to `borrowFee_`. Input in 1e2 (1% = 100, 100% = 10_000). function updateBorrowFee(uint borrowFee_) public _updateExchangePrice _verifyCaller { emit LogUpdateBorrowFee(borrowFee_); if (borrowFee_ > X10) revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); vaultVariables2 = (vaultVariables2 & 0xfffffffffffffffffffffffffffffffffffffffff003ffffffffffffffffffff) | (borrowFee_ << 82); } /// @notice updates the all Vault core settings according to input params. /// All input values are expected in 1e2 (1% = 100, 100% = 10_000). function updateCoreSettings( uint256 supplyRateMagnifier_, uint256 borrowRateMagnifier_, uint256 collateralFactor_, uint256 liquidationThreshold_, uint256 liquidationMaxLimit_, uint256 withdrawGap_, uint256 liquidationPenalty_, uint256 borrowFee_ ) public _updateExchangePrice _verifyCaller { // emitting the event at the start as then we are updating numbers to store in a more optimized way emit LogUpdateCoreSettings( supplyRateMagnifier_, borrowRateMagnifier_, collateralFactor_, liquidationThreshold_, liquidationMaxLimit_, withdrawGap_, liquidationPenalty_, borrowFee_ ); _checkLiquidationMaxLimitAndPenalty(liquidationMaxLimit_, liquidationPenalty_); collateralFactor_ = collateralFactor_ / 10; liquidationThreshold_ = liquidationThreshold_ / 10; liquidationMaxLimit_ = liquidationMaxLimit_ / 10; withdrawGap_ = withdrawGap_ / 10; if ( (supplyRateMagnifier_ > X16) || (borrowRateMagnifier_ > X16) || (collateralFactor_ >= liquidationThreshold_) || (liquidationThreshold_ >= liquidationMaxLimit_) || (withdrawGap_ > X10) || (liquidationPenalty_ > X10) || (borrowFee_ > X10) ) { revert FluidVaultError(ErrorTypes.VaultAdmin__ValueAboveLimit); } vaultVariables2 = (vaultVariables2 & 0xfffffffffffffffffffffffffffffffffffffffff00000000000000000000000) | supplyRateMagnifier_ | (borrowRateMagnifier_ << 16) | (collateralFactor_ << 32) | (liquidationThreshold_ << 42) | (liquidationMaxLimit_ << 52) | (withdrawGap_ << 62) | (liquidationPenalty_ << 72) | (borrowFee_ << 82); } /// @notice updates the Vault oracle to `newOracle_`. Must implement the FluidOracle interface. function updateOracle(address newOracle_) public _updateExchangePrice _verifyCaller { if (newOracle_ == address(0)) revert FluidVaultError(ErrorTypes.VaultAdmin__AddressZeroNotAllowed); // Removing current oracle by masking only first 96 bits then inserting new oracle as bits vaultVariables2 = (vaultVariables2 & X96) | (uint256(uint160(newOracle_)) << 96); emit LogUpdateOracle(newOracle_); } /// @notice updates the allowed rebalancer to `newRebalancer_`. function updateRebalancer(address newRebalancer_) public _updateExchangePrice _verifyCaller { if (newRebalancer_ == address(0)) revert FluidVaultError(ErrorTypes.VaultAdmin__AddressZeroNotAllowed); rebalancer = newRebalancer_; emit LogUpdateRebalancer(newRebalancer_); } /// @notice sends any potentially stuck funds to Liquidity contract. /// @dev this contract never holds any funds as all operations send / receive funds from user <-> Liquidity. function rescueFunds(address token_) external _verifyCaller { if (token_ == NATIVE_TOKEN) { SafeTransfer.safeTransferNative(IFluidVaultT1(address(this)).LIQUIDITY(), address(this).balance); } else { SafeTransfer.safeTransfer( token_, IFluidVaultT1(address(this)).LIQUIDITY(), IERC20(token_).balanceOf(address(this)) ); } emit LogRescueFunds(token_); } /// @notice absorbs accumulated dust debt /// @dev in decades if a lot of positions are 100% liquidated (aka absorbed) then dust debt can mount up /// which is basically sort of an extra revenue for the protocol. // // this function might never come in use that's why adding it in admin module function absorbDustDebt(uint[] memory nftIds_) public _verifyCaller { uint256 vaultVariables_ = vaultVariables; // re-entrancy check if (vaultVariables_ & 1 == 0) { // Updating on storage vaultVariables = vaultVariables_ | 1; } else { revert FluidVaultError(ErrorTypes.Vault__AlreadyEntered); } uint nftId_; uint posData_; int posTick_; uint tickId_; uint posCol_; uint posDebt_; uint posDustDebt_; uint tickData_; uint absorbedDustDebt_ = absorbedDustDebt; for (uint i = 0; i < nftIds_.length; ) { nftId_ = nftIds_[i]; if (nftId_ == 0) { revert FluidVaultError(ErrorTypes.VaultAdmin__NftIdShouldBeNonZero); } // user's position data posData_ = positionData[nftId_]; if (posData_ == 0) { revert FluidVaultError(ErrorTypes.VaultAdmin__NftNotOfThisVault); } posCol_ = (posData_ >> 45) & X64; // Converting big number into normal number posCol_ = (posCol_ >> 8) << (posCol_ & X8); posDustDebt_ = (posData_ >> 109) & X64; // Converting big number into normal number posDustDebt_ = (posDustDebt_ >> 8) << (posDustDebt_ & X8); if (posDustDebt_ == 0) { revert FluidVaultError(ErrorTypes.VaultAdmin__DustDebtIsZero); } // borrow position (has collateral & debt) posTick_ = posData_ & 2 == 2 ? int((posData_ >> 2) & X19) : -int((posData_ >> 2) & X19); tickId_ = (posData_ >> 21) & X24; posDebt_ = (TickMath.getRatioAtTick(int24(posTick_)) * posCol_) >> 96; // Tick data from user's tick tickData_ = tickData[posTick_]; // Checking if tick is liquidated OR if the total IDs of tick is greater than user's tick ID if (((tickData_ & 1) == 1) || (((tickData_ >> 1) & X24) > tickId_)) { // User got liquidated (, posDebt_, , , ) = IFluidVaultT1(address(this)).fetchLatestPosition( posTick_, tickId_, posDebt_, tickData_ ); if (posDebt_ > 0) { revert FluidVaultError(ErrorTypes.VaultAdmin__FinalDebtShouldBeZero); } // absorbing user's debt as it's 100% or almost 100% liquidated absorbedDustDebt_ = absorbedDustDebt_ + posDustDebt_; // making position as supply only positionData[nftId_] = 1; } else { revert FluidVaultError(ErrorTypes.VaultAdmin__NftNotLiquidated); } unchecked { i++; } } if (absorbedDustDebt_ == 0) { revert FluidVaultError(ErrorTypes.VaultAdmin__AbsorbedDustDebtIsZero); } uint totalBorrow_ = (vaultVariables_ >> 146) & X64; // Converting big number into normal number totalBorrow_ = (totalBorrow_ >> 8) << (totalBorrow_ & X8); // note: by default dust debt is not added into total borrow but on 100% liquidation (aka absorb) dust debt equivalent // is removed from total borrow so adding it back again here totalBorrow_ = totalBorrow_ + absorbedDustDebt_; totalBorrow_ = BigMathMinified.toBigNumber(totalBorrow_, 56, 8, BigMathMinified.ROUND_UP); // adding absorbed dust debt to total borrow so it will get included in the next rebalancing. // there is some fuzziness here as when the position got fully liquidated (aka absorbed) the exchange price was different // than what it'll be now. The fuzziness which will be extremely small so we can ignore it // updating on storage vaultVariables = (vaultVariables_ & 0xfffffffffffc0000000000000003ffffffffffffffffffffffffffffffffffff) | (totalBorrow_ << 146); // updating on storage absorbedDustDebt = 0; emit LogAbsorbDustDebt(nftIds_, absorbedDustDebt_); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; /// @title library that represents a number in BigNumber(coefficient and exponent) format to store in smaller bits. /// @notice the number is divided into two parts: a coefficient and an exponent. This comes at a cost of losing some precision /// at the end of the number because the exponent simply fills it with zeroes. This precision is oftentimes negligible and can /// result in significant gas cost reduction due to storage space reduction. /// Also note, a valid big number is as follows: if the exponent is > 0, then coefficient last bits should be occupied to have max precision. /// @dev roundUp is more like a increase 1, which happens everytime for the same number. /// roundDown simply sets trailing digits after coefficientSize to zero (floor), only once for the same number. library BigMathMinified { /// @dev constants to use for `roundUp` input param to increase readability bool internal constant ROUND_DOWN = false; bool internal constant ROUND_UP = true; /// @dev converts `normal` number to BigNumber with `exponent` and `coefficient` (or precision). /// e.g.: /// 5035703444687813576399599 (normal) = (coefficient[32bits], exponent[8bits])[40bits] /// 5035703444687813576399599 (decimal) => 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 (binary) /// => 10000101010010110100000011111011000000000000000000000000000000000000000000000000000 /// ^-------------------- 51(exponent) -------------- ^ /// coefficient = 1000,0101,0100,1011,0100,0000,1111,1011 (2236301563) /// exponent = 0011,0011 (51) /// bigNumber = 1000,0101,0100,1011,0100,0000,1111,1011,0011,0011 (572493200179) /// /// @param normal number which needs to be converted into Big Number /// @param coefficientSize at max how many bits of precision there should be (64 = uint64 (64 bits precision)) /// @param exponentSize at max how many bits of exponent there should be (8 = uint8 (8 bits exponent)) /// @param roundUp signals if result should be rounded down or up /// @return bigNumber converted bigNumber (coefficient << exponent) function toBigNumber( uint256 normal, uint256 coefficientSize, uint256 exponentSize, bool roundUp ) internal pure returns (uint256 bigNumber) { assembly { let lastBit_ let number_ := normal if gt(number_, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) { number_ := shr(0x80, number_) lastBit_ := 0x80 } if gt(number_, 0xFFFFFFFFFFFFFFFF) { number_ := shr(0x40, number_) lastBit_ := add(lastBit_, 0x40) } if gt(number_, 0xFFFFFFFF) { number_ := shr(0x20, number_) lastBit_ := add(lastBit_, 0x20) } if gt(number_, 0xFFFF) { number_ := shr(0x10, number_) lastBit_ := add(lastBit_, 0x10) } if gt(number_, 0xFF) { number_ := shr(0x8, number_) lastBit_ := add(lastBit_, 0x8) } if gt(number_, 0xF) { number_ := shr(0x4, number_) lastBit_ := add(lastBit_, 0x4) } if gt(number_, 0x3) { number_ := shr(0x2, number_) lastBit_ := add(lastBit_, 0x2) } if gt(number_, 0x1) { lastBit_ := add(lastBit_, 1) } if gt(number_, 0) { lastBit_ := add(lastBit_, 1) } if lt(lastBit_, coefficientSize) { // for throw exception lastBit_ := coefficientSize } let exponent := sub(lastBit_, coefficientSize) let coefficient := shr(exponent, normal) if and(roundUp, gt(exponent, 0)) { // rounding up is only needed if exponent is > 0, as otherwise the coefficient fully holds the original number coefficient := add(coefficient, 1) if eq(shl(coefficientSize, 1), coefficient) { // case were coefficient was e.g. 111, with adding 1 it became 1000 (in binary) and coefficientSize 3 bits // final coefficient would exceed it's size. -> reduce coefficent to 100 and increase exponent by 1. coefficient := shl(sub(coefficientSize, 1), 1) exponent := add(exponent, 1) } } if iszero(lt(exponent, shl(exponentSize, 1))) { // if exponent is >= exponentSize, the normal number is too big to fit within // BigNumber with too small sizes for coefficient and exponent revert(0, 0) } bigNumber := shl(exponentSize, coefficient) bigNumber := add(bigNumber, exponent) } } /// @dev get `normal` number from `bigNumber`, `exponentSize` and `exponentMask` function fromBigNumber( uint256 bigNumber, uint256 exponentSize, uint256 exponentMask ) internal pure returns (uint256 normal) { assembly { let coefficient := shr(exponentSize, bigNumber) let exponent := and(bigNumber, exponentMask) normal := shl(exponent, coefficient) } } /// @dev gets the most significant bit `lastBit` of a `normal` number (length of given number of binary format). /// e.g. /// 5035703444687813576399599 = 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 /// lastBit = ^--------------------------------- 83 ----------------------------------------^ function mostSignificantBit(uint256 normal) internal pure returns (uint lastBit) { assembly { let number_ := normal if gt(normal, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) { number_ := shr(0x80, number_) lastBit := 0x80 } if gt(number_, 0xFFFFFFFFFFFFFFFF) { number_ := shr(0x40, number_) lastBit := add(lastBit, 0x40) } if gt(number_, 0xFFFFFFFF) { number_ := shr(0x20, number_) lastBit := add(lastBit, 0x20) } if gt(number_, 0xFFFF) { number_ := shr(0x10, number_) lastBit := add(lastBit, 0x10) } if gt(number_, 0xFF) { number_ := shr(0x8, number_) lastBit := add(lastBit, 0x8) } if gt(number_, 0xF) { number_ := shr(0x4, number_) lastBit := add(lastBit, 0x4) } if gt(number_, 0x3) { number_ := shr(0x2, number_) lastBit := add(lastBit, 0x2) } if gt(number_, 0x1) { lastBit := add(lastBit, 1) } if gt(number_, 0) { lastBit := add(lastBit, 1) } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; library LibsErrorTypes { /***********************************| | LiquidityCalcs | |__________________________________*/ /// @notice thrown when supply or borrow exchange price is zero at calc token data (token not configured yet) uint256 internal constant LiquidityCalcs__ExchangePriceZero = 70001; /// @notice thrown when rate data is set to a version that is not implemented uint256 internal constant LiquidityCalcs__UnsupportedRateVersion = 70002; /// @notice thrown when the calculated borrow rate turns negative. This should never happen. uint256 internal constant LiquidityCalcs__BorrowRateNegative = 70003; /***********************************| | SafeTransfer | |__________________________________*/ /// @notice thrown when safe transfer from for an ERC20 fails uint256 internal constant SafeTransfer__TransferFromFailed = 71001; /// @notice thrown when safe transfer for an ERC20 fails uint256 internal constant SafeTransfer__TransferFailed = 71002; /***********************************| | SafeApprove | |__________________________________*/ /// @notice thrown when safe approve from for an ERC20 fails uint256 internal constant SafeApprove__ApproveFailed = 81001; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.21; import { LibsErrorTypes as ErrorTypes } from "./errorTypes.sol"; /// @notice provides minimalistic methods for safe transfers, e.g. ERC20 safeTransferFrom library SafeTransfer { uint256 internal constant MAX_NATIVE_TRANSFER_GAS = 20000; // pass max. 20k gas for native transfers error FluidSafeTransferError(uint256 errorId_); /// @dev Transfer `amount_` of `token_` from `from_` to `to_`, spending the approval given by `from_` to the /// calling contract. If `token_` returns no value, non-reverting calls are assumed to be successful. /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error): /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L31-L63 function safeTransferFrom(address token_, address from_, address to_, uint256 amount_) internal { bool success_; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(from_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from_" argument. mstore(add(freeMemoryPointer, 36), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to_" argument. mstore(add(freeMemoryPointer, 68), amount_) // Append the "amount_" argument. Masking not required as it's a full 32 byte type. success_ := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token_, 0, freeMemoryPointer, 100, 0, 32) ) } if (!success_) { revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFromFailed); } } /// @dev Transfer `amount_` of `token_` to `to_`. /// If `token_` returns no value, non-reverting calls are assumed to be successful. /// Minimally modified from Solmate SafeTransferLib (address as input param for token, Custom Error): /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L65-L95 function safeTransfer(address token_, address to_, uint256 amount_) internal { bool success_; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to_, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to_" argument. mstore(add(freeMemoryPointer, 36), amount_) // Append the "amount_" argument. Masking not required as it's a full 32 byte type. success_ := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token_, 0, freeMemoryPointer, 68, 0, 32) ) } if (!success_) { revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed); } } /// @dev Transfer `amount_` of ` native token to `to_`. /// Minimally modified from Solmate SafeTransferLib (Custom Error): /// https://github.com/transmissions11/solmate/blob/50e15bb566f98b7174da9b0066126a4c3e75e0fd/src/utils/SafeTransferLib.sol#L15-L25 function safeTransferNative(address to_, uint256 amount_) internal { bool success_; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. Pass limited gas success_ := call(MAX_NATIVE_TRANSFER_GAS, to_, amount_, 0, 0, 0, 0) } if (!success_) { revert FluidSafeTransferError(ErrorTypes.SafeTransfer__TransferFailed); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; /// @title library that calculates number "tick" and "ratioX96" from this: ratioX96 = (1.0015^tick) * 2^96 /// @notice this library is used in Fluid Vault protocol for optimiziation. /// @dev "tick" supports between -32767 and 32767. "ratioX96" supports between 37075072 and 169307877264527972847801929085841449095838922544595 library TickMath { /// The minimum tick that can be passed in getRatioAtTick. 1.0015**-32767 int24 internal constant MIN_TICK = -32767; /// The maximum tick that can be passed in getRatioAtTick. 1.0015**32767 int24 internal constant MAX_TICK = 32767; uint256 internal constant FACTOR00 = 0x100000000000000000000000000000000; uint256 internal constant FACTOR01 = 0xff9dd7de423466c20352b1246ce4856f; // 2^128/1.0015**1 = 339772707859149738855091969477551883631 uint256 internal constant FACTOR02 = 0xff3bd55f4488ad277531fa1c725a66d0; // 2^128/1.0015**2 = 339263812140938331358054887146831636176 uint256 internal constant FACTOR03 = 0xfe78410fd6498b73cb96a6917f853259; // 2^128/1.0015**4 = 338248306163758188337119769319392490073 uint256 internal constant FACTOR04 = 0xfcf2d9987c9be178ad5bfeffaa123273; // 2^128/1.0015**8 = 336226404141693512316971918999264834163 uint256 internal constant FACTOR05 = 0xf9ef02c4529258b057769680fc6601b3; // 2^128/1.0015**16 = 332218786018727629051611634067491389875 uint256 internal constant FACTOR06 = 0xf402d288133a85a17784a411f7aba082; // 2^128/1.0015**32 = 324346285652234375371948336458280706178 uint256 internal constant FACTOR07 = 0xe895615b5beb6386553757b0352bda90; // 2^128/1.0015**64 = 309156521885964218294057947947195947664 uint256 internal constant FACTOR08 = 0xd34f17a00ffa00a8309940a15930391a; // 2^128/1.0015**128 = 280877777739312896540849703637713172762 uint256 internal constant FACTOR09 = 0xae6b7961714e20548d88ea5123f9a0ff; // 2^128/1.0015**256 = 231843708922198649176471782639349113087 uint256 internal constant FACTOR10 = 0x76d6461f27082d74e0feed3b388c0ca1; // 2^128/1.0015**512 = 157961477267171621126394973980180876449 uint256 internal constant FACTOR11 = 0x372a3bfe0745d8b6b19d985d9a8b85bb; // 2^128/1.0015**1024 = 73326833024599564193373530205717235131 uint256 internal constant FACTOR12 = 0x0be32cbee48979763cf7247dd7bb539d; // 2^128/1.0015**2048 = 15801066890623697521348224657638773661 uint256 internal constant FACTOR13 = 0x8d4f70c9ff4924dac37612d1e2921e; // 2^128/1.0015**4096 = 733725103481409245883800626999235102 uint256 internal constant FACTOR14 = 0x4e009ae5519380809a02ca7aec77; // 2^128/1.0015**8192 = 1582075887005588088019997442108535 uint256 internal constant FACTOR15 = 0x17c45e641b6e95dee056ff10; // 2^128/1.0015**16384 = 7355550435635883087458926352 /// The minimum value that can be returned from getRatioAtTick. Equivalent to getRatioAtTick(MIN_TICK). ~ Equivalent to `(1 << 96) * (1.0015**-32767)` uint256 internal constant MIN_RATIOX96 = 37075072; /// The maximum value that can be returned from getRatioAtTick. Equivalent to getRatioAtTick(MAX_TICK). /// ~ Equivalent to `(1 << 96) * (1.0015**32767)`, rounding etc. leading to minor difference uint256 internal constant MAX_RATIOX96 = 169307877264527972847801929085841449095838922544595; uint256 internal constant ZERO_TICK_SCALED_RATIO = 0x1000000000000000000000000; // 1 << 96 // 79228162514264337593543950336 uint256 internal constant _1E26 = 1e26; /// @notice ratioX96 = (1.0015^tick) * 2^96 /// @dev Throws if |tick| > max tick /// @param tick The input tick for the above formula /// @return ratioX96 ratio = (debt amount/collateral amount) function getRatioAtTick(int tick) internal pure returns (uint256 ratioX96) { assembly { let absTick_ := sub(xor(tick, sar(255, tick)), sar(255, tick)) if gt(absTick_, MAX_TICK) { revert(0, 0) } let factor_ := FACTOR00 if and(absTick_, 0x1) { factor_ := FACTOR01 } if and(absTick_, 0x2) { factor_ := shr(128, mul(factor_, FACTOR02)) } if and(absTick_, 0x4) { factor_ := shr(128, mul(factor_, FACTOR03)) } if and(absTick_, 0x8) { factor_ := shr(128, mul(factor_, FACTOR04)) } if and(absTick_, 0x10) { factor_ := shr(128, mul(factor_, FACTOR05)) } if and(absTick_, 0x20) { factor_ := shr(128, mul(factor_, FACTOR06)) } if and(absTick_, 0x40) { factor_ := shr(128, mul(factor_, FACTOR07)) } if and(absTick_, 0x80) { factor_ := shr(128, mul(factor_, FACTOR08)) } if and(absTick_, 0x100) { factor_ := shr(128, mul(factor_, FACTOR09)) } if and(absTick_, 0x200) { factor_ := shr(128, mul(factor_, FACTOR10)) } if and(absTick_, 0x400) { factor_ := shr(128, mul(factor_, FACTOR11)) } if and(absTick_, 0x800) { factor_ := shr(128, mul(factor_, FACTOR12)) } if and(absTick_, 0x1000) { factor_ := shr(128, mul(factor_, FACTOR13)) } if and(absTick_, 0x2000) { factor_ := shr(128, mul(factor_, FACTOR14)) } if and(absTick_, 0x4000) { factor_ := shr(128, mul(factor_, FACTOR15)) } let precision_ := 0 if iszero(and(tick, 0x8000000000000000000000000000000000000000000000000000000000000000)) { factor_ := div(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, factor_) // we round up in the division so getTickAtRatio of the output price is always consistent if mod(factor_, 0x100000000) { precision_ := 1 } } ratioX96 := add(shr(32, factor_), precision_) } } /// @notice ratioX96 = (1.0015^tick) * 2^96 /// @dev Throws if ratioX96 > max ratio || ratioX96 < min ratio /// @param ratioX96 The input ratio; ratio = (debt amount/collateral amount) /// @return tick The output tick for the above formula. Returns in round down form. if tick is 123.23 then 123, if tick is -123.23 then returns -124 /// @return perfectRatioX96 perfect ratio for the above tick function getTickAtRatio(uint256 ratioX96) internal pure returns (int tick, uint perfectRatioX96) { assembly { if or(gt(ratioX96, MAX_RATIOX96), lt(ratioX96, MIN_RATIOX96)) { revert(0, 0) } let cond := lt(ratioX96, ZERO_TICK_SCALED_RATIO) let factor_ if iszero(cond) { // if ratioX96 >= ZERO_TICK_SCALED_RATIO factor_ := div(mul(ratioX96, _1E26), ZERO_TICK_SCALED_RATIO) } if cond { // ratioX96 < ZERO_TICK_SCALED_RATIO factor_ := div(mul(ZERO_TICK_SCALED_RATIO, _1E26), ratioX96) } // put in https://www.wolframalpha.com/ whole equation: (1.0015^tick) * 2^96 * 10^26 / 79228162514264337593543950336 // for tick = 16384 // ratioX96 = (1.0015^16384) * 2^96 = 3665252098134783297721995888537077351735 // 3665252098134783297721995888537077351735 * 10^26 / 79228162514264337593543950336 = // 4626198540796508716348404308345255985.06131964639489434655721 if iszero(lt(factor_, 4626198540796508716348404308345255985)) { tick := or(tick, 0x4000) factor_ := div(mul(factor_, _1E26), 4626198540796508716348404308345255985) } // for tick = 8192 // ratioX96 = (1.0015^8192) * 2^96 = 17040868196391020479062776466509865 // 17040868196391020479062776466509865 * 10^26 / 79228162514264337593543950336 = // 21508599537851153911767490449162.3037648642153898377655505172 if iszero(lt(factor_, 21508599537851153911767490449162)) { tick := or(tick, 0x2000) factor_ := div(mul(factor_, _1E26), 21508599537851153911767490449162) } // for tick = 4096 // ratioX96 = (1.0015^4096) * 2^96 = 36743933851015821532611831851150 // 36743933851015821532611831851150 * 10^26 / 79228162514264337593543950336 = // 46377364670549310883002866648.9777607649742626173648716941385 if iszero(lt(factor_, 46377364670549310883002866649)) { tick := or(tick, 0x1000) factor_ := div(mul(factor_, _1E26), 46377364670549310883002866649) } // for tick = 2048 // ratioX96 = (1.0015^2048) * 2^96 = 1706210527034005899209104452335 // 1706210527034005899209104452335 * 10^26 / 79228162514264337593543950336 = // 2153540449365864845468344760.06357108484096046743300420319322 if iszero(lt(factor_, 2153540449365864845468344760)) { tick := or(tick, 0x800) factor_ := div(mul(factor_, _1E26), 2153540449365864845468344760) } // for tick = 1024 // ratioX96 = (1.0015^1024) * 2^96 = 367668226692760093024536487236 // 367668226692760093024536487236 * 10^26 / 79228162514264337593543950336 = // 464062544207767844008185024.950588990554136265212906454481127 if iszero(lt(factor_, 464062544207767844008185025)) { tick := or(tick, 0x400) factor_ := div(mul(factor_, _1E26), 464062544207767844008185025) } // for tick = 512 // ratioX96 = (1.0015^512) * 2^96 = 170674186729409605620119663668 // 170674186729409605620119663668 * 10^26 / 79228162514264337593543950336 = // 215421109505955298802281577.031879604792139232258508172947569 if iszero(lt(factor_, 215421109505955298802281577)) { tick := or(tick, 0x200) factor_ := div(mul(factor_, _1E26), 215421109505955298802281577) } // for tick = 256 // ratioX96 = (1.0015^256) * 2^96 = 116285004205991934861656513301 // 116285004205991934861656513301 * 10^26 / 79228162514264337593543950336 = // 146772309890508740607270614.667650899656438875541505058062410 if iszero(lt(factor_, 146772309890508740607270615)) { tick := or(tick, 0x100) factor_ := div(mul(factor_, _1E26), 146772309890508740607270615) } // for tick = 128 // ratioX96 = (1.0015^128) * 2^96 = 95984619659632141743747099590 // 95984619659632141743747099590 * 10^26 / 79228162514264337593543950336 = // 121149622323187099817270416.157248837742741760456796835775887 if iszero(lt(factor_, 121149622323187099817270416)) { tick := or(tick, 0x80) factor_ := div(mul(factor_, _1E26), 121149622323187099817270416) } // for tick = 64 // ratioX96 = (1.0015^64) * 2^96 = 87204845308406958006717891124 // 87204845308406958006717891124 * 10^26 / 79228162514264337593543950336 = // 110067989135437147685980801.568068573422377364214113968609839 if iszero(lt(factor_, 110067989135437147685980801)) { tick := or(tick, 0x40) factor_ := div(mul(factor_, _1E26), 110067989135437147685980801) } // for tick = 32 // ratioX96 = (1.0015^32) * 2^96 = 83120873769022354029916374475 // 83120873769022354029916374475 * 10^26 / 79228162514264337593543950336 = // 104913292358707887270979599.831816586773651266562785765558183 if iszero(lt(factor_, 104913292358707887270979600)) { tick := or(tick, 0x20) factor_ := div(mul(factor_, _1E26), 104913292358707887270979600) } // for tick = 16 // ratioX96 = (1.0015^16) * 2^96 = 81151180492336368327184716176 // 81151180492336368327184716176 * 10^26 / 79228162514264337593543950336 = // 102427189924701091191840927.762844039579442328381455567932128 if iszero(lt(factor_, 102427189924701091191840928)) { tick := or(tick, 0x10) factor_ := div(mul(factor_, _1E26), 102427189924701091191840928) } // for tick = 8 // ratioX96 = (1.0015^8) * 2^96 = 80183906840906820640659903620 // 80183906840906820640659903620 * 10^26 / 79228162514264337593543950336 = // 101206318935480056907421312.890625 if iszero(lt(factor_, 101206318935480056907421313)) { tick := or(tick, 0x8) factor_ := div(mul(factor_, _1E26), 101206318935480056907421313) } // for tick = 4 // ratioX96 = (1.0015^4) * 2^96 = 79704602139525152702959747603 // 79704602139525152702959747603 * 10^26 / 79228162514264337593543950336 = // 100601351350506250000000000 if iszero(lt(factor_, 100601351350506250000000000)) { tick := or(tick, 0x4) factor_ := div(mul(factor_, _1E26), 100601351350506250000000000) } // for tick = 2 // ratioX96 = (1.0015^2) * 2^96 = 79466025265172787701084167660 // 79466025265172787701084167660 * 10^26 / 79228162514264337593543950336 = // 100300225000000000000000000 if iszero(lt(factor_, 100300225000000000000000000)) { tick := or(tick, 0x2) factor_ := div(mul(factor_, _1E26), 100300225000000000000000000) } // for tick = 1 // ratioX96 = (1.0015^1) * 2^96 = 79347004758035734099934266261 // 79347004758035734099934266261 * 10^26 / 79228162514264337593543950336 = // 100150000000000000000000000 if iszero(lt(factor_, 100150000000000000000000000)) { tick := or(tick, 0x1) factor_ := div(mul(factor_, _1E26), 100150000000000000000000000) } if iszero(cond) { // if ratioX96 >= ZERO_TICK_SCALED_RATIO perfectRatioX96 := div(mul(ratioX96, _1E26), factor_) } if cond { // ratioX96 < ZERO_TICK_SCALED_RATIO tick := not(tick) perfectRatioX96 := div(mul(ratioX96, factor_), 100150000000000000000000000) } // perfect ratio should always be <= ratioX96 // not sure if it can ever be bigger but better to have extra checks if gt(perfectRatioX96, ratioX96) { revert(0, 0) } } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; abstract contract Error { error FluidVaultError(uint256 errorId_); /// @notice used to simulate liquidation to find the maximum liquidatable amounts error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; library ErrorTypes { /***********************************| | Vault Factory | |__________________________________*/ uint256 internal constant VaultFactory__InvalidOperation = 30001; uint256 internal constant VaultFactory__Unauthorized = 30002; uint256 internal constant VaultFactory__SameTokenNotAllowed = 30003; uint256 internal constant VaultFactory__InvalidParams = 30004; uint256 internal constant VaultFactory__InvalidVault = 30005; uint256 internal constant VaultFactory__InvalidVaultAddress = 30006; uint256 internal constant VaultFactory__OnlyDelegateCallAllowed = 30007; /***********************************| | Vault | |__________________________________*/ /// @notice thrown at reentrancy uint256 internal constant Vault__AlreadyEntered = 31001; /// @notice thrown when user sends deposit & borrow amount as 0 uint256 internal constant Vault__InvalidOperateAmount = 31002; /// @notice thrown when msg.value is not in sync with native token deposit or payback uint256 internal constant Vault__InvalidMsgValueOperate = 31003; /// @notice thrown when msg.sender is not the owner of the vault uint256 internal constant Vault__NotAnOwner = 31004; /// @notice thrown when user's position does not exist. Sending the wrong index from the frontend uint256 internal constant Vault__TickIsEmpty = 31005; /// @notice thrown when the user's position is above CF and the user tries to make it more risky by trying to withdraw or borrow uint256 internal constant Vault__PositionAboveCF = 31006; /// @notice thrown when the top tick is not initialized. Happens if the vault is totally new or all the user's left uint256 internal constant Vault__TopTickDoesNotExist = 31007; /// @notice thrown when msg.value in liquidate is not in sync payback uint256 internal constant Vault__InvalidMsgValueLiquidate = 31008; /// @notice thrown when slippage is more on liquidation than what the liquidator sent uint256 internal constant Vault__ExcessSlippageLiquidation = 31009; /// @notice thrown when msg.sender is not the rebalancer/reserve contract uint256 internal constant Vault__NotRebalancer = 31010; /// @notice thrown when NFT of one vault interacts with the NFT of other vault uint256 internal constant Vault__NftNotOfThisVault = 31011; /// @notice thrown when the token is not initialized on the liquidity contract uint256 internal constant Vault__TokenNotInitialized = 31012; /// @notice thrown when admin updates fallback if a non-auth calls vault uint256 internal constant Vault__NotAnAuth = 31013; /// @notice thrown in operate when user tries to witdhraw more collateral than deposited uint256 internal constant Vault__ExcessCollateralWithdrawal = 31014; /// @notice thrown in operate when user tries to payback more debt than borrowed uint256 internal constant Vault__ExcessDebtPayback = 31015; /// @notice thrown when user try to withdrawal more than operate's withdrawal limit uint256 internal constant Vault__WithdrawMoreThanOperateLimit = 31016; /// @notice thrown when caller of liquidityCallback is not Liquidity uint256 internal constant Vault__InvalidLiquidityCallbackAddress = 31017; /// @notice thrown when reentrancy is not already on uint256 internal constant Vault__NotEntered = 31018; /// @notice thrown when someone directly calls operate or secondary implementation contract uint256 internal constant Vault__OnlyDelegateCallAllowed = 31019; /// @notice thrown when the safeTransferFrom for a token amount failed uint256 internal constant Vault__TransferFromFailed = 31020; /// @notice thrown when exchange price overflows while updating on storage uint256 internal constant Vault__ExchangePriceOverFlow = 31021; /// @notice thrown when debt to liquidate amt is sent wrong uint256 internal constant Vault__InvalidLiquidationAmt = 31022; /// @notice thrown when user debt or collateral goes above 2**128 or below -2**128 uint256 internal constant Vault__UserCollateralDebtExceed = 31023; /// @notice thrown if on liquidation branch debt becomes lower than 100 uint256 internal constant Vault__BranchDebtTooLow = 31024; /// @notice thrown when tick's debt is less than 10000 uint256 internal constant Vault__TickDebtTooLow = 31025; /// @notice thrown when the received new liquidity exchange price is of unexpected value (< than the old one) uint256 internal constant Vault__LiquidityExchangePriceUnexpected = 31026; /// @notice thrown when user's debt is less than 10000 uint256 internal constant Vault__UserDebtTooLow = 31027; /// @notice thrown when on only payback and only deposit the ratio of position increases uint256 internal constant Vault__InvalidPaybackOrDeposit = 31028; /// @notice thrown when liquidation just happens of a single partial or when there's nothing to liquidate uint256 internal constant Vault__InvalidLiquidation = 31029; /// @notice thrown when msg.value is sent wrong in rebalance uint256 internal constant Vault__InvalidMsgValueInRebalance = 31030; /// @notice thrown when nothing rebalanced uint256 internal constant Vault__NothingToRebalance = 31031; /// @notice thrown on unforseen liquidation scenarios. Might never come in use. uint256 internal constant Vault__LiquidationReverts = 31032; /// @notice thrown when oracle price is > 1e54 uint256 internal constant Vault__InvalidOraclePrice = 31033; /// @notice thrown when constants are not set properly via contructor uint256 internal constant Vault__ImproperConstantsSetup = 31034; /// @notice thrown when externally calling fetchLatestPosition function uint256 internal constant Vault__FetchLatestPositionFailed = 31035; /// @notice thrown when dex callback is not from dex uint256 internal constant Vault__InvalidDexCallbackAddress = 31036; /// @notice thrown when dex callback is already set uint256 internal constant Vault__DexFromAddressAlreadySet = 31037; /// @notice thrown when an invalid min / max amounts config is passed to rebalance() uint256 internal constant Vault__InvalidMinMaxInRebalance = 31038; /***********************************| | ERC721 | |__________________________________*/ uint256 internal constant ERC721__InvalidParams = 32001; uint256 internal constant ERC721__Unauthorized = 32002; uint256 internal constant ERC721__InvalidOperation = 32003; uint256 internal constant ERC721__UnsafeRecipient = 32004; uint256 internal constant ERC721__OutOfBoundsIndex = 32005; /***********************************| | Vault Admin | |__________________________________*/ /// @notice thrown when admin tries to setup invalid value which are crossing limits uint256 internal constant VaultAdmin__ValueAboveLimit = 33001; /// @notice when someone directly calls admin implementation contract uint256 internal constant VaultAdmin__OnlyDelegateCallAllowed = 33002; /// @notice thrown when auth sends NFT ID as 0 while collecting dust debt uint256 internal constant VaultAdmin__NftIdShouldBeNonZero = 33003; /// @notice thrown when trying to collect dust debt of NFT which is not of this vault uint256 internal constant VaultAdmin__NftNotOfThisVault = 33004; /// @notice thrown when dust debt of NFT is 0, meaning nothing to collect uint256 internal constant VaultAdmin__DustDebtIsZero = 33005; /// @notice thrown when final debt after liquidation is not 0, meaning position 100% liquidated uint256 internal constant VaultAdmin__FinalDebtShouldBeZero = 33006; /// @notice thrown when NFT is not liquidated state uint256 internal constant VaultAdmin__NftNotLiquidated = 33007; /// @notice thrown when total absorbed dust debt is 0 uint256 internal constant VaultAdmin__AbsorbedDustDebtIsZero = 33008; /// @notice thrown when address is set as 0 uint256 internal constant VaultAdmin__AddressZeroNotAllowed = 33009; /***********************************| | Vault Rewards | |__________________________________*/ uint256 internal constant VaultRewards__Unauthorized = 34001; uint256 internal constant VaultRewards__AddressZero = 34002; uint256 internal constant VaultRewards__InvalidParams = 34003; uint256 internal constant VaultRewards__NewMagnifierSameAsOldMagnifier = 34004; uint256 internal constant VaultRewards__NotTheInitiator = 34005; uint256 internal constant VaultRewards__NotTheGovernance = 34006; uint256 internal constant VaultRewards__AlreadyStarted = 34007; uint256 internal constant VaultRewards__RewardsNotStartedOrEnded = 34008; uint256 internal constant VaultRewards__InvalidStartTime = 34009; uint256 internal constant VaultRewards__AlreadyEnded = 34010; /***********************************| | Vault DEX Types | |__________________________________*/ uint256 internal constant VaultDex__InvalidOperateAmount = 35001; uint256 internal constant VaultDex__DebtSharesPaidMoreThanAvailableLiquidation = 35002; /***********************************| | Vault Borrow Rewards | |__________________________________*/ uint256 internal constant VaultBorrowRewards__Unauthorized = 36001; uint256 internal constant VaultBorrowRewards__AddressZero = 36002; uint256 internal constant VaultBorrowRewards__InvalidParams = 36003; uint256 internal constant VaultBorrowRewards__NewMagnifierSameAsOldMagnifier = 36004; uint256 internal constant VaultBorrowRewards__NotTheInitiator = 36005; uint256 internal constant VaultBorrowRewards__NotTheGovernance = 36006; uint256 internal constant VaultBorrowRewards__AlreadyStarted = 36007; uint256 internal constant VaultBorrowRewards__RewardsNotStartedOrEnded = 36008; uint256 internal constant VaultBorrowRewards__InvalidStartTime = 36009; uint256 internal constant VaultBorrowRewards__AlreadyEnded = 36010; }
//SPDX-License-Identifier: MIT pragma solidity 0.8.21; interface IFluidVaultT1 { /// @notice returns the vault id function VAULT_ID() external view returns (uint256); /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key. function readFromStorage(bytes32 slot_) external view returns (uint256 result_); struct ConstantViews { address liquidity; address factory; address adminImplementation; address secondaryImplementation; address supplyToken; address borrowToken; uint8 supplyDecimals; uint8 borrowDecimals; uint vaultId; bytes32 liquiditySupplyExchangePriceSlot; bytes32 liquidityBorrowExchangePriceSlot; bytes32 liquidityUserSupplySlot; bytes32 liquidityUserBorrowSlot; } /// @notice returns all Vault constants function constantsView() external view returns (ConstantViews memory constantsView_); /// @notice fetches the latest user position after a liquidation function fetchLatestPosition( int256 positionTick_, uint256 positionTickId_, uint256 positionRawDebt_, uint256 tickData_ ) external view returns ( int256, // tick uint256, // raw debt uint256, // raw collateral uint256, // branchID_ uint256 // branchData_ ); /// @notice calculates the updated vault exchange prices function updateExchangePrices( uint256 vaultVariables2_ ) external view returns ( uint256 liqSupplyExPrice_, uint256 liqBorrowExPrice_, uint256 vaultSupplyExPrice_, uint256 vaultBorrowExPrice_ ); /// @notice calculates the updated vault exchange prices and writes them to storage function updateExchangePricesOnStorage() external returns ( uint256 liqSupplyExPrice_, uint256 liqBorrowExPrice_, uint256 vaultSupplyExPrice_, uint256 vaultBorrowExPrice_ ); /// @notice returns the liquidity contract address function LIQUIDITY() external view returns (address); function operate( uint256 nftId_, // if 0 then new position int256 newCol_, // if negative then withdraw int256 newDebt_, // if negative then payback address to_ // address at which the borrow & withdraw amount should go to. If address(0) then it'll go to msg.sender ) external payable returns ( uint256, // nftId_ int256, // final supply amount. if - then withdraw int256 // final borrow amount. if - then payback ); function liquidate( uint256 debtAmt_, uint256 colPerUnitDebt_, // min collateral needed per unit of debt in 1e18 address to_, bool absorb_ ) external payable returns (uint actualDebtAmt_, uint actualColAmt_); function absorb() external; function rebalance() external payable returns (int supplyAmt_, int borrowAmt_); error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; contract Events { /// @notice emitted when the supply rate magnifier config is updated event LogUpdateSupplyRateMagnifier(uint supplyRateMagnifier_); /// @notice emitted when the borrow rate magnifier config is updated event LogUpdateBorrowRateMagnifier(uint borrowRateMagnifier_); /// @notice emitted when the collateral factor config is updated event LogUpdateCollateralFactor(uint collateralFactor_); /// @notice emitted when the liquidation threshold config is updated event LogUpdateLiquidationThreshold(uint liquidationThreshold_); /// @notice emitted when the liquidation max limit config is updated event LogUpdateLiquidationMaxLimit(uint liquidationMaxLimit_); /// @notice emitted when the withdrawal gap config is updated event LogUpdateWithdrawGap(uint withdrawGap_); /// @notice emitted when the liquidation penalty config is updated event LogUpdateLiquidationPenalty(uint liquidationPenalty_); /// @notice emitted when the borrow fee config is updated event LogUpdateBorrowFee(uint borrowFee_); /// @notice emitted when the core setting configs are updated event LogUpdateCoreSettings( uint supplyRateMagnifier_, uint borrowRateMagnifier_, uint collateralFactor_, uint liquidationThreshold_, uint liquidationMaxLimit_, uint withdrawGap_, uint liquidationPenalty_, uint borrowFee_ ); /// @notice emitted when the oracle is updated event LogUpdateOracle(address indexed newOracle_); /// @notice emitted when the allowed rebalancer is updated event LogUpdateRebalancer(address indexed newRebalancer_); /// @notice emitted when funds are rescued event LogRescueFunds(address indexed token_); /// @notice emitted when dust debt is absorbed for `nftIds_` event LogAbsorbDustDebt(uint256[] nftIds_, uint256 absorbedDustDebt_); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.21; contract Variables { /***********************************| | Storage Variables | |__________________________________*/ /// note: in all variables. For tick >= 0 are represented with bit as 1, tick < 0 are represented with bit as 0 /// note: read all the variables through storageRead.sol /// note: vaultVariables contains vault variables which need regular updates through transactions /// First 1 bit => 0 => re-entrancy. If 0 then allow transaction to go, else throw. /// Next 1 bit => 1 => Is the current active branch liquidated? If true then check the branch's minima tick before creating a new position /// If the new tick is greater than minima tick then initialize a new branch, make that as current branch & do proper linking /// Next 1 bit => 2 => sign of topmost tick (0 -> negative; 1 -> positive) /// Next 19 bits => 3-21 => absolute value of topmost tick /// Next 30 bits => 22-51 => current branch ID /// Next 30 bits => 52-81 => total branch ID /// Next 64 bits => 82-145 => Total supply /// Next 64 bits => 146-209 => Total borrow /// Next 32 bits => 210-241 => Total positions uint256 internal vaultVariables; /// note: vaultVariables2 contains variables which do not update on every transaction. So mainly admin/auth set amount /// First 16 bits => 0-15 => supply rate magnifier; 10000 = 1x (Here 16 bits should be more than enough) /// Next 16 bits => 16-31 => borrow rate magnifier; 10000 = 1x (Here 16 bits should be more than enough) /// Next 10 bits => 32-41 => collateral factor. 800 = 0.8 = 80% (max precision of 0.1%) /// Next 10 bits => 42-51 => liquidation Threshold. 900 = 0.9 = 90% (max precision of 0.1%) /// Next 10 bits => 52-61 => liquidation Max Limit. 950 = 0.95 = 95% (max precision of 0.1%) (above this 100% liquidation can happen) /// Next 10 bits => 62-71 => withdraw gap. 100 = 0.1 = 10%. (max precision of 0.1%) (max 7 bits can also suffice for the requirement here of 0.1% to 10%). Needed to save some limits on withdrawals so liquidate can work seamlessly. /// Next 10 bits => 72-81 => liquidation penalty. 100 = 0.01 = 1%. (max precision of 0.01%) (max liquidation penantly can be 10.23%). Applies when tick is in between liquidation Threshold & liquidation Max Limit. /// Next 10 bits => 82-91 => borrow fee. 100 = 0.01 = 1%. (max precision of 0.01%) (max borrow fee can be 10.23%). Fees on borrow. /// Next 4 bits => 92-95 => empty /// Next 160 bits => 96-255 => Oracle address uint256 internal vaultVariables2; /// note: stores absorbed liquidity /// First 128 bits raw debt amount /// last 128 bits raw col amount uint256 internal absorbedLiquidity; /// position index => position data uint /// if the entire variable is 0 (meaning not initialized) at the start that means no position at all /// First 1 bit => 0 => position type (0 => borrow position; 1 => supply position) /// Next 1 bit => 1 => sign of user's tick (0 => negative; 1 => positive) /// Next 19 bits => 2-20 => absolute value of user's tick /// Next 24 bits => 21-44 => user's tick's id /// Below we are storing user's collateral & not debt, because the position can also be only collateral with no tick but it can never be only debt /// Next 64 bits => 45-108 => user's supply amount. Debt will be calculated through supply & ratio. /// Next 64 bits => 109-172 => user's dust debt amount. User's net debt = total debt - dust amount. Total debt is calculated through supply & ratio /// User won't pay any extra interest on dust debt & hence we will not show it as a debt on UI. For user's there's no dust. mapping(uint256 => uint256) internal positionData; /// Tick has debt only keeps data of non liquidated positions. liquidated tick's data stays in branch itself /// tick parent => uint (represents bool for 256 children) /// parent of (i)th tick:- /// if (i>=0) (i / 256); /// else ((i + 1) / 256) - 1 /// first bit of the variable is the smallest tick & last bit is the biggest tick of that slot mapping(int256 => uint256) internal tickHasDebt; /// mapping tickId => tickData /// Tick related data. Total debt & other things /// First bit => 0 => If 1 then liquidated else not liquidated /// Next 24 bits => 1-24 => Total IDs. ID should start from 1. /// If not liquidated: /// Next 64 bits => 25-88 => raw debt /// If liquidated /// The below 3 things are of last ID. This is to be updated when user creates a new position /// Next 1 bit => 25 => Is 100% liquidated? If this is 1 meaning it was above max tick when it got liquidated (100% liquidated) /// Next 30 bits => 26-55 => branch ID where this tick got liquidated /// Next 50 bits => 56-105 => debt factor 50 bits (35 bits coefficient | 15 bits expansion) mapping(int256 => uint256) internal tickData; /// tick id => previous tick id liquidation data. ID starts from 1 /// One tick ID contains 3 IDs of 80 bits in it, holding liquidation data of previously active but liquidated ticks /// 81 bits data below /// #### First 85 bits #### /// 1st bit => 0 => Is 100% liquidated? If this is 1 meaning it was above max tick when it got liquidated /// Next 30 bits => 1-30 => branch ID where this tick got liquidated /// Next 50 bits => 31-80 => debt factor 50 bits (35 bits coefficient | 15 bits expansion) /// #### Second 85 bits #### /// 85th bit => 85 => Is 100% liquidated? If this is 1 meaning it was above max tick when it got liquidated /// Next 30 bits => 86-115 => branch ID where this tick got liquidated /// Next 50 bits => 116-165 => debt factor 50 bits (35 bits coefficient | 15 bits expansion) /// #### Third 85 bits #### /// 170th bit => 170 => Is 100% liquidated? If this is 1 meaning it was above max tick when it got liquidated /// Next 30 bits => 171-200 => branch ID where this tick got liquidated /// Next 50 bits => 201-250 => debt factor 50 bits (35 bits coefficient | 15 bits expansion) mapping(int256 => mapping(uint256 => uint256)) internal tickId; /// mapping branchId => branchData /// First 2 bits => 0-1 => if 0 then not liquidated, if 1 then liquidated, if 2 then merged, if 3 then closed /// merged means the branch is merged into it's base branch /// closed means all the users are 100% liquidated /// Next 1 bit => 2 => minima tick sign of this branch. Will only be there if any liquidation happened. /// Next 19 bits => 3-21 => minima tick of this branch. Will only be there if any liquidation happened. /// Next 30 bits => 22-51 => Partials of minima tick of branch this is connected to. 0 if master branch. /// Next 64 bits => 52-115 Debt liquidity at this branch. Similar to last's top tick data. Remaining debt will move here from tickData after first liquidation /// If not merged /// Next 50 bits => 116-165 => Debt factor or of this branch. (35 bits coefficient | 15 bits expansion) /// If merged /// Next 50 bits => 116-165 => Connection/adjustment debt factor of this branch with the next branch. /// If closed /// Next 50 bits => 116-165 => Debt factor as 0. As all the user's positions are now fully gone /// following values are present always again (merged / not merged / closed) /// Next 30 bits => 166-195 => Branch's ID with which this branch is connected. If 0 then that means this is the master branch /// Next 1 bit => 196 => sign of minima tick of branch this is connected to. 0 if master branch. /// Next 19 bits => 197-215 => minima tick of branch this is connected to. 0 if master branch. mapping(uint256 => uint256) internal branchData; /// Exchange prices are in 1e12 /// First 64 bits => 0-63 => Liquidity's collateral token supply exchange price /// First 64 bits => 64-127 => Liquidity's debt token borrow exchange price /// First 64 bits => 128-191 => Vault's collateral token supply exchange price /// First 64 bits => 192-255 => Vault's debt token borrow exchange price uint256 internal rates; /// address of rebalancer address internal rebalancer; uint256 internal absorbedDustDebt; }
{ "optimizer": { "enabled": true, "runs": 10000000 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"colLiquidated","type":"uint256"},{"internalType":"uint256","name":"debtLiquidated","type":"uint256"}],"name":"FluidLiquidateResult","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorId_","type":"uint256"}],"name":"FluidSafeTransferError","type":"error"},{"inputs":[{"internalType":"uint256","name":"errorId_","type":"uint256"}],"name":"FluidVaultError","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"nftIds_","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"absorbedDustDebt_","type":"uint256"}],"name":"LogAbsorbDustDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token_","type":"address"}],"name":"LogRescueFunds","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"borrowFee_","type":"uint256"}],"name":"LogUpdateBorrowFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"borrowRateMagnifier_","type":"uint256"}],"name":"LogUpdateBorrowRateMagnifier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"collateralFactor_","type":"uint256"}],"name":"LogUpdateCollateralFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"supplyRateMagnifier_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowRateMagnifier_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralFactor_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationThreshold_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationMaxLimit_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"withdrawGap_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationPenalty_","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"borrowFee_","type":"uint256"}],"name":"LogUpdateCoreSettings","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"liquidationMaxLimit_","type":"uint256"}],"name":"LogUpdateLiquidationMaxLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"liquidationPenalty_","type":"uint256"}],"name":"LogUpdateLiquidationPenalty","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"liquidationThreshold_","type":"uint256"}],"name":"LogUpdateLiquidationThreshold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOracle_","type":"address"}],"name":"LogUpdateOracle","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newRebalancer_","type":"address"}],"name":"LogUpdateRebalancer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"supplyRateMagnifier_","type":"uint256"}],"name":"LogUpdateSupplyRateMagnifier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"withdrawGap_","type":"uint256"}],"name":"LogUpdateWithdrawGap","type":"event"},{"inputs":[{"internalType":"uint256[]","name":"nftIds_","type":"uint256[]"}],"name":"absorbDustDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"borrowFee_","type":"uint256"}],"name":"updateBorrowFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"borrowRateMagnifier_","type":"uint256"}],"name":"updateBorrowRateMagnifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"collateralFactor_","type":"uint256"}],"name":"updateCollateralFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"supplyRateMagnifier_","type":"uint256"},{"internalType":"uint256","name":"borrowRateMagnifier_","type":"uint256"},{"internalType":"uint256","name":"collateralFactor_","type":"uint256"},{"internalType":"uint256","name":"liquidationThreshold_","type":"uint256"},{"internalType":"uint256","name":"liquidationMaxLimit_","type":"uint256"},{"internalType":"uint256","name":"withdrawGap_","type":"uint256"},{"internalType":"uint256","name":"liquidationPenalty_","type":"uint256"},{"internalType":"uint256","name":"borrowFee_","type":"uint256"}],"name":"updateCoreSettings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidationMaxLimit_","type":"uint256"}],"name":"updateLiquidationMaxLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidationPenalty_","type":"uint256"}],"name":"updateLiquidationPenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidationThreshold_","type":"uint256"}],"name":"updateLiquidationThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOracle_","type":"address"}],"name":"updateOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newRebalancer_","type":"address"}],"name":"updateRebalancer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"supplyRateMagnifier_","type":"uint256"}],"name":"updateSupplyRateMagnifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"withdrawGap_","type":"uint256"}],"name":"updateWithdrawGap","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b5030608052608051612499610084600039600081816102680152818161040a015281816105c40152818161074d015281816108ee01528181610b6101528181610d0c01528181610ec001528181611069015281816111f90152818161133c015281816117e90152611ad401526124996000f3fe608060405234801561001057600080fd5b50600436106100df5760003560e01c8063898e96281161008c578063d3b5be1a11610066578063d3b5be1a14610191578063d61b93fe146101a4578063e53b2017146101b7578063f7a0a7e0146101ca57600080fd5b8063898e962814610158578063b046a4491461016b578063b8244f5f1461017e57600080fd5b8063509c21a4116100bd578063509c21a41461011f57806354b04ef51461013257806357917a111461014557600080fd5b806303f9923c146100e45780631cb44dfc146100f95780634a138a711461010c575b600080fd5b6100f76100f23660046120ac565b6101dd565b005b6100f76101073660046120ea565b61037f565b6100f761011a3660046120ac565b610539565b6100f761012d3660046120ac565b6106c2565b6100f761014036600461210e565b610863565b6100f76101533660046120ac565b610ad6565b6100f76101663660046120ac565b610c81565b6100f76101793660046120ea565b610e35565b6100f761018c3660046120ac565b610fde565b6100f761019f3660046120ac565b61116e565b6100f76101b2366004612192565b611325565b6100f76101c53660046120ea565b6117d2565b6100f76101d83660046120ac565b611a49565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af115801561022a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024e919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016300390506102cb576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024015b60405180910390fd5b6040518181527fba3aefe95d9bb126dd0e7885e76f453e72b0ee6efd457771f26fe0a7ca56cedc9060200160405180910390a1610309600a826122d3565b90506103e881111561034b576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b603e81901b6001547fffffffffffffffffffffffffffffffffffffffffffffff003fffffffffffffff161760018190555050565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af11580156103cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f0919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630039050610468576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b73ffffffffffffffffffffffffffffffffffffffff81166104b9576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180f160048201526024016102c2565b600180546bffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084901b1617905560405173ffffffffffffffffffffffffffffffffffffffff8216907f7a46205dbf7cc57a79f474f580e08d7961ad634e14643486b8df2dc30c392b6290600090a250565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015610586573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105aa919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630039050610622576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f06f8b08c94d657867f843433de70bed3628bbdc19b0c89413af75d30420ad3f39060200160405180910390a161ffff811115610695576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169091179055565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af115801561070f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610733919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016300390506107ab576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f0e8160f7246256e8f7eea7dc5ee9de8c9fa1d6057c30561f548e6a84defeef159060200160405180910390a1600154602a81901c6103ff166107f5600a846122d3565b9250808310610834576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b507ffffffffffffffffffffffffffffffffffffffffffffffffffffffc00ffffffff1660209190911b17600155565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af11580156108b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d4919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003905061094c576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040805189815260208101899052908101879052606081018690526080810185905260a0810184905260c0810183905260e081018290527ff992c18e9b1aec434f456c32a556717f76f0f19cba16d430d4ba1be0813ab3e8906101000160405180910390a16109bb8483611bd9565b6109c6600a876122d3565b95506109d3600a866122d3565b94506109e0600a856122d3565b93506109ed600a846122d3565b925061ffff881180610a00575061ffff87115b80610a0b5750848610155b80610a165750838510155b80610a2257506103ff83115b80610a2e57506103ff82115b80610a3a57506103ff81115b15610a75576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b605281901b604883901b603e85901b603487901b602a89901b60208b901b60108d901b8e6001547ffffffffffffffffffffffffffffffffffffffffff000000000000000000000001617171717171717176001819055505050505050505050565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b47919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630039050610bbf576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527fd3d6bb99321a653b7fc969c9f2a1917bd9623cab8ecaa67a2e1bec34c3eb2e1c9060200160405180910390a1600154603481901c6103ff16610c12610c0c82600a61230e565b84611bd9565b6103ff831115610c52576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b507ffffffffffffffffffffffffffffffffffffffffffffc00ffffffffffffffffff1660489190911b17600155565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015610cce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf2919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630039050610d6a576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f5ac1492eb2009d4983693cc59b4ec4032b506a0f9cbefc19a7545af5945d26af9060200160405180910390a16001546103ff602a82901c811690604883901c16610dbb8482611bd9565b610dc6600a856122d3565b9350838210610e05576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b50507fffffffffffffffffffffffffffffffffffffffffffffffffc00fffffffffffff1660349190911b17600155565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015610e82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea6919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630039050610f1e576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b73ffffffffffffffffffffffffffffffffffffffff8116610f6f576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180f160048201526024016102c2565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fdb94ee7fd8b5bbf8f6d59e76731ff4b4f5a02ab3af1d3e0c774862cf96ff613b90600090a250565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af115801561102b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104f919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016300390506110c7576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f06a28e5e1500bd478bd28b400a0fb46a9cc8748a5dac616b38bc91c29462c17f9060200160405180910390a16103ff81111561113a576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b605281901b6001547ffffffffffffffffffffffffffffffffffffffffff003ffffffffffffffffffff161760018190555050565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af11580156111bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111df919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630039050611257576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f44a667dd6218a52f7ef808da1e39e9c8497db215eaff093c0c42ecf9bf2168f39060200160405180910390a16001546103ff602082901c811690603483901c166112a9600a856122d3565b935083821015806112ba5750808410155b156112f5576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b50507ffffffffffffffffffffffffffffffffffffffffffffffffffff003ffffffffff16602a9190911b17600155565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003611398576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b60008054906001821690036113b357600181176000556113e9565b6040517f60121cca00000000000000000000000000000000000000000000000000000000815261791960048201526024016102c2565b6000806000806000806000806000600a54905060005b8b518110156116e5578b818151811061141a5761141a61232b565b6020026020010151995089600003611462576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180eb60048201526024016102c2565b60008a81526003602052604081205499508990036114b0576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ec60048201526024016102c2565b67ffffffffffffffff602d8a901c16955060ff8616600887901c901b955067ffffffffffffffff606d8a901c16935060ff8416600885901c901b93508360000361152a576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ed60048201526024016102c2565b8860021660021461154c5761154760028a901c6207ffff1661235a565b611557565b6207ffff60028a901c165b975062ffffff60158a901c1696506060866115748a60020b611c26565b61157e919061230e565b60008a815260056020526040902054911c95509250600180841614806115ac57508662ffffff600185901c16115b156116a7576040517f22348cc70000000000000000000000000000000000000000000000000000000081526004810189905260248101889052604481018690526064810184905230906322348cc79060840160a060405180830381865afa15801561161b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163f9190612392565b5091975050861591506116849050576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ee60048201526024016102c2565b61168e84836123d2565b60008b81526003602052604090206001905591506116dd565b6040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ef60048201526024016102c2565b6001016113ff565b5080600003611724576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180f060048201526024016102c2565b66ffffffffffffff609a8b901c1660ff60928c901c161b61174582826123d2565b905061175681603860086001611e88565b7ffffffffffffc0000000000000003ffffffffffffffffffffffffffffffffffff8c16609282901b176000908155600a556040519091507fae8abcd7cc16d6da9fa7098d41cc4cdb3bd5ce892e46f15d904b44c9b156cb5e906117bc908e9085906123e5565b60405180910390a1505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003611845576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016118ff576118fa3073ffffffffffffffffffffffffffffffffffffffff16632861c7d16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f4919061242d565b47611fb1565b611a05565b611a05813073ffffffffffffffffffffffffffffffffffffffff16632861c7d16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561194e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611972919061242d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156119dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a00919061244a565b612002565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fdff2a3947bcf9fc0807b142e7c8497066db9183428b7bdbfb1fcd0f55c27a3df90600090a250565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015611a96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aba919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630039050611b32576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f8d6a11b15739c2d7a6d0a69b9d322262db8c1fb2e4b96239e4e4733df8a5164e9060200160405180910390a161ffff811115611ba5576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b601081901b6001547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff161760018190555050565b6126f2611be682846123d2565b1115611c22576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b5050565b600060ff82901d80831803617fff811115611c4057600080fd5b7001000000000000000000000000000000006001821615611c6e57506fff9dd7de423466c20352b1246ce4856f5b6002821615611c8d576fff3bd55f4488ad277531fa1c725a66d00260801c5b6004821615611cac576ffe78410fd6498b73cb96a6917f8532590260801c5b6008821615611ccb576ffcf2d9987c9be178ad5bfeffaa1232730260801c5b6010821615611cea576ff9ef02c4529258b057769680fc6601b30260801c5b6020821615611d09576ff402d288133a85a17784a411f7aba0820260801c5b6040821615611d28576fe895615b5beb6386553757b0352bda900260801c5b6080821615611d47576fd34f17a00ffa00a8309940a15930391a0260801c5b610100821615611d67576fae6b7961714e20548d88ea5123f9a0ff0260801c5b610200821615611d87576f76d6461f27082d74e0feed3b388c0ca10260801c5b610400821615611da7576f372a3bfe0745d8b6b19d985d9a8b85bb0260801c5b610800821615611dc7576f0be32cbee48979763cf7247dd7bb539d0260801c5b611000821615611de6576e8d4f70c9ff4924dac37612d1e2921e0260801c5b612000821615611e04576d4e009ae5519380809a02ca7aec770260801c5b614000821615611e20576b17c45e641b6e95dee056ff100260801c5b600091507f80000000000000000000000000000000000000000000000000000000000000008416611e7e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0463ffffffff811615611e7e57600191505b60201c0192915050565b600080856fffffffffffffffffffffffffffffffff811115611eab5760809150811c5b67ffffffffffffffff811115611ec3576040918201911c5b63ffffffff811115611ed7576020918201911c5b61ffff811115611ee9576010918201911c5b60ff811115611efa576008918201911c5b600f811115611f0b576004918201911c5b6003811115611f1c576002918201911c5b6001811115611f2c576001820191505b8015611f39576001820191505b5084811015611f455750835b848103905085811c60008211841615611f9457600181019050806001871b03611f9457506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210611fa357600080fd5b90931b909201949350505050565b60008060008060008587614e20f1905080611ffd576040517fdee51a8a0000000000000000000000000000000000000000000000000000000081526201155a60048201526024016102c2565b505050565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806120a6576040517fdee51a8a0000000000000000000000000000000000000000000000000000000081526201155a60048201526024016102c2565b50505050565b6000602082840312156120be57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146120e757600080fd5b50565b6000602082840312156120fc57600080fd5b8135612107816120c5565b9392505050565b600080600080600080600080610100898b03121561212b57600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208083850312156121a557600080fd5b823567ffffffffffffffff808211156121bd57600080fd5b818501915085601f8301126121d157600080fd5b8135818111156121e3576121e3612163565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561222657612226612163565b60405291825284820192508381018501918883111561224457600080fd5b938501935b8285101561226257843584529385019392850192612249565b98975050505050505050565b6000806000806080858703121561228457600080fd5b505082516020840151604085015160609095015191969095509092509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082612309577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8082028115828204841417612325576123256122a4565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007f8000000000000000000000000000000000000000000000000000000000000000820361238b5761238b6122a4565b5060000390565b600080600080600060a086880312156123aa57600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b80820180821115612325576123256122a4565b604080825283519082018190526000906020906060840190828701845b8281101561241e57815184529284019290840190600101612402565b50505092019290925292915050565b60006020828403121561243f57600080fd5b8151612107816120c5565b60006020828403121561245c57600080fd5b505191905056fea2646970667358221220abda92e80f4f45bce3a5a9e55e518168f660e26cb37f41c35ecab91bc460d1fb64736f6c63430008150033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100df5760003560e01c8063898e96281161008c578063d3b5be1a11610066578063d3b5be1a14610191578063d61b93fe146101a4578063e53b2017146101b7578063f7a0a7e0146101ca57600080fd5b8063898e962814610158578063b046a4491461016b578063b8244f5f1461017e57600080fd5b8063509c21a4116100bd578063509c21a41461011f57806354b04ef51461013257806357917a111461014557600080fd5b806303f9923c146100e45780631cb44dfc146100f95780634a138a711461010c575b600080fd5b6100f76100f23660046120ac565b6101dd565b005b6100f76101073660046120ea565b61037f565b6100f761011a3660046120ac565b610539565b6100f761012d3660046120ac565b6106c2565b6100f761014036600461210e565b610863565b6100f76101533660046120ac565b610ad6565b6100f76101663660046120ac565b610c81565b6100f76101793660046120ea565b610e35565b6100f761018c3660046120ac565b610fde565b6100f761019f3660046120ac565b61116e565b6100f76101b2366004612192565b611325565b6100f76101c53660046120ea565b6117d2565b6100f76101d83660046120ac565b611a49565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af115801561022a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061024e919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b16300390506102cb576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024015b60405180910390fd5b6040518181527fba3aefe95d9bb126dd0e7885e76f453e72b0ee6efd457771f26fe0a7ca56cedc9060200160405180910390a1610309600a826122d3565b90506103e881111561034b576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b603e81901b6001547fffffffffffffffffffffffffffffffffffffffffffffff003fffffffffffffff161760018190555050565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af11580156103cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f0919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b1630039050610468576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b73ffffffffffffffffffffffffffffffffffffffff81166104b9576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180f160048201526024016102c2565b600180546bffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084901b1617905560405173ffffffffffffffffffffffffffffffffffffffff8216907f7a46205dbf7cc57a79f474f580e08d7961ad634e14643486b8df2dc30c392b6290600090a250565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015610586573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105aa919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b1630039050610622576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f06f8b08c94d657867f843433de70bed3628bbdc19b0c89413af75d30420ad3f39060200160405180910390a161ffff811115610695576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b600180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169091179055565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af115801561070f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610733919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b16300390506107ab576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f0e8160f7246256e8f7eea7dc5ee9de8c9fa1d6057c30561f548e6a84defeef159060200160405180910390a1600154602a81901c6103ff166107f5600a846122d3565b9250808310610834576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b507ffffffffffffffffffffffffffffffffffffffffffffffffffffffc00ffffffff1660209190911b17600155565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af11580156108b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d4919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b163003905061094c576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040805189815260208101899052908101879052606081018690526080810185905260a0810184905260c0810183905260e081018290527ff992c18e9b1aec434f456c32a556717f76f0f19cba16d430d4ba1be0813ab3e8906101000160405180910390a16109bb8483611bd9565b6109c6600a876122d3565b95506109d3600a866122d3565b94506109e0600a856122d3565b93506109ed600a846122d3565b925061ffff881180610a00575061ffff87115b80610a0b5750848610155b80610a165750838510155b80610a2257506103ff83115b80610a2e57506103ff82115b80610a3a57506103ff81115b15610a75576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b605281901b604883901b603e85901b603487901b602a89901b60208b901b60108d901b8e6001547ffffffffffffffffffffffffffffffffffffffffff000000000000000000000001617171717171717176001819055505050505050505050565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015610b23573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b47919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b1630039050610bbf576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527fd3d6bb99321a653b7fc969c9f2a1917bd9623cab8ecaa67a2e1bec34c3eb2e1c9060200160405180910390a1600154603481901c6103ff16610c12610c0c82600a61230e565b84611bd9565b6103ff831115610c52576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b507ffffffffffffffffffffffffffffffffffffffffffffc00ffffffffffffffffff1660489190911b17600155565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015610cce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf2919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b1630039050610d6a576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f5ac1492eb2009d4983693cc59b4ec4032b506a0f9cbefc19a7545af5945d26af9060200160405180910390a16001546103ff602a82901c811690604883901c16610dbb8482611bd9565b610dc6600a856122d3565b9350838210610e05576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b50507fffffffffffffffffffffffffffffffffffffffffffffffffc00fffffffffffff1660349190911b17600155565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015610e82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea6919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b1630039050610f1e576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b73ffffffffffffffffffffffffffffffffffffffff8116610f6f576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180f160048201526024016102c2565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517fdb94ee7fd8b5bbf8f6d59e76731ff4b4f5a02ab3af1d3e0c774862cf96ff613b90600090a250565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af115801561102b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104f919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b16300390506110c7576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f06a28e5e1500bd478bd28b400a0fb46a9cc8748a5dac616b38bc91c29462c17f9060200160405180910390a16103ff81111561113a576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b605281901b6001547ffffffffffffffffffffffffffffffffffffffffff003ffffffffffffffffffff161760018190555050565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af11580156111bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111df919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b1630039050611257576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f44a667dd6218a52f7ef808da1e39e9c8497db215eaff093c0c42ecf9bf2168f39060200160405180910390a16001546103ff602082901c811690603483901c166112a9600a856122d3565b935083821015806112ba5750808410155b156112f5576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b50507ffffffffffffffffffffffffffffffffffffffffffffffffffff003ffffffffff16602a9190911b17600155565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b163003611398576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b60008054906001821690036113b357600181176000556113e9565b6040517f60121cca00000000000000000000000000000000000000000000000000000000815261791960048201526024016102c2565b6000806000806000806000806000600a54905060005b8b518110156116e5578b818151811061141a5761141a61232b565b6020026020010151995089600003611462576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180eb60048201526024016102c2565b60008a81526003602052604081205499508990036114b0576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ec60048201526024016102c2565b67ffffffffffffffff602d8a901c16955060ff8616600887901c901b955067ffffffffffffffff606d8a901c16935060ff8416600885901c901b93508360000361152a576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ed60048201526024016102c2565b8860021660021461154c5761154760028a901c6207ffff1661235a565b611557565b6207ffff60028a901c165b975062ffffff60158a901c1696506060866115748a60020b611c26565b61157e919061230e565b60008a815260056020526040902054911c95509250600180841614806115ac57508662ffffff600185901c16115b156116a7576040517f22348cc70000000000000000000000000000000000000000000000000000000081526004810189905260248101889052604481018690526064810184905230906322348cc79060840160a060405180830381865afa15801561161b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163f9190612392565b5091975050861591506116849050576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ee60048201526024016102c2565b61168e84836123d2565b60008b81526003602052604090206001905591506116dd565b6040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ef60048201526024016102c2565b6001016113ff565b5080600003611724576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180f060048201526024016102c2565b66ffffffffffffff609a8b901c1660ff60928c901c161b61174582826123d2565b905061175681603860086001611e88565b7ffffffffffffc0000000000000003ffffffffffffffffffffffffffffffffffff8c16609282901b176000908155600a556040519091507fae8abcd7cc16d6da9fa7098d41cc4cdb3bd5ce892e46f15d904b44c9b156cb5e906117bc908e9085906123e5565b60405180910390a1505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b163003611845576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8216016118ff576118fa3073ffffffffffffffffffffffffffffffffffffffff16632861c7d16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118f4919061242d565b47611fb1565b611a05565b611a05813073ffffffffffffffffffffffffffffffffffffffff16632861c7d16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561194e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611972919061242d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156119dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a00919061244a565b612002565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fdff2a3947bcf9fc0807b142e7c8497066db9183428b7bdbfb1fcd0f55c27a3df90600090a250565b3073ffffffffffffffffffffffffffffffffffffffff1663021618876040518163ffffffff1660e01b81526004016080604051808303816000875af1158015611a96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aba919061226e565b50505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000071f177e42cbabad75d1393e485b60fec8e815f3b1630039050611b32576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180ea60048201526024016102c2565b6040518181527f8d6a11b15739c2d7a6d0a69b9d322262db8c1fb2e4b96239e4e4733df8a5164e9060200160405180910390a161ffff811115611ba5576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b601081901b6001547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff161760018190555050565b6126f2611be682846123d2565b1115611c22576040517f60121cca0000000000000000000000000000000000000000000000000000000081526180e960048201526024016102c2565b5050565b600060ff82901d80831803617fff811115611c4057600080fd5b7001000000000000000000000000000000006001821615611c6e57506fff9dd7de423466c20352b1246ce4856f5b6002821615611c8d576fff3bd55f4488ad277531fa1c725a66d00260801c5b6004821615611cac576ffe78410fd6498b73cb96a6917f8532590260801c5b6008821615611ccb576ffcf2d9987c9be178ad5bfeffaa1232730260801c5b6010821615611cea576ff9ef02c4529258b057769680fc6601b30260801c5b6020821615611d09576ff402d288133a85a17784a411f7aba0820260801c5b6040821615611d28576fe895615b5beb6386553757b0352bda900260801c5b6080821615611d47576fd34f17a00ffa00a8309940a15930391a0260801c5b610100821615611d67576fae6b7961714e20548d88ea5123f9a0ff0260801c5b610200821615611d87576f76d6461f27082d74e0feed3b388c0ca10260801c5b610400821615611da7576f372a3bfe0745d8b6b19d985d9a8b85bb0260801c5b610800821615611dc7576f0be32cbee48979763cf7247dd7bb539d0260801c5b611000821615611de6576e8d4f70c9ff4924dac37612d1e2921e0260801c5b612000821615611e04576d4e009ae5519380809a02ca7aec770260801c5b614000821615611e20576b17c45e641b6e95dee056ff100260801c5b600091507f80000000000000000000000000000000000000000000000000000000000000008416611e7e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0463ffffffff811615611e7e57600191505b60201c0192915050565b600080856fffffffffffffffffffffffffffffffff811115611eab5760809150811c5b67ffffffffffffffff811115611ec3576040918201911c5b63ffffffff811115611ed7576020918201911c5b61ffff811115611ee9576010918201911c5b60ff811115611efa576008918201911c5b600f811115611f0b576004918201911c5b6003811115611f1c576002918201911c5b6001811115611f2c576001820191505b8015611f39576001820191505b5084811015611f455750835b848103905085811c60008211841615611f9457600181019050806001871b03611f9457506001908101907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff86011b5b6001851b8210611fa357600080fd5b90931b909201949350505050565b60008060008060008587614e20f1905080611ffd576040517fdee51a8a0000000000000000000000000000000000000000000000000000000081526201155a60048201526024016102c2565b505050565b60006040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806120a6576040517fdee51a8a0000000000000000000000000000000000000000000000000000000081526201155a60048201526024016102c2565b50505050565b6000602082840312156120be57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146120e757600080fd5b50565b6000602082840312156120fc57600080fd5b8135612107816120c5565b9392505050565b600080600080600080600080610100898b03121561212b57600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208083850312156121a557600080fd5b823567ffffffffffffffff808211156121bd57600080fd5b818501915085601f8301126121d157600080fd5b8135818111156121e3576121e3612163565b8060051b6040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0603f8301168101818110858211171561222657612226612163565b60405291825284820192508381018501918883111561224457600080fd5b938501935b8285101561226257843584529385019392850192612249565b98975050505050505050565b6000806000806080858703121561228457600080fd5b505082516020840151604085015160609095015191969095509092509050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082612309577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b8082028115828204841417612325576123256122a4565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007f8000000000000000000000000000000000000000000000000000000000000000820361238b5761238b6122a4565b5060000390565b600080600080600060a086880312156123aa57600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b80820180821115612325576123256122a4565b604080825283519082018190526000906020906060840190828701845b8281101561241e57815184529284019290840190600101612402565b50505092019290925292915050565b60006020828403121561243f57600080fd5b8151612107816120c5565b60006020828403121561245c57600080fd5b505191905056fea2646970667358221220abda92e80f4f45bce3a5a9e55e518168f660e26cb37f41c35ecab91bc460d1fb64736f6c63430008150033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.