Source Code
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Liquidator
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-v3
pragma solidity 0.8.21;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@gammaswap/v1-core/contracts/interfaces/IPoolViewer.sol";
import "@gammaswap/v1-core/contracts/libraries/GSMath.sol";
import "./interfaces/ILiquidator.sol";
/// @title Liquidator Smart Contract
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Helps liquidation of loans in GammaPools
contract Liquidator is ILiquidator {
constructor(){
}
/// @dev See {ILiquidator-canLiquidate}.
function canLiquidate(address pool, uint256 tokenId) external override view returns(uint256 liquidity, uint256 collateral) {
return _canLiquidate(pool, tokenId);
}
function _canLiquidate(address pool, uint256 tokenId) internal virtual view returns(uint256 liquidity, uint256 collateral) {
IPoolViewer viewer = IPoolViewer(IGammaPool(pool).viewer());
if(viewer.canLiquidate(pool, tokenId)) {
IGammaPool.LoanData memory loan = viewer.loan(pool, tokenId);
liquidity = loan.liquidity;
collateral = GSMath.sqrt(uint256(loan.tokensHeld[0])*loan.tokensHeld[1]);
}
}
/// @dev See {ILiquidator-canBatchLiquidate}.
function canBatchLiquidate(address pool, uint256[] calldata tokenIds) external override virtual view returns(uint256[] memory _tokenIds, uint256 _liquidity, uint256 _collateral) {
return _canBatchLiquidate(pool, tokenIds);
}
function _canBatchLiquidate(address pool, uint256[] calldata tokenIds) internal virtual view returns(uint256[] memory _tokenIds, uint256 _liquidity, uint256 _collateral) {
IGammaPool.LoanData[] memory _loans = IPoolViewer(IGammaPool(pool).viewer()).getLoansById(pool, tokenIds, true);
uint256[] memory __tokenIds = new uint256[](_loans.length);
uint256 k = 0;
IGammaPool.LoanData memory _loan;
for(uint256 i = 0; i < _loans.length;) {
_loan = _loans[i];
if(_loan.id > 0) {
if(_loan.canLiquidate) {
__tokenIds[k] = _loan.tokenId;
_liquidity += _loan.liquidity;
_collateral += GSMath.sqrt(uint256(_loan.tokensHeld[0]) * _loan.tokensHeld[1]);
unchecked {
++k;
}
}
} else {
break;
}
unchecked {
++i;
}
}
_tokenIds = new uint256[](k);
for(uint256 j = 0; j < _tokenIds.length;) {
_tokenIds[j] = __tokenIds[j];
unchecked {
++j;
}
}
}
/// @dev See {ILiquidator-liquidate}.
function liquidate(address pool, uint256 tokenId, address to) external override virtual returns(uint256 refund) {
IPoolViewer viewer = IPoolViewer(IGammaPool(pool).viewer());
if(viewer.canLiquidate(pool, tokenId)) {
address cfmm = IGammaPool(pool).cfmm();
uint256 beforeBalance = IERC20(cfmm).balanceOf(address(this));
(,refund) = IGammaPool(pool).liquidate(tokenId);
uint256 afterBalance = IERC20(cfmm).balanceOf(address(this));
if(afterBalance > beforeBalance) {
IERC20(cfmm).transfer(to,afterBalance - beforeBalance);
}
}
}
/// @dev See {ILiquidator-calcLPTokenDebt}.
function calcLPTokenDebt(address pool, uint256 tokenId) external override virtual view returns(uint256 lpTokens) {
return _calcLPTokenDebt(pool, tokenId);
}
function _calcLPTokenDebt(address pool, uint256 tokenId) internal virtual view returns(uint256 lpTokens) {
IGammaPool.LoanData memory _loan = IPoolViewer(IGammaPool(pool).viewer()).loan(pool, tokenId);
lpTokens = _convertLiquidityToLPTokens(pool, _loan.liquidity);
}
/// @dev See {ILiquidator-liquidateWithLP}.
function liquidateWithLP(address pool, uint256 tokenId, uint256 lpTokens, bool calcLpTokens, address to) external override virtual returns(uint256[] memory refunds) {
//check can liquidate first
IPoolViewer viewer = IPoolViewer(IGammaPool(pool).viewer());
if(viewer.canLiquidate(pool, tokenId)){
if(calcLpTokens) {
lpTokens = _calcLPTokenDebt(pool, tokenId) * 10002 / 10000; // adding 0.02% to avoid rounding issues
}
// transfer CFMM LP Tokens
address cfmm = IGammaPool(pool).cfmm();
uint256 beforeBalance = IERC20(cfmm).balanceOf(address(this));
_transferLPTokensFrom(pool, lpTokens, msg.sender);
(,refunds) = IGammaPool(pool).liquidateWithLP(tokenId);
uint256 afterBalance = IERC20(cfmm).balanceOf(address(this));
_transferRefunds(pool, refunds, to);
if(afterBalance > beforeBalance) {
IERC20(cfmm).transfer(msg.sender,afterBalance - beforeBalance);
}
}
}
/// @dev See {ILiquidator-batchLiquidate}.
function batchLiquidate(address pool, uint256[] calldata tokenIds, address to) external override virtual returns(uint256[] memory _tokenIds, uint256[] memory refunds) {
//call canLiquidate first
uint256 _liquidity;
(_tokenIds, _liquidity,) = _canBatchLiquidate(pool, tokenIds);
if(_liquidity > 0) {
uint256 lpTokens = _convertLiquidityToLPTokens(pool, _liquidity) * 10002 / 10000;
address cfmm = IGammaPool(pool).cfmm();
uint256 beforeBalance = IERC20(cfmm).balanceOf(address(this));
// transfer CFMM LP Tokens
_transferLPTokensFrom(pool, lpTokens, msg.sender);
(,refunds) = IGammaPool(pool).batchLiquidations(_tokenIds);
uint256 afterBalance = IERC20(cfmm).balanceOf(address(this));
_transferRefunds(pool, refunds, to);
if(afterBalance > beforeBalance) {
IERC20(cfmm).transfer(msg.sender,afterBalance - beforeBalance);
}
}
}
/// @dev See {ILiquidator-getLoan}.
function getLoan(address pool, uint256 tokenId) external override virtual view returns(IGammaPool.LoanData memory loan) {
loan = IPoolViewer(IGammaPool(pool).viewer()).loan(pool, tokenId);
}
/// @dev See {ILiquidator-getLoans}.
function getLoans(address pool, uint256[] calldata tokenId, bool active) external override virtual view returns(IGammaPool.LoanData[] memory loans) {
loans = IGammaPool(pool).getLoansById(tokenId, active);
}
/// @dev See {ILiquidator-getOpenLoans}.
function getLoans(address pool, uint256 start, uint256 end, bool active) external override virtual view returns(IGammaPool.LoanData[] memory loans) {
loans = IGammaPool(pool).getLoans(start, end, active);
}
/// @dev See {ILiquidator-getOpenLoanIds}.
function getLoanIds(address pool, uint256 start, uint256 end, bool active) external override virtual view returns(uint256[] memory tokenIds) {
IGammaPool.LoanData[] memory loans = IGammaPool(pool).getLoans(start, end, active);
tokenIds = new uint256[](loans.length);
for(uint256 i = 0; i < loans.length;) {
tokenIds[i] = loans[i].tokenId;
unchecked {
++i;
}
}
}
/// @dev convert liquidity invariant units to LP tokens
/// @param pool - address of GammaPool for CFMM's liquidity
/// @param liquidity - liquidity invariant units to convert into CFMM LP tokens
/// @return lpTokens - CFMM LP tokens `liquidity` invariant units converts to
function _convertLiquidityToLPTokens(address pool, uint256 liquidity) internal virtual view returns(uint256 lpTokens) {
(, uint256 cfmmInvariant, uint256 cfmmTotalSupply) = IGammaPool(pool).getLatestCFMMBalances();
lpTokens = liquidity * cfmmTotalSupply / cfmmInvariant;
}
/// @dev transfer refunded amounts to `to` address
/// @param pool - refunded quantities of CFMM tokens
/// @param refunds - refunded quantities of CFMM tokens
/// @param to - address that will receive refunded quantities
function _transferRefunds(address pool, uint256[] memory refunds, address to) internal virtual {
address[] memory tokens = IGammaPool(pool).tokens();
for(uint256 i = 0; i < refunds.length;) {
IERC20(tokens[i]).transfer(to, refunds[i]);
unchecked {
++i;
}
}
}
/// @dev transfer refunded amounts from `from` address
/// @param pool - address of GammaPool that will receive the LP tokens
/// @param lpTokens - CFMM LP token amounts refunded
/// @param from - sender of CFMM LP tokens
function _transferLPTokensFrom(address pool, uint256 lpTokens, address from) internal virtual {
IERC20(IGammaPool(pool).cfmm()).transferFrom(from,pool,lpTokens);
}
function _calcWritedown(address pool, uint256 tokenId) internal virtual returns (uint256) {
address liquidationStrategy = IGammaPool(pool).singleLiquidationStrategy();
(bool success, bytes memory data) = liquidationStrategy.staticcall(abi.encodeWithSignature("LIQUIDATION_FEE()"));
if (success && data.length > 0) {
uint16 liquidationFee = abi.decode(data, (uint16));
(uint256 debt, uint256 collateral) = _canLiquidate(pool, tokenId);
collateral = collateral * (1e4 - liquidationFee) / 1e4;
return collateral >= debt ? 0 : debt - collateral;
}
return 0;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
import "./IGammaPoolEvents.sol";
import "./IProtocol.sol";
import "./strategies/events/IGammaPoolERC20Events.sol";
import "./rates/IRateModel.sol";
/// @title Interface for GammaPool
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Interface used for GammaPool implementations
interface IGammaPool is IProtocol, IGammaPoolEvents, IGammaPoolERC20Events, IRateModel {
/// @dev Struct containing Loan data plus tokenId
struct LoanData {
/// @dev Loan counter, used to generate unique tokenId which indentifies the loan in the GammaPool
uint256 id;
/// @dev Loan tokenId
uint256 tokenId;
// 1x256 bits
/// @dev GammaPool address loan belongs to
address poolId; // 160 bits
/// @dev Index of GammaPool interest rate at time loan is created/updated, max 7.9% trillion
uint96 rateIndex; // 96 bits
// 1x256 bits
/// @dev Initial loan debt in liquidity invariant units. Only increase when more liquidity is borrowed, decreases when liquidity is paid
uint128 initLiquidity; // 128 bits
/// @dev Loan debt in liquidity invariant units in last update
uint128 lastLiquidity; // 128 bits
/// @dev Loan debt in liquidity invariant units, increases with every update according to how many blocks have passed
uint128 liquidity; // 128 bits
/// @dev Collateral in terms of liquidity invariant units, increases with every update according to how many blocks have passed
uint256 collateral;
/// @dev Initial loan debt in terms of LP tokens at time liquidity was borrowed, updates along with initLiquidity
uint256 lpTokens;
/// @dev Reserve tokens held as collateral for the liquidity debt, indices match GammaPool's tokens[] array indices
uint128[] tokensHeld; // array of 128 bit numbers
/// @dev reference address of contract holding additional collateral for loan (e.g. CollateralManager)
address refAddr;
/// @dev reference fee of contract holding additional collateral for loan (e.g. CollateralManager)
uint16 refFee;
/// @dev reference type of contract holding additional collateral for loan (e.g. CollateralManager)
uint8 refType;
/// @dev price at which loan was opened
uint256 px;
/// @dev if true loan can be liquidated
bool canLiquidate;
/// @dev names of ERC20 tokens of CFMM
uint256 accFeeIndex;
/// @dev Percent accrual in CFMM invariant since last update
uint256 lastCFMMFeeIndex;
/// @dev names of ERC20 tokens of CFMM
uint256 LAST_BLOCK_NUMBER;
/// @dev ERC20 tokens of CFMM
address[] tokens;
/// @dev decimals of ERC20 tokens of CFMM
uint8[] decimals;
/// @dev symbols of ERC20 tokens of CFMM
string[] symbols;
/// @dev names of ERC20 tokens of CFMM
string[] names;
/// @dev interest rate model parameter store
address paramsStore;
/// @dev address of short strategy
address shortStrategy;
/// @dev borrowed liquidity invariant of the pool
uint256 BORROWED_INVARIANT;
/// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens
uint256 LP_INVARIANT;
/// @dev balance of CFMM LP tokens in the pool
uint256 LP_TOKEN_BALANCE;
/// @dev last CFMM liquidity invariant
uint256 lastCFMMInvariant;
/// @dev last CFMM total supply of LP tokens
uint256 lastCFMMTotalSupply;
/// @dev LTV liquidation threshold
uint256 ltvThreshold;
/// @dev Liquidation fee
uint256 liquidationFee;
}
/// @dev Struct returned in getLatestRates function. Contains all relevant global state variables
struct RateData {
/// @dev GammaPool's ever increasing interest rate index, tracks interest accrued through CFMM and liquidity loans, max 7.9% trillion
uint256 accFeeIndex;
/// @dev Percent accrual in CFMM invariant since last update
uint256 lastCFMMFeeIndex;
/// @dev Percent accrual in CFMM invariant and GammaPool interest since last update
uint256 lastFeeIndex;
/// @dev Borrow APR of LP tokens in GammaPool
uint256 borrowRate;
/// @dev Utilization rate of GammaPool
uint256 utilizationRate;
/// @dev last block an update to the GammaPool's global storage variables happened
uint256 lastBlockNumber;
/// @dev Current block number when requesting pool data
uint256 currBlockNumber;
/// @dev Last Price in CFMM
uint256 lastPrice;
/// @dev Supply APR of LP tokens in GammaPool
uint256 supplyRate;
/// @dev names of ERC20 tokens of CFMM
uint256 BORROWED_INVARIANT;
/// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens
uint256 LP_INVARIANT;
/// @dev EMA of utilization Rate
uint256 emaUtilRate;
/// @dev Minimum Utilization Rate 1
uint256 minUtilRate1;
/// @dev Minimum Utilization Rate 2
uint256 minUtilRate2;
/// @dev Dynamic origination fee divisor
uint256 feeDivisor;
/// @dev Loan opening origination fee in basis points
uint256 origFee; // 16 bits
/// @dev LTV liquidation threshold
uint256 ltvThreshold;
/// @dev Liquidation fee
uint256 liquidationFee;
/// @dev Short Strategy implementation address
address shortStrategy;
/// @dev Interest Rate Parameters Store contract
address paramsStore;
}
/// @dev Struct returned in getPoolData function. Contains all relevant global state variables
struct PoolData {
/// @dev GammaPool address
address poolId;
/// @dev Protocol id of the implementation contract for this GammaPool
uint16 protocolId;
/// @dev Borrow Strategy implementation contract for this GammaPool
address borrowStrategy;
/// @dev Repay Strategy implementation contract for this GammaPool
address repayStrategy;
/// @dev Rebalance Strategy implementation contract for this GammaPool
address rebalanceStrategy;
/// @dev Short Strategy implementation contract for this GammaPool
address shortStrategy;
/// @dev Single Liquidation Strategy implementation contract for this GammaPool
address singleLiquidationStrategy;
/// @dev Batch Liquidation Strategy implementation contract for this GammaPool
address batchLiquidationStrategy;
/// @dev factory - address of factory contract that instantiated this GammaPool
address factory;
/// @dev paramsStore - interest rate model parameters store contract
address paramsStore;
// LP Tokens
/// @dev Quantity of CFMM's LP tokens deposited in GammaPool by liquidity providers
uint256 LP_TOKEN_BALANCE;// LP Tokens in GS, LP_TOKEN_TOTAL = LP_TOKEN_BALANCE + LP_TOKEN_BORROWED_PLUS_INTEREST
/// @dev Quantity of CFMM's LP tokens that have been borrowed by liquidity borrowers excluding accrued interest (principal)
uint256 LP_TOKEN_BORROWED;//LP Tokens that have been borrowed (Principal)
/// @dev Quantity of CFMM's LP tokens that have been borrowed by liquidity borrowers including accrued interest
uint256 LP_TOKEN_BORROWED_PLUS_INTEREST;//LP Tokens that have been borrowed (principal) plus interest in LP Tokens
// Invariants
/// @dev Quantity of CFMM's liquidity invariant that has been borrowed including accrued interest, maps to LP_TOKEN_BORROWED_PLUS_INTEREST
uint128 BORROWED_INVARIANT;
/// @dev Quantity of CFMM's liquidity invariant held in GammaPool as LP tokens, maps to LP_TOKEN_BALANCE
uint128 LP_INVARIANT;//Invariant from LP Tokens, TOTAL_INVARIANT = BORROWED_INVARIANT + LP_INVARIANT
// Rates
/// @dev cfmm - address of CFMM this GammaPool is for
address cfmm;
/// @dev GammaPool's ever increasing interest rate index, tracks interest accrued through CFMM and liquidity loans, max 30.9% billion
uint80 accFeeIndex;
/// @dev External swap fee in basis points, max 255 basis points = 2.55%
uint8 extSwapFee; // 8 bits
/// @dev Loan opening origination fee in basis points
uint16 origFee; // 16 bits
/// @dev LAST_BLOCK_NUMBER - last block an update to the GammaPool's global storage variables happened
uint40 LAST_BLOCK_NUMBER;
/// @dev Percent accrual in CFMM invariant since last update
uint64 lastCFMMFeeIndex; // 64 bits
/// @dev Total liquidity invariant amount in CFMM (from GammaPool and others), read in last update to GammaPool's storage variables
uint128 lastCFMMInvariant;
/// @dev Total LP token supply from CFMM (belonging to GammaPool and others), read in last update to GammaPool's storage variables
uint256 lastCFMMTotalSupply;
// ERC20 fields
/// @dev Total supply of GammaPool's own ERC20 token representing the liquidity of depositors to the CFMM through the GammaPool
uint256 totalSupply;
// tokens and balances
/// @dev ERC20 tokens of CFMM
address[] tokens;
/// @dev symbols of ERC20 tokens of CFMM
string[] symbols;
/// @dev names of ERC20 tokens of CFMM
string[] names;
/// @dev Decimals of CFMM tokens, indices match tokens[] array
uint8[] decimals;
/// @dev Amounts of ERC20 tokens from the CFMM held as collateral in the GammaPool. Equals to the sum of all tokensHeld[] quantities in all loans
uint128[] TOKEN_BALANCE;
/// @dev Amounts of ERC20 tokens from the CFMM held in the CFMM as reserve quantities. Used to log prices in the CFMM during updates to the GammaPool
uint128[] CFMM_RESERVES; //keeps track of price of CFMM at time of update
/// @dev Last Price in CFMM
uint256 lastPrice;
/// @dev Percent accrual in CFMM invariant and GammaPool interest since last update
uint256 lastFeeIndex;
/// @dev Borrow rate of LP tokens in GammaPool
uint256 borrowRate;
/// @dev Utilization rate of GammaPool
uint256 utilizationRate;
/// @dev Current block number when requesting pool data
uint40 currBlockNumber;
/// @dev LTV liquidation threshold
uint8 ltvThreshold;
/// @dev Liquidation fee
uint8 liquidationFee;
/// @dev Supply APR of LP tokens in GammaPool
uint256 supplyRate;
/// @dev EMA of utilization Rate
uint40 emaUtilRate;
/// @dev Multiplier of EMA Utilization Rate
uint8 emaMultiplier;
/// @dev Minimum Utilization Rate 1
uint8 minUtilRate1;
/// @dev Minimum Utilization Rate 2
uint8 minUtilRate2;
/// @dev Dynamic origination fee divisor
uint16 feeDivisor;
/// @dev Minimum liquidity amount that can be borrowed
uint72 minBorrow;
}
/// @dev cfmm - address of CFMM this GammaPool is for
function cfmm() external view returns(address);
/// @dev ERC20 tokens of CFMM
function tokens() external view returns(address[] memory);
/// @dev address of factory contract that instantiated this GammaPool
function factory() external view returns(address);
/// @dev viewer contract to implement complex view functions for data in this GammaPool
function viewer() external view returns(address);
/// @dev Borrow Strategy implementation contract for this GammaPool
function borrowStrategy() external view returns(address);
/// @dev Repay Strategy implementation contract for this GammaPool
function repayStrategy() external view returns(address);
/// @dev Rebalance Strategy implementation contract for this GammaPool
function rebalanceStrategy() external view returns(address);
/// @dev Short Strategy implementation contract for this GammaPool
function shortStrategy() external view returns(address);
/// @dev Single Loan Liquidation Strategy implementation contract for this GammaPool
function singleLiquidationStrategy() external view returns(address);
/// @dev Batch Liquidations Strategy implementation contract for this GammaPool
function batchLiquidationStrategy() external view returns(address);
/// @dev Set parameters to calculate origination fee, liquidation fee, and ltv threshold
/// @param origFee - loan opening origination fee in basis points
/// @param extSwapFee - external swap fee in basis points, max 255 basis points = 2.55%
/// @param emaMultiplier - multiplier used in EMA calculation of utilization rate
/// @param minUtilRate1 - minimum utilization rate to calculate dynamic origination fee in exponential model
/// @param minUtilRate2 - minimum utilization rate to calculate dynamic origination fee in linear model
/// @param feeDivisor - fee divisor for calculating origination fee, based on 2^(maxUtilRate - minUtilRate1)
/// @param liquidationFee - liquidation fee to charge during liquidations in basis points (1 - 255 => 0.01% to 2.55%)
/// @param ltvThreshold - ltv threshold (1 - 255 => 0.1% to 25.5%)
/// @param minBorrow - minimum liquidity amount that can be borrowed or left unpaid in a loan
function setPoolParams(uint16 origFee, uint8 extSwapFee, uint8 emaMultiplier, uint8 minUtilRate1, uint8 minUtilRate2, uint16 feeDivisor, uint8 liquidationFee, uint8 ltvThreshold, uint72 minBorrow) external;
/// @dev Balances in the GammaPool of collateral tokens, CFMM LP tokens, and invariant amounts at last update
/// @return tokenBalances - balances of collateral tokens in GammaPool
/// @return lpTokenBalance - CFMM LP token balance of GammaPool
/// @return lpTokenBorrowed - CFMM LP token principal amounts borrowed from GammaPool
/// @return lpTokenBorrowedPlusInterest - CFMM LP token amounts borrowed from GammaPool including accrued interest
/// @return borrowedInvariant - invariant amount borrowed from GammaPool including accrued interest, maps to lpTokenBorrowedPlusInterest
/// @return lpInvariant - invariant of CFMM LP tokens in GammaPool not borrowed, maps to lpTokenBalance
function getPoolBalances() external view returns(uint128[] memory tokenBalances, uint256 lpTokenBalance, uint256 lpTokenBorrowed,
uint256 lpTokenBorrowedPlusInterest, uint256 borrowedInvariant, uint256 lpInvariant);
/// @dev Balances in CFMM at last update of GammaPool
/// @return cfmmReserves - total reserve tokens in CFMM last time GammaPool was updated
/// @return cfmmInvariant - total liquidity invariant of CFMM last time GammaPool was updated
/// @return cfmmTotalSupply - total CFMM LP tokens in existence last time GammaPool was updated
function getCFMMBalances() external view returns(uint128[] memory cfmmReserves, uint256 cfmmInvariant, uint256 cfmmTotalSupply);
/// @dev Interest rate information in GammaPool at last update
/// @return accFeeIndex - total accrued interest in GammaPool at last update
/// @return lastCFMMFeeIndex - total accrued CFMM fee since last update
/// @return lastBlockNumber - last block GammaPool was updated
function getRates() external view returns(uint256 accFeeIndex, uint256 lastCFMMFeeIndex, uint256 lastBlockNumber);
/// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls
function getPoolData() external view returns(PoolData memory data);
// Short Gamma
/// @dev Deposit CFMM LP token and get GS LP token, without doing a transferFrom transaction. Must have sent CFMM LP token first
/// @param to - address of receiver of GS LP token
/// @return shares - quantity of GS LP tokens received for CFMM LP tokens
function depositNoPull(address to) external returns(uint256 shares);
/// @dev Withdraw CFMM LP token, by burning GS LP token, without doing a transferFrom transaction. Must have sent GS LP token first
/// @param to - address of receiver of CFMM LP tokens
/// @return assets - quantity of CFMM LP tokens received for GS LP tokens
function withdrawNoPull(address to) external returns(uint256 assets);
/// @dev Withdraw reserve token quantities of CFMM (instead of CFMM LP tokens), by burning GS LP token
/// @param to - address of receiver of reserve token quantities
/// @return reserves - quantity of reserve tokens withdrawn from CFMM and sent to receiver
/// @return assets - quantity of CFMM LP tokens representing reserve tokens withdrawn
function withdrawReserves(address to) external returns (uint256[] memory reserves, uint256 assets);
/// @dev Deposit reserve token quantities to CFMM (instead of CFMM LP tokens) to get CFMM LP tokens, store them in GammaPool and receive GS LP tokens
/// @param to - address of receiver of GS LP tokens
/// @param amountsDesired - desired amounts of reserve tokens to deposit
/// @param amountsMin - minimum amounts of reserve tokens to deposit
/// @param data - information identifying request to deposit
/// @return reserves - quantity of actual reserve tokens deposited in CFMM
/// @return shares - quantity of GS LP tokens received for reserve tokens deposited
function depositReserves(address to, uint256[] calldata amountsDesired, uint256[] calldata amountsMin, bytes calldata data) external returns(uint256[] memory reserves, uint256 shares);
/// @return cfmmReserves - latest token reserves in the CFMM
function getLatestCFMMReserves() external view returns(uint128[] memory cfmmReserves);
/// @return cfmmReserves - latest token reserves in the CFMM
/// @return cfmmInvariant - latest total invariant in the CFMM
/// @return cfmmTotalSupply - latest total supply of LP tokens in CFMM
function getLatestCFMMBalances() external view returns(uint128[] memory cfmmReserves, uint256 cfmmInvariant, uint256 cfmmTotalSupply);
/// @return lastPrice - calculates and gets current price at CFMM
function getLastCFMMPrice() external view returns(uint256);
// Long Gamma
/// @dev Create a new Loan struct
/// @param refId - Reference id of post transaction activities attached to this loan
/// @return tokenId - unique id of loan struct created
function createLoan(uint16 refId) external returns(uint256 tokenId);
/// @dev Get loan from storage and convert to LoanData struct
/// @param _tokenId - tokenId of loan to convert
/// @return _loanData - loan data struct (same as Loan + tokenId)
function getLoanData(uint256 _tokenId) external view returns(LoanData memory _loanData);
/// @dev Get loan with its most updated information
/// @param _tokenId - unique id of loan, used to look up loan in GammaPool
/// @return _loanData - loan data struct (same as Loan + tokenId)
function loan(uint256 _tokenId) external view returns(LoanData memory _loanData);
/// @dev Get list of loans and their corresponding tokenIds created in GammaPool. Capped at s.tokenIds.length.
/// @param start - index from where to start getting tokenIds from array
/// @param end - end index of array wishing to get tokenIds. If end > s.tokenIds.length, end is s.tokenIds.length
/// @param active - if true, return loans that have an outstanding liquidity debt
/// @return _loans - list of loans created in GammaPool
function getLoans(uint256 start, uint256 end, bool active) external view returns(LoanData[] memory _loans);
/// @dev calculate liquidity invariant from collateral tokens
/// @param tokensHeld - loan's collateral tokens
/// @return collateralInvariant - invariant calculated from loan's collateral tokens
function calcInvariant(uint128[] memory tokensHeld) external view returns(uint256);
/// @dev Get list of loans mapped to tokenIds in array `tokenIds`
/// @param tokenIds - list of loan tokenIds
/// @param active - if true, return loans that have an outstanding liquidity debt
/// @return _loans - list of loans created in GammaPool
function getLoansById(uint256[] calldata tokenIds, bool active) external view returns(LoanData[] memory _loans);
/// @return loanCount - total number of loans opened
function getLoanCount() external view returns(uint256);
/// @dev Deposit more collateral in loan identified by tokenId
/// @param tokenId - unique id identifying loan
/// @param ratio - ratio to rebalance collateral after increasing collateral
/// @return tokensHeld - updated collateral token amounts backing loan
function increaseCollateral(uint256 tokenId, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);
/// @dev Withdraw collateral from loan identified by tokenId
/// @param tokenId - unique id identifying loan
/// @param amounts - amounts of collateral tokens requested to withdraw
/// @param to - destination address of receiver of collateral withdrawn
/// @param ratio - ratio to rebalance collateral after withdrawing collateral
/// @return tokensHeld - updated collateral token amounts backing loan
function decreaseCollateral(uint256 tokenId, uint128[] memory amounts, address to, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);
/// @dev Borrow liquidity from the CFMM and add it to the debt and collateral of loan identified by tokenId
/// @param tokenId - unique id identifying loan
/// @param lpTokens - quantity of CFMM LP tokens requested to short
/// @param ratio - ratio to rebalance collateral after borrowing
/// @return liquidityBorrowed - liquidity amount that has been borrowed
/// @return amounts - reserves quantities withdrawn from CFMM that correspond to the LP tokens shorted, now used as collateral
/// @return tokensHeld - updated collateral token amounts backing loan
function borrowLiquidity(uint256 tokenId, uint256 lpTokens, uint256[] calldata ratio) external returns(uint256 liquidityBorrowed, uint256[] memory amounts, uint128[] memory tokensHeld);
/// @dev Repay liquidity debt of loan identified by tokenId, debt is repaid using available collateral in loan
/// @param tokenId - unique id identifying loan
/// @param liquidity - liquidity debt being repaid, capped at actual liquidity owed. Can't repay more than you owe
/// @param collateralId - index of collateral token + 1
/// @param to - if repayment type requires withdrawal, the address that will receive the funds. Otherwise can be zero address
/// @return liquidityPaid - liquidity amount that has been repaid
/// @return amounts - collateral amounts consumed in repaying liquidity debt
function repayLiquidity(uint256 tokenId, uint256 liquidity, uint256 collateralId, address to) external returns(uint256 liquidityPaid, uint256[] memory amounts);
/// @dev Repay liquidity debt of loan identified by tokenId, debt is repaid using available collateral in loan
/// @param tokenId - unique id identifying loan
/// @param liquidity - liquidity debt being repaid, capped at actual liquidity owed. Can't repay more than you owe
/// @param ratio - weights of collateral after repaying liquidity
/// @return liquidityPaid - liquidity amount that has been repaid
/// @return amounts - collateral amounts consumed in repaying liquidity debt
function repayLiquiditySetRatio(uint256 tokenId, uint256 liquidity, uint256[] calldata ratio) external returns(uint256 liquidityPaid, uint256[] memory amounts);
/// @dev Repay liquidity debt of loan identified by tokenId, using CFMM LP token
/// @param tokenId - unique id identifying loan
/// @param collateralId - index of collateral token to rebalance to + 1
/// @param to - if repayment type requires withdrawal, the address that will receive the funds. Otherwise can be zero address
/// @return liquidityPaid - liquidity amount that has been repaid
/// @return tokensHeld - remaining token amounts collateralizing loan
function repayLiquidityWithLP(uint256 tokenId, uint256 collateralId, address to) external returns(uint256 liquidityPaid, uint128[] memory tokensHeld);
/// @dev Rebalance collateral amounts of loan identified by tokenId by purchasing or selling some of the collateral
/// @param tokenId - unique id identifying loan
/// @param deltas - collateral amounts being bought or sold (>0 buy, <0 sell), index matches tokensHeld[] index. Only n-1 tokens can be traded
/// @param ratio - ratio to rebalance collateral
/// @return tokensHeld - updated collateral token amounts backing loan
function rebalanceCollateral(uint256 tokenId, int256[] memory deltas, uint256[] calldata ratio) external returns(uint128[] memory tokensHeld);
/// @dev Update pool liquidity debt and optinally also loan liquidity debt
/// @param tokenId - (optional) unique ids identifying loan, pass zero to ignore this parameter
/// @return loanLiquidityDebt - updated liquidity debt amount of loan
/// @return poolLiquidityDebt - updated liquidity debt amount of pool
function updatePool(uint256 tokenId) external returns(uint256 loanLiquidityDebt, uint256 poolLiquidityDebt);
/// @notice When calling this function and adding additional collateral it is assumed that you have sent the collateral first
/// @dev Function to liquidate a loan using its own collateral or depositing additional tokens. Seeks full liquidation
/// @param tokenId - tokenId of loan being liquidated
/// @return loanLiquidity - loan liquidity liquidated (after write down)
/// @return refund - amount of CFMM LP tokens being refunded to liquidator
function liquidate(uint256 tokenId) external returns(uint256 loanLiquidity, uint256 refund);
/// @dev Function to liquidate a loan using external LP tokens. Allows partial liquidation
/// @param tokenId - tokenId of loan being liquidated
/// @return loanLiquidity - loan liquidity liquidated (after write down)
/// @return refund - amounts from collateral tokens being refunded to liquidator
function liquidateWithLP(uint256 tokenId) external returns(uint256 loanLiquidity, uint256[] memory refund);
/// @dev Function to liquidate multiple loans in batch.
/// @param tokenIds - list of tokenIds of loans to liquidate
/// @return totalLoanLiquidity - total loan liquidity liquidated (after write down)
/// @return refund - amounts from collateral tokens being refunded to liquidator
function batchLiquidations(uint256[] calldata tokenIds) external returns(uint256 totalLoanLiquidity, uint256[] memory refund);
// Sync functions
/// @dev Skim excess collateral tokens or CFMM LP tokens from GammaPool and send them to receiver (`to`) address
/// @param to - address receiving excess tokens
function skim(address to) external;
/// @dev Synchronize LP_TOKEN_BALANCE with actual CFMM LP tokens deposited in GammaPool
function sync() external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
import "./strategies/events/ILiquidationStrategyEvents.sol";
import "./strategies/events/IShortStrategyEvents.sol";
import "./strategies/events/IExternalStrategyEvents.sol";
/// @title GammaPool Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by all GammaPool implementations (contains all strategy events)
interface IGammaPoolEvents is IShortStrategyEvents, ILiquidationStrategyEvents, IExternalStrategyEvents {
/// @dev Event emitted when a Loan is created
/// @param caller - address that created the loan
/// @param tokenId - unique id that identifies the loan in question
/// @param refId - Reference id of post transaction activities attached to this loan
event LoanCreated(address indexed caller, uint256 tokenId, uint16 refId);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
import "./IGammaPool.sol";
/// @title Interface for Viewer Contract for GammaPool
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Viewer makes complex view function calls from GammaPool's storage data (e.g. updated loan and pool debt)
interface IPoolViewer {
/// @dev Check if can liquidate loan identified by `tokenId`
/// @param pool - address of pool loans belong to
/// @param tokenId - unique id of loan, used to look up loan in GammaPool
/// @return canLiquidate - true if loan can be liquidated, false otherwise
function canLiquidate(address pool, uint256 tokenId) external view returns(bool);
/// @dev Get latest rate information from GammaPool
/// @param pool - address of pool to request latest rates for
/// @return data - RateData struct containing latest rate information
function getLatestRates(address pool) external view returns(IGammaPool.RateData memory data);
/// @dev Get list of loans and their corresponding tokenIds created in GammaPool. Capped at s.tokenIds.length.
/// @param pool - address of pool loans belong to
/// @param start - index from where to start getting tokenIds from array
/// @param end - end index of array wishing to get tokenIds. If end > s.tokenIds.length, end is s.tokenIds.length
/// @param active - if true, return loans that have an outstanding liquidity debt
/// @return _loans - list of loans created in GammaPool
function getLoans(address pool, uint256 start, uint256 end, bool active) external view returns(IGammaPool.LoanData[] memory _loans);
/// @dev Get list of loans mapped to tokenIds in array `tokenIds`
/// @param pool - address of pool loans belong to
/// @param tokenIds - list of loan tokenIds
/// @param active - if true, return loans that have an outstanding liquidity debt
/// @return _loans - list of loans created in GammaPool
function getLoansById(address pool, uint256[] calldata tokenIds, bool active) external view returns(IGammaPool.LoanData[] memory _loans);
/// @dev Get loan with its most updated information
/// @param pool - address of pool loan belongs to
/// @param tokenId - unique id of loan, used to look up loan in GammaPool
/// @return loanData - loan data struct (same as Loan + tokenId)
function loan(address pool, uint256 tokenId) external view returns(IGammaPool.LoanData memory loanData);
/// @dev Returns pool storage data updated to their latest values
/// @notice Difference with getPoolData() is this struct is what PoolData would return if an update of the GammaPool were to occur at the current block
/// @param pool - address of pool to get pool data for
/// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls
function getLatestPoolData(address pool) external view returns(IGammaPool.PoolData memory data);
/// @dev Calculate origination fee that will be charged if borrowing liquidity amount
/// @param pool - address of GammaPool to calculate origination fee for
/// @param liquidity - liquidity to borrow
/// @return origFee - calculated origination fee, without any discounts
function calcDynamicOriginationFee(address pool, uint256 liquidity) external view returns(uint256 origFee);
/// @dev Return pool storage data
/// @param pool - address of pool to get pool data for
/// @return data - struct containing all relevant global state variables and descriptive information of GammaPool. Used to avoid making multiple calls
function getPoolData(address pool) external view returns(IGammaPool.PoolData memory data);
/// @dev Get CFMM tokens meta data
/// @param _tokens - array of token address of ERC20 tokens of CFMM
/// @return _symbols - array of symbols of ERC20 tokens of CFMM
/// @return _names - array of names of ERC20 tokens of CFMM
/// @return _decimals - array of decimals of ERC20 tokens of CFMM
function getTokensMetaData(address[] memory _tokens) external view returns(string[] memory _symbols, string[] memory _names, uint8[] memory _decimals);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
/// @title Interface for Protocol
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Interface used to add protocols and initialize them in GammaPoolFactory
interface IProtocol {
/// @dev Protocol id of the implementation contract for this GammaPool
function protocolId() external view returns(uint16);
/// @dev Check GammaPool for CFMM and tokens can be created with this implementation
/// @param _tokens - assumed tokens of CFMM, validate function should check CFMM is indeed for these tokens
/// @param _cfmm - address of CFMM GammaPool will be for
/// @param _data - custom struct containing additional information used to verify the `_cfmm`
/// @return _tokensOrdered - tokens ordered to match the same order as in CFMM
function validateCFMM(address[] calldata _tokens, address _cfmm, bytes calldata _data) external view returns(address[] memory _tokensOrdered);
/// @dev Function to initialize state variables GammaPool, called usually from GammaPoolFactory contract right after GammaPool instantiation
/// @param _cfmm - address of CFMM GammaPool is for
/// @param _tokens - ERC20 tokens of CFMM
/// @param _decimals - decimals of CFMM tokens, indices must match _tokens[] array
/// @param _data - custom struct containing additional information used to verify the `_cfmm`
/// @param _minBorrow - minimum amount of liquidity that can be borrowed or left unpaid in a loan
function initialize(address _cfmm, address[] calldata _tokens, uint8[] calldata _decimals, uint72 _minBorrow, bytes calldata _data) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
/// @title Interface of Interest Rate Model Store
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @notice Interface of contract that saves and retrieves interest rate model parameters
interface IRateModel {
/// @dev Function to validate interest rate model parameters
/// @param _data - bytes parameters containing interest rate model parameters
/// @return validation - true if parameters passed validation
function validateParameters(bytes calldata _data) external view returns(bool);
/// @dev Gets address of contract containing parameters for interest rate model
/// @return address - address of smart contract that stores interest rate parameters
function rateParamsStore() external view returns(address);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
import "./IStrategyEvents.sol";
/// @title External Strategy Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by external strategy (flash loans) implementations
interface IExternalStrategyEvents is IStrategyEvents {
/// @dev Event emitted when a flash loan is made. Purpose of flash loan is for external swaps/rebalance of loan collateral
/// @param tokenId - unique id that identifies the loan in question
/// @param amounts - amounts of tokens held as collateral in pool that were swapped
/// @param lpTokens - LP tokens swapped externally
/// @param liquidity - total liquidity externally swapped in flash loan (amounts + lpTokens)
/// @param txType - transaction type. Possible values come from enum TX_TYPE
event ExternalSwap(uint256 indexed tokenId, uint128[] amounts, uint256 lpTokens, uint128 liquidity, TX_TYPE indexed txType);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
/// @title GammaPool ERC20 Events
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events that should be emitted by all strategy implementations (root of all strategy events interfaces)
interface IGammaPoolERC20Events {
/// @dev Emitted when `amount` GS LP tokens are moved from account `from` to account `to`.
/// @param from - address sending GS LP tokens
/// @param to - address receiving GS LP tokens
/// @param amount - amount of GS LP tokens being sent
event Transfer(address indexed from, address indexed to, uint256 amount);
/// @dev Emitted when the allowance of a `spender` for an `owner` is set by a call to approve function. `amount` is the new allowance.
/// @param owner - address which owns the GS LP tokens spender is being given permission to spend
/// @param spender - address given permission to spend owner's GS LP tokens
/// @param amount - amount of GS LP tokens spender is given permission to spend
event Approval(address indexed owner, address indexed spender, uint256 amount);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
import "./ILongStrategyEvents.sol";
/// @title Liquidation Strategy Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by all liquidation strategy implementations
interface ILiquidationStrategyEvents is ILongStrategyEvents {
/// @dev Event emitted when liquidating through _liquidate or _liquidateWithLP functions
/// @param tokenId - id identifier of loan being liquidated
/// @param collateral - collateral of loan being liquidated
/// @param liquidity - liquidity debt being repaid
/// @param writeDownAmt - amount of liquidity invariant being written down
/// @param fee - liquidation fee paid to liquidator in liquidity invariant units
/// @param txType - type of liquidation. Possible values come from enum TX_TYPE
event Liquidation(uint256 indexed tokenId, uint128 collateral, uint128 liquidity, uint128 writeDownAmt, uint128 fee, TX_TYPE txType);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
import "./IStrategyEvents.sol";
/// @title Long Strategy Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by all long strategy implementations
interface ILongStrategyEvents is IStrategyEvents {
/// @dev Event emitted when a Loan is updated
/// @param tokenId - unique id that identifies the loan in question
/// @param tokensHeld - amounts of tokens held as collateral against the loan
/// @param liquidity - liquidity invariant that was borrowed including accrued interest
/// @param initLiquidity - initial liquidity borrowed excluding interest (principal)
/// @param lpTokens - LP tokens borrowed excluding interest (principal)
/// @param rateIndex - interest rate index of GammaPool at time loan is updated
/// @param txType - transaction type. Possible values come from enum TX_TYPE
event LoanUpdated(uint256 indexed tokenId, uint128[] tokensHeld, uint128 liquidity, uint128 initLiquidity, uint256 lpTokens, uint96 rateIndex, TX_TYPE indexed txType);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
import "./IStrategyEvents.sol";
/// @title Short Strategy Events Interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events emitted by all short strategy implementations
interface IShortStrategyEvents is IStrategyEvents {
/// @dev Event emitted when a deposit of CFMM LP tokens in exchange of GS LP tokens happens (e.g. _deposit, _mint, _depositReserves, _depositNoPull)
/// @param caller - address calling the function to deposit CFMM LP tokens
/// @param to - address receiving GS LP tokens
/// @param assets - amount CFMM LP tokens deposited
/// @param shares - amount GS LP tokens minted
event Deposit(address indexed caller, address indexed to, uint256 assets, uint256 shares);
/// @dev Event emitted when a withdrawal of CFMM LP tokens happens (e.g. _withdraw, _redeem, _withdrawReserves, _withdrawNoPull)
/// @param caller - address calling the function to withdraw CFMM LP tokens
/// @param to - address receiving CFMM LP tokens
/// @param from - address redeeming/burning GS LP tokens
/// @param assets - amount of CFMM LP tokens withdrawn
/// @param shares - amount of GS LP tokens redeemed
event Withdraw(address indexed caller, address indexed to, address indexed from, uint256 assets, uint256 shares);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
/// @title Strategy Events interface
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Events that should be emitted by all strategy implementations (root of all strategy events interfaces)
interface IStrategyEvents {
enum TX_TYPE {
DEPOSIT_LIQUIDITY, // 0
WITHDRAW_LIQUIDITY, // 1
DEPOSIT_RESERVES, // 2
WITHDRAW_RESERVES, // 3
INCREASE_COLLATERAL, // 4
DECREASE_COLLATERAL, // 5
REBALANCE_COLLATERAL, // 6
BORROW_LIQUIDITY, // 7
REPAY_LIQUIDITY, // 8
REPAY_LIQUIDITY_SET_RATIO,// 9
REPAY_LIQUIDITY_WITH_LP,// 10
LIQUIDATE, // 11
LIQUIDATE_WITH_LP, // 12
BATCH_LIQUIDATION, // 13
SYNC, // 14
EXTERNAL_REBALANCE, // 15
EXTERNAL_LIQUIDATION, // 16
UPDATE_POOL } // 17
/// @dev Event emitted when the Pool's global state variables is updated
/// @param lpTokenBalance - quantity of CFMM LP tokens deposited in the pool
/// @param lpTokenBorrowed - quantity of CFMM LP tokens that have been borrowed from the pool (principal)
/// @param lastBlockNumber - last block the Pool's where updated
/// @param accFeeIndex - interest of total accrued interest in the GammaPool until current update
/// @param lpTokenBorrowedPlusInterest - quantity of CFMM LP tokens that have been borrowed from the pool including interest
/// @param lpInvariant - lpTokenBalance as invariant units
/// @param borrowedInvariant - lpTokenBorrowedPlusInterest as invariant units
/// @param cfmmReserves - reserves in CFMM. Used to track price
/// @param txType - transaction type. Possible values come from enum TX_TYPE
event PoolUpdated(uint256 lpTokenBalance, uint256 lpTokenBorrowed, uint40 lastBlockNumber, uint80 accFeeIndex,
uint256 lpTokenBorrowedPlusInterest, uint128 lpInvariant, uint128 borrowedInvariant, uint128[] cfmmReserves, TX_TYPE indexed txType);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.0;
/// @title Math Library
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Library for performing various math operations
library GSMath {
function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x > y ? x : y;
}
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x < y ? x : y;
}
// Babylonian Method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
function sqrt(uint256 y) internal pure returns (uint256 z) {
unchecked {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
}// SPDX-License-Identifier: GPL-v3
pragma solidity >=0.8.0;
import "@gammaswap/v1-core/contracts/interfaces/IGammaPool.sol";
/// @title Interface for Liquidator contract
/// @author Daniel D. Alcarraz (https://github.com/0xDanr)
/// @dev Helps liquidation of loans in GammaPools
interface ILiquidator {
/// @dev Calculate liquidity debt as CFMM LP Tokens
/// @param pool - address of GammaPool loan belongs to
/// @param tokenId - tokenId of loan in GammaPool (`pool`) to check
/// @return lpTokens - liquidity debt of loan as CFMM LP Tokens
function calcLPTokenDebt(address pool, uint256 tokenId) external view returns(uint256 lpTokens);
/// @dev Check if loan in `pool` identified by `tokenId` can be liquidated
/// @param pool - address of GammaPool loan belongs to
/// @param tokenId - tokenId of loan in GammaPool (`pool`) to check
/// @return liquidity - liquidity debt of loan (not written down), if it can be liquidated. Otherwise it returns 0
/// @return collateral - liquidity collateral backing loan, if it can be liquidated. Otherwise it returns 0
function canLiquidate(address pool, uint256 tokenId) external view returns(uint256 liquidity, uint256 collateral);
/// @dev Check if loans in `pool` identified by `tokenIds` can be liquidated
/// @param pool - address of GammaPool loan belongs to
/// @param tokenIds - list of tokenIds of loans in GammaPool (`pool`) to check
/// @return _tokenIds - list of tokenIds of loans that can be liquidated. The array may be larger
/// @return _liquidity - summed liquidity debt of loans (not written down) that can be liquidated. If a loan can't be liquidate it is not summed
/// @return _collateral - liquidity collateral backing loan that can be liquidated. If a loan can't be liquidate it is not summed
function canBatchLiquidate(address pool, uint256[] calldata tokenIds) external view returns(uint256[] memory _tokenIds, uint256 _liquidity, uint256 _collateral);
/// @dev Liquidate loan in `pool` identified by `tokenId` using the loan's own collateral tokens
/// @param pool - address of GammaPool loan belongs to
/// @param tokenId - tokenId of loan in GammaPool (`pool`) to check
/// @param to - receiver of liquidation fee
/// @return refund - CFMM LP tokens that are refunded to liquidator
function liquidate(address pool, uint256 tokenId, address to) external returns(uint256 refund);
/// @dev Liquidate loan in `pool` identified by `tokenId` using CFMM LP tokens of the CFMM liquidity was borrowed from
/// @param pool - address of GammaPool loan belongs to
/// @param tokenId - tokenId of loan in GammaPool (`pool`) to check
/// @param lpTokens - CFMM LP tokens to transfer to liquidate
/// @param calcLpTokens - if true calculate how many CFMM LP Tokens to liquidate
/// @param to - receiver of liquidation fee
/// @return refunds - collateral tokens that are refunded to liquidator
function liquidateWithLP(address pool, uint256 tokenId, uint256 lpTokens, bool calcLpTokens, address to) external returns(uint256[] memory refunds);
/// @dev Liquidate loan in `pool` identified by `tokenId` using the loan's own collateral tokens
/// @param pool - address of GammaPool loan belongs to
/// @param tokenId - tokenId of loan in GammaPool (`pool`) to check
/// @param to - receiver of liquidation fee
/// @return _tokenIds - list of tokenIds of loans that were liquidated
/// @return refunds - collateral tokens that are refunded to liquidator from all loans that were liquidated
function batchLiquidate(address pool, uint256[] calldata tokenId, address to) external returns(uint256[] memory _tokenIds, uint256[] memory refunds);
/// @dev Get most updated loan information for a loan identified by `tokenId` in `pool`
/// @param pool - address of GammaPool loan belongs to
/// @param tokenId - tokenId of loan in GammaPool (`pool`) to check
/// @return loan - struct containing most up to date loan information and other data to identify loan
function getLoan(address pool, uint256 tokenId) external view returns(IGammaPool.LoanData memory loan);
/// @dev Get most updated loan information for list of loans in GammaPool
/// @param pool - address of GammaPool loans belong to
/// @param tokenIds - list of tokenIds of loans in GammaPool (`pool`) to get information for
/// @param active - filter to select only loans with outstanding liquidity debts (if true, ignore loans with 0 liquidity debts)
/// @return loans - struct containing most up to date loan information and other data to identify loan
function getLoans(address pool, uint256[] calldata tokenIds, bool active) external view returns(IGammaPool.LoanData[] memory loans);
/// @dev Get most updated loan information for loans opened in GammaPool from index `start` to `end`
/// @notice All loans in GammaPool are opened in ascending order. The first loan has index 1, the next is 2, ...
/// @param pool - address of GammaPool loans belong to
/// @param start - beginning index to query for loans in GammaPool
/// @param end - last index to query for loans in GammaPool
/// @param active - filter to select only loans with outstanding liquidity debts (if true, ignore loans with 0 liquidity debts)
/// @return loans - struct containing most up to date loan information and other data to identify loan
function getLoans(address pool, uint256 start, uint256 end, bool active) external view returns(IGammaPool.LoanData[] memory loans);
/// @dev Get tokenIds of loans opened in GammaPool from index `start` to `end`
/// @notice All loans in GammaPool are opened in ascending order. The first loan has index 1, the next is 2, ...
/// @param pool - address of GammaPool loans belong to
/// @param start - beginning index to query for loans in GammaPool
/// @param end - last index to query for loans in GammaPool
/// @param active - filter to select only loans with outstanding liquidity debts (if true, ignore loans with 0 liquidity debts)
/// @return tokenIds - list of tokenIds of loans found in query
function getLoanIds(address pool, uint256 start, uint256 end, bool active) external view returns(uint256[] memory tokenIds);
}// 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);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/"
],
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"address","name":"to","type":"address"}],"name":"batchLiquidate","outputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"refunds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"calcLPTokenDebt","outputs":[{"internalType":"uint256","name":"lpTokens","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"canBatchLiquidate","outputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"_liquidity","type":"uint256"},{"internalType":"uint256","name":"_collateral","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"canLiquidate","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"collateral","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getLoan","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"poolId","type":"address"},{"internalType":"uint96","name":"rateIndex","type":"uint96"},{"internalType":"uint128","name":"initLiquidity","type":"uint128"},{"internalType":"uint128","name":"lastLiquidity","type":"uint128"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"lpTokens","type":"uint256"},{"internalType":"uint128[]","name":"tokensHeld","type":"uint128[]"},{"internalType":"address","name":"refAddr","type":"address"},{"internalType":"uint16","name":"refFee","type":"uint16"},{"internalType":"uint8","name":"refType","type":"uint8"},{"internalType":"uint256","name":"px","type":"uint256"},{"internalType":"bool","name":"canLiquidate","type":"bool"},{"internalType":"uint256","name":"accFeeIndex","type":"uint256"},{"internalType":"uint256","name":"lastCFMMFeeIndex","type":"uint256"},{"internalType":"uint256","name":"LAST_BLOCK_NUMBER","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint8[]","name":"decimals","type":"uint8[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"string[]","name":"names","type":"string[]"},{"internalType":"address","name":"paramsStore","type":"address"},{"internalType":"address","name":"shortStrategy","type":"address"},{"internalType":"uint256","name":"BORROWED_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BALANCE","type":"uint256"},{"internalType":"uint256","name":"lastCFMMInvariant","type":"uint256"},{"internalType":"uint256","name":"lastCFMMTotalSupply","type":"uint256"},{"internalType":"uint256","name":"ltvThreshold","type":"uint256"},{"internalType":"uint256","name":"liquidationFee","type":"uint256"}],"internalType":"struct IGammaPool.LoanData","name":"loan","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"name":"getLoanIds","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"bool","name":"active","type":"bool"}],"name":"getLoans","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"poolId","type":"address"},{"internalType":"uint96","name":"rateIndex","type":"uint96"},{"internalType":"uint128","name":"initLiquidity","type":"uint128"},{"internalType":"uint128","name":"lastLiquidity","type":"uint128"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"lpTokens","type":"uint256"},{"internalType":"uint128[]","name":"tokensHeld","type":"uint128[]"},{"internalType":"address","name":"refAddr","type":"address"},{"internalType":"uint16","name":"refFee","type":"uint16"},{"internalType":"uint8","name":"refType","type":"uint8"},{"internalType":"uint256","name":"px","type":"uint256"},{"internalType":"bool","name":"canLiquidate","type":"bool"},{"internalType":"uint256","name":"accFeeIndex","type":"uint256"},{"internalType":"uint256","name":"lastCFMMFeeIndex","type":"uint256"},{"internalType":"uint256","name":"LAST_BLOCK_NUMBER","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint8[]","name":"decimals","type":"uint8[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"string[]","name":"names","type":"string[]"},{"internalType":"address","name":"paramsStore","type":"address"},{"internalType":"address","name":"shortStrategy","type":"address"},{"internalType":"uint256","name":"BORROWED_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BALANCE","type":"uint256"},{"internalType":"uint256","name":"lastCFMMInvariant","type":"uint256"},{"internalType":"uint256","name":"lastCFMMTotalSupply","type":"uint256"},{"internalType":"uint256","name":"ltvThreshold","type":"uint256"},{"internalType":"uint256","name":"liquidationFee","type":"uint256"}],"internalType":"struct IGammaPool.LoanData[]","name":"loans","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256[]","name":"tokenId","type":"uint256[]"},{"internalType":"bool","name":"active","type":"bool"}],"name":"getLoans","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"poolId","type":"address"},{"internalType":"uint96","name":"rateIndex","type":"uint96"},{"internalType":"uint128","name":"initLiquidity","type":"uint128"},{"internalType":"uint128","name":"lastLiquidity","type":"uint128"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"collateral","type":"uint256"},{"internalType":"uint256","name":"lpTokens","type":"uint256"},{"internalType":"uint128[]","name":"tokensHeld","type":"uint128[]"},{"internalType":"address","name":"refAddr","type":"address"},{"internalType":"uint16","name":"refFee","type":"uint16"},{"internalType":"uint8","name":"refType","type":"uint8"},{"internalType":"uint256","name":"px","type":"uint256"},{"internalType":"bool","name":"canLiquidate","type":"bool"},{"internalType":"uint256","name":"accFeeIndex","type":"uint256"},{"internalType":"uint256","name":"lastCFMMFeeIndex","type":"uint256"},{"internalType":"uint256","name":"LAST_BLOCK_NUMBER","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint8[]","name":"decimals","type":"uint8[]"},{"internalType":"string[]","name":"symbols","type":"string[]"},{"internalType":"string[]","name":"names","type":"string[]"},{"internalType":"address","name":"paramsStore","type":"address"},{"internalType":"address","name":"shortStrategy","type":"address"},{"internalType":"uint256","name":"BORROWED_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_INVARIANT","type":"uint256"},{"internalType":"uint256","name":"LP_TOKEN_BALANCE","type":"uint256"},{"internalType":"uint256","name":"lastCFMMInvariant","type":"uint256"},{"internalType":"uint256","name":"lastCFMMTotalSupply","type":"uint256"},{"internalType":"uint256","name":"ltvThreshold","type":"uint256"},{"internalType":"uint256","name":"liquidationFee","type":"uint256"}],"internalType":"struct IGammaPool.LoanData[]","name":"loans","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"liquidate","outputs":[{"internalType":"uint256","name":"refund","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"lpTokens","type":"uint256"},{"internalType":"bool","name":"calcLpTokens","type":"bool"},{"internalType":"address","name":"to","type":"address"}],"name":"liquidateWithLP","outputs":[{"internalType":"uint256[]","name":"refunds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5061281f806100206000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c8063b39ff73611610066578063b39ff7361461012f578063cd2a755d14610157578063dcf5843914610177578063f3b5b0b314610198578063f42b405d146101ba57600080fd5b80634914c008146100a3578063753a43d2146100c957806383f0454a146100e9578063912863aa146100fc578063a1c515861461010f575b600080fd5b6100b66100b13660046117bf565b6101cd565b6040519081526020015b60405180910390f35b6100dc6100d736600461180f565b6104e9565b6040516100c09190611bcf565b6100b66100f7366004611c31565b610572565b6100dc61010a366004611ca1565b610587565b61012261011d366004611c31565b6105ba565b6040516100c09190611cfd565b61014261013d366004611c31565b610696565b604080519283526020830191909152016100c0565b61016a610165366004611d10565b6106af565b6040516100c09190611d9f565b61018a610185366004611db2565b610a14565b6040516100c0929190611e0e565b6101ab6101a6366004611e33565b610cb8565b6040516100c093929190611e87565b61016a6101c836600461180f565b610cd7565b600080846001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561020e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102329190611eb7565b6040516359cffb9b60e11b81529091506001600160a01b0382169063b39ff736906102639088908890600401611edb565b602060405180830381865afa158015610280573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a49190611eff565b156104e1576000856001600160a01b0316633035aa9c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030d9190611eb7565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610357573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037b9190611f1c565b6040516301057c4960e61b8152600481018890529091506001600160a01b0388169063415f12409060240160408051808303816000875af11580156103c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e89190611f35565b6040516370a0823160e01b8152306004820152909550600091506001600160a01b038416906370a0823190602401602060405180830381865afa158015610433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104579190611f1c565b9050818111156104dd576001600160a01b03831663a9059cbb8761047b8585611f6f565b6040518363ffffffff1660e01b8152600401610498929190611edb565b6020604051808303816000875af11580156104b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104db9190611eff565b505b5050505b509392505050565b60405163af800bf960e01b8152600481018490526024810183905281151560448201526060906001600160a01b0386169063af800bf9906064015b600060405180830381865afa158015610541573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261056991908101906124de565b95945050505050565b600061057e8383610df9565b90505b92915050565b6040516359df61a160e01b81526060906001600160a01b038616906359df61a190610524908790879087906004016125c0565b6105c2611670565b826001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106249190611eb7565b6001600160a01b031663185cc75184846040518363ffffffff1660e01b8152600401610651929190611edb565b600060405180830381865afa15801561066e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261057e91908101906125e6565b6000806106a38484610ef1565b915091505b9250929050565b60606000866001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107159190611eb7565b6040516359cffb9b60e11b81529091506001600160a01b0382169063b39ff73690610746908a908a90600401611edb565b602060405180830381865afa158015610763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107879190611eff565b15610a0a5783156107b85761271061079f8888610df9565b6107ab9061271261261a565b6107b59190612647565b94505b6000876001600160a01b0316633035aa9c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081c9190611eb7565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088a9190611f1c565b90506108978988336110c7565b604051633bfe638960e21b8152600481018990526001600160a01b038a169063eff98e24906024016000604051808303816000875af11580156108de573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109069190810190612669565b6040516370a0823160e01b8152306004820152909550600091506001600160a01b038416906370a0823190602401602060405180830381865afa158015610951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109759190611f1c565b90506109828a86886111ac565b81811115610a06576001600160a01b03831663a9059cbb336109a48585611f6f565b6040518363ffffffff1660e01b81526004016109c1929190611edb565b6020604051808303816000875af11580156109e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a049190611eff565b505b5050505b5095945050505050565b6060806000610a248787876112d5565b5090935090508015610cae576000612710610a3f898461158b565b610a4b9061271261261a565b610a559190612647565b90506000886001600160a01b0316633035aa9c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610abb9190611eb7565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b299190611f1c565b9050610b368a84336110c7565b604051638015d92560e01b81526001600160a01b038b1690638015d92590610b62908990600401611d9f565b6000604051808303816000875af1158015610b81573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ba99190810190612669565b6040516370a0823160e01b8152306004820152909650600091506001600160a01b038416906370a0823190602401602060405180830381865afa158015610bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c189190611f1c565b9050610c258b878a6111ac565b81811115610ca9576001600160a01b03831663a9059cbb33610c478585611f6f565b6040518363ffffffff1660e01b8152600401610c64929190611edb565b6020604051808303816000875af1158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190611eff565b505b505050505b5094509492505050565b6060600080610cc88686866112d5565b92509250925093509350939050565b60405163af800bf960e01b8152600481018490526024810183905281151560448201526060906000906001600160a01b0387169063af800bf990606401600060405180830381865afa158015610d31573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d5991908101906124de565b905080516001600160401b03811115610d7457610d74611f82565b604051908082528060200260200182016040528015610d9d578160200160208202803683370190505b50915060005b8151811015610def57818181518110610dbe57610dbe612705565b602002602001015160200151838281518110610ddc57610ddc612705565b6020908102919091010152600101610da3565b5050949350505050565b600080836001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5e9190611eb7565b6001600160a01b031663185cc75185856040518363ffffffff1660e01b8152600401610e8b929190611edb565b600060405180830381865afa158015610ea8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed091908101906125e6565b9050610ee9848260c001516001600160801b031661158b565b949350505050565b6000806000846001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f589190611eb7565b6040516359cffb9b60e11b81529091506001600160a01b0382169063b39ff73690610f899088908890600401611edb565b602060405180830381865afa158015610fa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fca9190611eff565b156110bf5760405163185cc75160e01b81526000906001600160a01b0383169063185cc751906110009089908990600401611edb565b600060405180830381865afa15801561101d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261104591908101906125e6565b90508060c001516001600160801b031693506110bb81610120015160018151811061107257611072612705565b60200260200101516001600160801b031682610120015160008151811061109b5761109b612705565b60200260200101516001600160801b03166110b6919061261a565b611612565b9250505b509250929050565b826001600160a01b0316633035aa9c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111299190611eb7565b6040516323b872dd60e01b81526001600160a01b03838116600483015285811660248301526044820185905291909116906323b872dd906064016020604051808303816000875af1158015611182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a69190611eff565b50505050565b6000836001600160a01b0316639d63848a6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156111ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611214919081019061271b565b905060005b83518110156112ce5781818151811061123457611234612705565b60200260200101516001600160a01b031663a9059cbb8486848151811061125d5761125d612705565b60200260200101516040518363ffffffff1660e01b8152600401611282929190611edb565b6020604051808303816000875af11580156112a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c59190611eff565b50600101611219565b5050505050565b60606000806000866001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190611eb7565b6001600160a01b0316637edd64b688888860016040518563ffffffff1660e01b8152600401611370949392919061274f565b600060405180830381865afa15801561138d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113b591908101906124de565b9050600081516001600160401b038111156113d2576113d2611f82565b6040519080825280602002602001820160405280156113fb578160200160208202803683370190505b5090506000611408611670565b60005b84518110156114ed5784818151811061142657611426612705565b602002602001015191506000826000015111156114e057816101c00151156114db57816020015184848151811061145f5761145f612705565b602090810291909101015260c0820151611482906001600160801b031688612787565b96506114c882610120015160018151811061149f5761149f612705565b60200260200101516001600160801b031683610120015160008151811061109b5761109b612705565b6114d29087612787565b95508260010192505b6114e5565b6114ed565b60010161140b565b50816001600160401b0381111561150657611506611f82565b60405190808252806020026020018201604052801561152f578160200160208202803683370190505b50965060005b875181101561157d5783818151811061155057611550612705565b602002602001015188828151811061156a5761156a612705565b6020908102919091010152600101611535565b505050505093509350939050565b6000806000846001600160a01b031663cd1891876040518163ffffffff1660e01b8152600401600060405180830381865afa1580156115ce573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115f6919081019061279a565b9250925050818185611608919061261a565b6105699190612647565b60006003821115611661575080600160028204015b8181101561165b5780915060028182858161164457611644612631565b04018161165357611653612631565b049050611627565b50919050565b811561166b575060015b919050565b604051806103e00160405280600081526020016000815260200160006001600160a01b0316815260200160006001600160601b0316815260200160006001600160801b0316815260200160006001600160801b0316815260200160006001600160801b0316815260200160008152602001600081526020016060815260200160006001600160a01b03168152602001600061ffff168152602001600060ff168152602001600081526020016000151581526020016000815260200160008152602001600081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b03811681146117bc57600080fd5b50565b6000806000606084860312156117d457600080fd5b83356117df816117a7565b92506020840135915060408401356117f6816117a7565b809150509250925092565b80151581146117bc57600080fd5b6000806000806080858703121561182557600080fd5b8435611830816117a7565b93506020850135925060408501359150606085013561184e81611801565b939692955090935050565b600081518084526020808501945080840160005b838110156118925781516001600160801b03168752958201959082019060010161186d565b509495945050505050565b600081518084526020808501945080840160005b838110156118925781516001600160a01b0316875295820195908201906001016118b1565b600081518084526020808501945080840160005b8381101561189257815160ff16875295820195908201906001016118ea565b60005b8381101561192457818101518382015260200161190c565b50506000910152565b600081518084526020808501808196508360051b8101915082860160005b8581101561198d5782840389528151805180865261196e81888801898501611909565b99860199601f01601f191694909401850193509084019060010161194b565b5091979650505050505050565b60006103e0825184526020830151602085015260408301516119c760408601826001600160a01b03169052565b5060608301516119e260608601826001600160601b03169052565b5060808301516119fd60808601826001600160801b03169052565b5060a0830151611a1860a08601826001600160801b03169052565b5060c0830151611a3360c08601826001600160801b03169052565b5060e083015160e0850152610100808401518186015250610120808401518282870152611a6283870182611859565b9250505061014080840151611a81828701826001600160a01b03169052565b50506101608381015161ffff16908501526101808084015160ff16908501526101a080840151908501526101c0808401511515908501526101e08084015190850152610200808401519085015261022080840151908501526102408084015185830382870152611af1838261189d565b925050506102608084015185830382870152611b0d83826118d6565b925050506102808084015185830382870152611b29838261192d565b925050506102a08084015185830382870152611b45838261192d565b925050506102c080840151611b64828701826001600160a01b03169052565b50506102e0838101516001600160a01b031690850152610300808401519085015261032080840151908501526103408084015190850152610360808401519085015261038080840151908501526103a080840151908501526103c09283015192909301919091525090565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015611c2457603f19888603018452611c1285835161199a565b94509285019290850190600101611bf6565b5092979650505050505050565b60008060408385031215611c4457600080fd5b8235611c4f816117a7565b946020939093013593505050565b60008083601f840112611c6f57600080fd5b5081356001600160401b03811115611c8657600080fd5b6020830191508360208260051b85010111156106a857600080fd5b60008060008060608587031215611cb757600080fd5b8435611cc2816117a7565b935060208501356001600160401b03811115611cdd57600080fd5b611ce987828801611c5d565b909450925050604085013561184e81611801565b60208152600061057e602083018461199a565b600080600080600060a08688031215611d2857600080fd5b8535611d33816117a7565b945060208601359350604086013592506060860135611d5181611801565b91506080860135611d61816117a7565b809150509295509295909350565b600081518084526020808501945080840160005b8381101561189257815187529582019590820190600101611d83565b60208152600061057e6020830184611d6f565b60008060008060608587031215611dc857600080fd5b8435611dd3816117a7565b935060208501356001600160401b03811115611dee57600080fd5b611dfa87828801611c5d565b909450925050604085013561184e816117a7565b604081526000611e216040830185611d6f565b82810360208401526105698185611d6f565b600080600060408486031215611e4857600080fd5b8335611e53816117a7565b925060208401356001600160401b03811115611e6e57600080fd5b611e7a86828701611c5d565b9497909650939450505050565b606081526000611e9a6060830186611d6f565b60208301949094525060400152919050565b805161166b816117a7565b600060208284031215611ec957600080fd5b8151611ed4816117a7565b9392505050565b6001600160a01b03929092168252602082015260400190565b805161166b81611801565b600060208284031215611f1157600080fd5b8151611ed481611801565b600060208284031215611f2e57600080fd5b5051919050565b60008060408385031215611f4857600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b8181038181111561058157610581611f59565b634e487b7160e01b600052604160045260246000fd5b6040516103e081016001600160401b0381118282101715611fbb57611fbb611f82565b60405290565b604051601f8201601f191681016001600160401b0381118282101715611fe957611fe9611f82565b604052919050565b60006001600160401b0382111561200a5761200a611f82565b5060051b60200190565b80516001600160601b038116811461166b57600080fd5b80516001600160801b038116811461166b57600080fd5b600082601f83011261205357600080fd5b8151602061206861206383611ff1565b611fc1565b82815260059290921b8401810191818101908684111561208757600080fd5b8286015b848110156120a95761209c8161202b565b835291830191830161208b565b509695505050505050565b805161ffff8116811461166b57600080fd5b805160ff8116811461166b57600080fd5b600082601f8301126120e857600080fd5b815160206120f861206383611ff1565b82815260059290921b8401810191818101908684111561211757600080fd5b8286015b848110156120a957805161212e816117a7565b835291830191830161211b565b600082601f83011261214c57600080fd5b8151602061215c61206383611ff1565b82815260059290921b8401810191818101908684111561217b57600080fd5b8286015b848110156120a957612190816120c6565b835291830191830161217f565b6000601f83818401126121af57600080fd5b825160206121bf61206383611ff1565b82815260059290921b850181019181810190878411156121de57600080fd5b8287015b848110156122745780516001600160401b03808211156122025760008081fd5b818a0191508a603f8301126122175760008081fd5b8582015160408282111561222d5761222d611f82565b61223e828b01601f19168901611fc1565b92508183528c818386010111156122555760008081fd5b61226482898501838701611909565b50508452509183019183016121e2565b50979650505050505050565b60006103e0828403121561229357600080fd5b61229b611f98565b905081518152602082015160208201526122b760408301611eac565b60408201526122c860608301612014565b60608201526122d96080830161202b565b60808201526122ea60a0830161202b565b60a08201526122fb60c0830161202b565b60c082015260e082015160e0820152610100808301518183015250610120808301516001600160401b038082111561233257600080fd5b61233e86838701612042565b838501526101409250612352838601611eac565b8385015261016092506123668386016120b4565b83850152610180925061237a8386016120c6565b838501526101a0925082850151838501526101c0925061239b838601611ef4565b92840192909252506101e0838101519083015261020080840151908301526102208084015190830152610240808401519091808211156123da57600080fd5b6123e6868387016120d7565b8385015261026092508285015191508082111561240257600080fd5b61240e8683870161213b565b8385015261028092508285015191508082111561242a57600080fd5b6124368683870161219d565b838501526102a092508285015191508082111561245257600080fd5b5061245f8582860161219d565b8284015250506102c0612473818401611eac565b908201526102e0612485838201611eac565b90820152610300828101519082015261032080830151908201526103408083015190820152610360808301519082015261038080830151908201526103a080830151908201526103c09182015191810191909152919050565b600060208083850312156124f157600080fd5b82516001600160401b038082111561250857600080fd5b818501915085601f83011261251c57600080fd5b815161252a61206382611ff1565b81815260059190911b8301840190848101908883111561254957600080fd5b8585015b83811015612581578051858111156125655760008081fd5b6125738b89838a0101612280565b84525091860191860161254d565b5098975050505050505050565b81835260006001600160fb1b038311156125a757600080fd5b8260051b80836020870137939093016020019392505050565b6040815260006125d460408301858761258e565b90508215156020830152949350505050565b6000602082840312156125f857600080fd5b81516001600160401b0381111561260e57600080fd5b610ee984828501612280565b808202811582820484141761058157610581611f59565b634e487b7160e01b600052601260045260246000fd5b60008261266457634e487b7160e01b600052601260045260246000fd5b500490565b6000806040838503121561267c57600080fd5b825191506020808401516001600160401b0381111561269a57600080fd5b8401601f810186136126ab57600080fd5b80516126b961206382611ff1565b81815260059190911b820183019083810190888311156126d857600080fd5b928401925b828410156126f6578351825292840192908401906126dd565b80955050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561272d57600080fd5b81516001600160401b0381111561274357600080fd5b610ee9848285016120d7565b6001600160a01b0385168152606060208201819052600090612774908301858761258e565b9050821515604083015295945050505050565b8082018082111561058157610581611f59565b6000806000606084860312156127af57600080fd5b83516001600160401b038111156127c557600080fd5b6127d186828701612042565b9350506020840151915060408401519050925092509256fea2646970667358221220b576600dcec3bd4a96e9fbf5c1706f2913ae80f30d88e418f4966b112887526864736f6c63430008150033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061009e5760003560e01c8063b39ff73611610066578063b39ff7361461012f578063cd2a755d14610157578063dcf5843914610177578063f3b5b0b314610198578063f42b405d146101ba57600080fd5b80634914c008146100a3578063753a43d2146100c957806383f0454a146100e9578063912863aa146100fc578063a1c515861461010f575b600080fd5b6100b66100b13660046117bf565b6101cd565b6040519081526020015b60405180910390f35b6100dc6100d736600461180f565b6104e9565b6040516100c09190611bcf565b6100b66100f7366004611c31565b610572565b6100dc61010a366004611ca1565b610587565b61012261011d366004611c31565b6105ba565b6040516100c09190611cfd565b61014261013d366004611c31565b610696565b604080519283526020830191909152016100c0565b61016a610165366004611d10565b6106af565b6040516100c09190611d9f565b61018a610185366004611db2565b610a14565b6040516100c0929190611e0e565b6101ab6101a6366004611e33565b610cb8565b6040516100c093929190611e87565b61016a6101c836600461180f565b610cd7565b600080846001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561020e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102329190611eb7565b6040516359cffb9b60e11b81529091506001600160a01b0382169063b39ff736906102639088908890600401611edb565b602060405180830381865afa158015610280573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102a49190611eff565b156104e1576000856001600160a01b0316633035aa9c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030d9190611eb7565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610357573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061037b9190611f1c565b6040516301057c4960e61b8152600481018890529091506001600160a01b0388169063415f12409060240160408051808303816000875af11580156103c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e89190611f35565b6040516370a0823160e01b8152306004820152909550600091506001600160a01b038416906370a0823190602401602060405180830381865afa158015610433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104579190611f1c565b9050818111156104dd576001600160a01b03831663a9059cbb8761047b8585611f6f565b6040518363ffffffff1660e01b8152600401610498929190611edb565b6020604051808303816000875af11580156104b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104db9190611eff565b505b5050505b509392505050565b60405163af800bf960e01b8152600481018490526024810183905281151560448201526060906001600160a01b0386169063af800bf9906064015b600060405180830381865afa158015610541573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261056991908101906124de565b95945050505050565b600061057e8383610df9565b90505b92915050565b6040516359df61a160e01b81526060906001600160a01b038616906359df61a190610524908790879087906004016125c0565b6105c2611670565b826001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106249190611eb7565b6001600160a01b031663185cc75184846040518363ffffffff1660e01b8152600401610651929190611edb565b600060405180830381865afa15801561066e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261057e91908101906125e6565b6000806106a38484610ef1565b915091505b9250929050565b60606000866001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107159190611eb7565b6040516359cffb9b60e11b81529091506001600160a01b0382169063b39ff73690610746908a908a90600401611edb565b602060405180830381865afa158015610763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107879190611eff565b15610a0a5783156107b85761271061079f8888610df9565b6107ab9061271261261a565b6107b59190612647565b94505b6000876001600160a01b0316633035aa9c6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061081c9190611eb7565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088a9190611f1c565b90506108978988336110c7565b604051633bfe638960e21b8152600481018990526001600160a01b038a169063eff98e24906024016000604051808303816000875af11580156108de573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109069190810190612669565b6040516370a0823160e01b8152306004820152909550600091506001600160a01b038416906370a0823190602401602060405180830381865afa158015610951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109759190611f1c565b90506109828a86886111ac565b81811115610a06576001600160a01b03831663a9059cbb336109a48585611f6f565b6040518363ffffffff1660e01b81526004016109c1929190611edb565b6020604051808303816000875af11580156109e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a049190611eff565b505b5050505b5095945050505050565b6060806000610a248787876112d5565b5090935090508015610cae576000612710610a3f898461158b565b610a4b9061271261261a565b610a559190612647565b90506000886001600160a01b0316633035aa9c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610abb9190611eb7565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b299190611f1c565b9050610b368a84336110c7565b604051638015d92560e01b81526001600160a01b038b1690638015d92590610b62908990600401611d9f565b6000604051808303816000875af1158015610b81573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ba99190810190612669565b6040516370a0823160e01b8152306004820152909650600091506001600160a01b038416906370a0823190602401602060405180830381865afa158015610bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c189190611f1c565b9050610c258b878a6111ac565b81811115610ca9576001600160a01b03831663a9059cbb33610c478585611f6f565b6040518363ffffffff1660e01b8152600401610c64929190611edb565b6020604051808303816000875af1158015610c83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca79190611eff565b505b505050505b5094509492505050565b6060600080610cc88686866112d5565b92509250925093509350939050565b60405163af800bf960e01b8152600481018490526024810183905281151560448201526060906000906001600160a01b0387169063af800bf990606401600060405180830381865afa158015610d31573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d5991908101906124de565b905080516001600160401b03811115610d7457610d74611f82565b604051908082528060200260200182016040528015610d9d578160200160208202803683370190505b50915060005b8151811015610def57818181518110610dbe57610dbe612705565b602002602001015160200151838281518110610ddc57610ddc612705565b6020908102919091010152600101610da3565b5050949350505050565b600080836001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5e9190611eb7565b6001600160a01b031663185cc75185856040518363ffffffff1660e01b8152600401610e8b929190611edb565b600060405180830381865afa158015610ea8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ed091908101906125e6565b9050610ee9848260c001516001600160801b031661158b565b949350505050565b6000806000846001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f589190611eb7565b6040516359cffb9b60e11b81529091506001600160a01b0382169063b39ff73690610f899088908890600401611edb565b602060405180830381865afa158015610fa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fca9190611eff565b156110bf5760405163185cc75160e01b81526000906001600160a01b0383169063185cc751906110009089908990600401611edb565b600060405180830381865afa15801561101d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261104591908101906125e6565b90508060c001516001600160801b031693506110bb81610120015160018151811061107257611072612705565b60200260200101516001600160801b031682610120015160008151811061109b5761109b612705565b60200260200101516001600160801b03166110b6919061261a565b611612565b9250505b509250929050565b826001600160a01b0316633035aa9c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111299190611eb7565b6040516323b872dd60e01b81526001600160a01b03838116600483015285811660248301526044820185905291909116906323b872dd906064016020604051808303816000875af1158015611182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a69190611eff565b50505050565b6000836001600160a01b0316639d63848a6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156111ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611214919081019061271b565b905060005b83518110156112ce5781818151811061123457611234612705565b60200260200101516001600160a01b031663a9059cbb8486848151811061125d5761125d612705565b60200260200101516040518363ffffffff1660e01b8152600401611282929190611edb565b6020604051808303816000875af11580156112a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112c59190611eff565b50600101611219565b5050505050565b60606000806000866001600160a01b031663f30878c16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190611eb7565b6001600160a01b0316637edd64b688888860016040518563ffffffff1660e01b8152600401611370949392919061274f565b600060405180830381865afa15801561138d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113b591908101906124de565b9050600081516001600160401b038111156113d2576113d2611f82565b6040519080825280602002602001820160405280156113fb578160200160208202803683370190505b5090506000611408611670565b60005b84518110156114ed5784818151811061142657611426612705565b602002602001015191506000826000015111156114e057816101c00151156114db57816020015184848151811061145f5761145f612705565b602090810291909101015260c0820151611482906001600160801b031688612787565b96506114c882610120015160018151811061149f5761149f612705565b60200260200101516001600160801b031683610120015160008151811061109b5761109b612705565b6114d29087612787565b95508260010192505b6114e5565b6114ed565b60010161140b565b50816001600160401b0381111561150657611506611f82565b60405190808252806020026020018201604052801561152f578160200160208202803683370190505b50965060005b875181101561157d5783818151811061155057611550612705565b602002602001015188828151811061156a5761156a612705565b6020908102919091010152600101611535565b505050505093509350939050565b6000806000846001600160a01b031663cd1891876040518163ffffffff1660e01b8152600401600060405180830381865afa1580156115ce573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115f6919081019061279a565b9250925050818185611608919061261a565b6105699190612647565b60006003821115611661575080600160028204015b8181101561165b5780915060028182858161164457611644612631565b04018161165357611653612631565b049050611627565b50919050565b811561166b575060015b919050565b604051806103e00160405280600081526020016000815260200160006001600160a01b0316815260200160006001600160601b0316815260200160006001600160801b0316815260200160006001600160801b0316815260200160006001600160801b0316815260200160008152602001600081526020016060815260200160006001600160a01b03168152602001600061ffff168152602001600060ff168152602001600081526020016000151581526020016000815260200160008152602001600081526020016060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6001600160a01b03811681146117bc57600080fd5b50565b6000806000606084860312156117d457600080fd5b83356117df816117a7565b92506020840135915060408401356117f6816117a7565b809150509250925092565b80151581146117bc57600080fd5b6000806000806080858703121561182557600080fd5b8435611830816117a7565b93506020850135925060408501359150606085013561184e81611801565b939692955090935050565b600081518084526020808501945080840160005b838110156118925781516001600160801b03168752958201959082019060010161186d565b509495945050505050565b600081518084526020808501945080840160005b838110156118925781516001600160a01b0316875295820195908201906001016118b1565b600081518084526020808501945080840160005b8381101561189257815160ff16875295820195908201906001016118ea565b60005b8381101561192457818101518382015260200161190c565b50506000910152565b600081518084526020808501808196508360051b8101915082860160005b8581101561198d5782840389528151805180865261196e81888801898501611909565b99860199601f01601f191694909401850193509084019060010161194b565b5091979650505050505050565b60006103e0825184526020830151602085015260408301516119c760408601826001600160a01b03169052565b5060608301516119e260608601826001600160601b03169052565b5060808301516119fd60808601826001600160801b03169052565b5060a0830151611a1860a08601826001600160801b03169052565b5060c0830151611a3360c08601826001600160801b03169052565b5060e083015160e0850152610100808401518186015250610120808401518282870152611a6283870182611859565b9250505061014080840151611a81828701826001600160a01b03169052565b50506101608381015161ffff16908501526101808084015160ff16908501526101a080840151908501526101c0808401511515908501526101e08084015190850152610200808401519085015261022080840151908501526102408084015185830382870152611af1838261189d565b925050506102608084015185830382870152611b0d83826118d6565b925050506102808084015185830382870152611b29838261192d565b925050506102a08084015185830382870152611b45838261192d565b925050506102c080840151611b64828701826001600160a01b03169052565b50506102e0838101516001600160a01b031690850152610300808401519085015261032080840151908501526103408084015190850152610360808401519085015261038080840151908501526103a080840151908501526103c09283015192909301919091525090565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015611c2457603f19888603018452611c1285835161199a565b94509285019290850190600101611bf6565b5092979650505050505050565b60008060408385031215611c4457600080fd5b8235611c4f816117a7565b946020939093013593505050565b60008083601f840112611c6f57600080fd5b5081356001600160401b03811115611c8657600080fd5b6020830191508360208260051b85010111156106a857600080fd5b60008060008060608587031215611cb757600080fd5b8435611cc2816117a7565b935060208501356001600160401b03811115611cdd57600080fd5b611ce987828801611c5d565b909450925050604085013561184e81611801565b60208152600061057e602083018461199a565b600080600080600060a08688031215611d2857600080fd5b8535611d33816117a7565b945060208601359350604086013592506060860135611d5181611801565b91506080860135611d61816117a7565b809150509295509295909350565b600081518084526020808501945080840160005b8381101561189257815187529582019590820190600101611d83565b60208152600061057e6020830184611d6f565b60008060008060608587031215611dc857600080fd5b8435611dd3816117a7565b935060208501356001600160401b03811115611dee57600080fd5b611dfa87828801611c5d565b909450925050604085013561184e816117a7565b604081526000611e216040830185611d6f565b82810360208401526105698185611d6f565b600080600060408486031215611e4857600080fd5b8335611e53816117a7565b925060208401356001600160401b03811115611e6e57600080fd5b611e7a86828701611c5d565b9497909650939450505050565b606081526000611e9a6060830186611d6f565b60208301949094525060400152919050565b805161166b816117a7565b600060208284031215611ec957600080fd5b8151611ed4816117a7565b9392505050565b6001600160a01b03929092168252602082015260400190565b805161166b81611801565b600060208284031215611f1157600080fd5b8151611ed481611801565b600060208284031215611f2e57600080fd5b5051919050565b60008060408385031215611f4857600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601160045260246000fd5b8181038181111561058157610581611f59565b634e487b7160e01b600052604160045260246000fd5b6040516103e081016001600160401b0381118282101715611fbb57611fbb611f82565b60405290565b604051601f8201601f191681016001600160401b0381118282101715611fe957611fe9611f82565b604052919050565b60006001600160401b0382111561200a5761200a611f82565b5060051b60200190565b80516001600160601b038116811461166b57600080fd5b80516001600160801b038116811461166b57600080fd5b600082601f83011261205357600080fd5b8151602061206861206383611ff1565b611fc1565b82815260059290921b8401810191818101908684111561208757600080fd5b8286015b848110156120a95761209c8161202b565b835291830191830161208b565b509695505050505050565b805161ffff8116811461166b57600080fd5b805160ff8116811461166b57600080fd5b600082601f8301126120e857600080fd5b815160206120f861206383611ff1565b82815260059290921b8401810191818101908684111561211757600080fd5b8286015b848110156120a957805161212e816117a7565b835291830191830161211b565b600082601f83011261214c57600080fd5b8151602061215c61206383611ff1565b82815260059290921b8401810191818101908684111561217b57600080fd5b8286015b848110156120a957612190816120c6565b835291830191830161217f565b6000601f83818401126121af57600080fd5b825160206121bf61206383611ff1565b82815260059290921b850181019181810190878411156121de57600080fd5b8287015b848110156122745780516001600160401b03808211156122025760008081fd5b818a0191508a603f8301126122175760008081fd5b8582015160408282111561222d5761222d611f82565b61223e828b01601f19168901611fc1565b92508183528c818386010111156122555760008081fd5b61226482898501838701611909565b50508452509183019183016121e2565b50979650505050505050565b60006103e0828403121561229357600080fd5b61229b611f98565b905081518152602082015160208201526122b760408301611eac565b60408201526122c860608301612014565b60608201526122d96080830161202b565b60808201526122ea60a0830161202b565b60a08201526122fb60c0830161202b565b60c082015260e082015160e0820152610100808301518183015250610120808301516001600160401b038082111561233257600080fd5b61233e86838701612042565b838501526101409250612352838601611eac565b8385015261016092506123668386016120b4565b83850152610180925061237a8386016120c6565b838501526101a0925082850151838501526101c0925061239b838601611ef4565b92840192909252506101e0838101519083015261020080840151908301526102208084015190830152610240808401519091808211156123da57600080fd5b6123e6868387016120d7565b8385015261026092508285015191508082111561240257600080fd5b61240e8683870161213b565b8385015261028092508285015191508082111561242a57600080fd5b6124368683870161219d565b838501526102a092508285015191508082111561245257600080fd5b5061245f8582860161219d565b8284015250506102c0612473818401611eac565b908201526102e0612485838201611eac565b90820152610300828101519082015261032080830151908201526103408083015190820152610360808301519082015261038080830151908201526103a080830151908201526103c09182015191810191909152919050565b600060208083850312156124f157600080fd5b82516001600160401b038082111561250857600080fd5b818501915085601f83011261251c57600080fd5b815161252a61206382611ff1565b81815260059190911b8301840190848101908883111561254957600080fd5b8585015b83811015612581578051858111156125655760008081fd5b6125738b89838a0101612280565b84525091860191860161254d565b5098975050505050505050565b81835260006001600160fb1b038311156125a757600080fd5b8260051b80836020870137939093016020019392505050565b6040815260006125d460408301858761258e565b90508215156020830152949350505050565b6000602082840312156125f857600080fd5b81516001600160401b0381111561260e57600080fd5b610ee984828501612280565b808202811582820484141761058157610581611f59565b634e487b7160e01b600052601260045260246000fd5b60008261266457634e487b7160e01b600052601260045260246000fd5b500490565b6000806040838503121561267c57600080fd5b825191506020808401516001600160401b0381111561269a57600080fd5b8401601f810186136126ab57600080fd5b80516126b961206382611ff1565b81815260059190911b820183019083810190888311156126d857600080fd5b928401925b828410156126f6578351825292840192908401906126dd565b80955050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561272d57600080fd5b81516001600160401b0381111561274357600080fd5b610ee9848285016120d7565b6001600160a01b0385168152606060208201819052600090612774908301858761258e565b9050821515604083015295945050505050565b8082018082111561058157610581611f59565b6000806000606084860312156127af57600080fd5b83516001600160401b038111156127c557600080fd5b6127d186828701612042565b9350506020840151915060408401519050925092509256fea2646970667358221220b576600dcec3bd4a96e9fbf5c1706f2913ae80f30d88e418f4966b112887526864736f6c63430008150033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.