Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
TokenTracker
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CometWithExtendedAssetList
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 1 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
import "./CometMainInterface.sol";
import "./IERC20NonStandard.sol";
import "./IPriceFeed.sol";
import "./IAssetListFactory.sol";
import "./IAssetListFactoryHolder.sol";
import "./IAssetList.sol";
/**
* @title Compound's Comet Contract
* @notice An efficient monolithic money market protocol
* @author Compound
*/
contract CometWithExtendedAssetList is CometMainInterface {
/** General configuration constants **/
/// @notice The admin of the protocol
address public override immutable governor;
/// @notice The account which may trigger pauses
address public override immutable pauseGuardian;
/// @notice The address of the base token contract
address public override immutable baseToken;
/// @notice The address of the price feed for the base token
address public override immutable baseTokenPriceFeed;
/// @notice The address of the extension contract delegate
address public override immutable extensionDelegate;
/// @notice The point in the supply rates separating the low interest rate slope and the high interest rate slope (factor)
/// @dev uint64
uint public override immutable supplyKink;
/// @notice Per second supply interest rate slope applied when utilization is below kink (factor)
/// @dev uint64
uint public override immutable supplyPerSecondInterestRateSlopeLow;
/// @notice Per second supply interest rate slope applied when utilization is above kink (factor)
/// @dev uint64
uint public override immutable supplyPerSecondInterestRateSlopeHigh;
/// @notice Per second supply base interest rate (factor)
/// @dev uint64
uint public override immutable supplyPerSecondInterestRateBase;
/// @notice The point in the borrow rate separating the low interest rate slope and the high interest rate slope (factor)
/// @dev uint64
uint public override immutable borrowKink;
/// @notice Per second borrow interest rate slope applied when utilization is below kink (factor)
/// @dev uint64
uint public override immutable borrowPerSecondInterestRateSlopeLow;
/// @notice Per second borrow interest rate slope applied when utilization is above kink (factor)
/// @dev uint64
uint public override immutable borrowPerSecondInterestRateSlopeHigh;
/// @notice Per second borrow base interest rate (factor)
/// @dev uint64
uint public override immutable borrowPerSecondInterestRateBase;
/// @notice The fraction of the liquidation penalty that goes to buyers of collateral instead of the protocol
/// @dev uint64
uint public override immutable storeFrontPriceFactor;
/// @notice The scale for base token (must be less than 18 decimals)
/// @dev uint64
uint public override immutable baseScale;
/// @notice The scale for reward tracking
/// @dev uint64
uint public override immutable trackingIndexScale;
/// @notice The speed at which supply rewards are tracked (in trackingIndexScale)
/// @dev uint64
uint public override immutable baseTrackingSupplySpeed;
/// @notice The speed at which borrow rewards are tracked (in trackingIndexScale)
/// @dev uint64
uint public override immutable baseTrackingBorrowSpeed;
/// @notice The minimum amount of base principal wei for rewards to accrue
/// @dev This must be large enough so as to prevent division by base wei from overflowing the 64 bit indices
/// @dev uint104
uint public override immutable baseMinForRewards;
/// @notice The minimum base amount required to initiate a borrow
uint public override immutable baseBorrowMin;
/// @notice The minimum base token reserves which must be held before collateral is hodled
uint public override immutable targetReserves;
/// @notice The number of decimals for wrapped base token
uint8 public override immutable decimals;
/// @notice The number of assets this contract actually supports
uint8 public override immutable numAssets;
/// @notice Factor to divide by when accruing rewards in order to preserve 6 decimals (i.e. baseScale / 1e6)
uint internal immutable accrualDescaleFactor;
/// @notice The address of the asset list
address immutable public assetList;
uint8 internal constant MAX_ASSETS_FOR_ASSET_LIST = 24;
/**
* @notice Construct a new protocol instance
* @param config The mapping of initial/constant parameters
**/
constructor(Configuration memory config) {
// Sanity checks
uint8 decimals_ = IERC20NonStandard(config.baseToken).decimals();
if (decimals_ > MAX_BASE_DECIMALS) revert BadDecimals();
if (config.storeFrontPriceFactor > FACTOR_SCALE) revert BadDiscount();
if (config.assetConfigs.length > MAX_ASSETS_FOR_ASSET_LIST) revert TooManyAssets();
if (config.baseMinForRewards == 0) revert BadMinimum();
if (IPriceFeed(config.baseTokenPriceFeed).decimals() != PRICE_FEED_DECIMALS) revert BadDecimals();
// Copy configuration
unchecked {
governor = config.governor;
pauseGuardian = config.pauseGuardian;
baseToken = config.baseToken;
baseTokenPriceFeed = config.baseTokenPriceFeed;
extensionDelegate = config.extensionDelegate;
storeFrontPriceFactor = config.storeFrontPriceFactor;
decimals = decimals_;
baseScale = uint64(10 ** decimals_);
trackingIndexScale = config.trackingIndexScale;
if (baseScale < BASE_ACCRUAL_SCALE) revert BadDecimals();
accrualDescaleFactor = baseScale / BASE_ACCRUAL_SCALE;
baseMinForRewards = config.baseMinForRewards;
baseTrackingSupplySpeed = config.baseTrackingSupplySpeed;
baseTrackingBorrowSpeed = config.baseTrackingBorrowSpeed;
baseBorrowMin = config.baseBorrowMin;
targetReserves = config.targetReserves;
}
// Set interest rate model configs
unchecked {
supplyKink = config.supplyKink;
supplyPerSecondInterestRateSlopeLow = config.supplyPerYearInterestRateSlopeLow / SECONDS_PER_YEAR;
supplyPerSecondInterestRateSlopeHigh = config.supplyPerYearInterestRateSlopeHigh / SECONDS_PER_YEAR;
supplyPerSecondInterestRateBase = config.supplyPerYearInterestRateBase / SECONDS_PER_YEAR;
borrowKink = config.borrowKink;
borrowPerSecondInterestRateSlopeLow = config.borrowPerYearInterestRateSlopeLow / SECONDS_PER_YEAR;
borrowPerSecondInterestRateSlopeHigh = config.borrowPerYearInterestRateSlopeHigh / SECONDS_PER_YEAR;
borrowPerSecondInterestRateBase = config.borrowPerYearInterestRateBase / SECONDS_PER_YEAR;
}
// Set asset info
numAssets = uint8(config.assetConfigs.length);
assetList = IAssetListFactory(IAssetListFactoryHolder(extensionDelegate).assetListFactory()).createAssetList(config.assetConfigs);
}
/**
* @dev Prevents marked functions from being reentered
* Note: this restrict contracts from calling comet functions in their hooks.
* Doing so will cause the transaction to revert.
*/
modifier nonReentrant() {
nonReentrantBefore();
_;
nonReentrantAfter();
}
/**
* @dev Checks that the reentrancy flag is not set and then sets the flag
*/
function nonReentrantBefore() internal {
bytes32 slot = REENTRANCY_GUARD_FLAG_SLOT;
uint256 status;
assembly ("memory-safe") {
status := sload(slot)
}
if (status == REENTRANCY_GUARD_ENTERED) revert ReentrantCallBlocked();
assembly ("memory-safe") {
sstore(slot, REENTRANCY_GUARD_ENTERED)
}
}
/**
* @dev Unsets the reentrancy flag
*/
function nonReentrantAfter() internal {
bytes32 slot = REENTRANCY_GUARD_FLAG_SLOT;
uint256 status;
assembly ("memory-safe") {
sstore(slot, REENTRANCY_GUARD_NOT_ENTERED)
}
}
/**
* @notice Initialize storage for the contract
* @dev Can be used from constructor or proxy
*/
function initializeStorage() override external {
if (lastAccrualTime != 0) revert AlreadyInitialized();
// Initialize aggregates
lastAccrualTime = getNowInternal();
baseSupplyIndex = BASE_INDEX_SCALE;
baseBorrowIndex = BASE_INDEX_SCALE;
// Implicit initialization (not worth increasing contract size)
// trackingSupplyIndex = 0;
// trackingBorrowIndex = 0;
}
/**
* @notice Get the i-th asset info, according to the order they were passed in originally
* @param i The index of the asset info to get
* @return The asset info object
*/
function getAssetInfo(uint8 i) override public view returns (AssetInfo memory) {
return IAssetList(assetList).getAssetInfo(i);
}
/**
* @dev Determine index of asset that matches given address
*/
function getAssetInfoByAddress(address asset) override public view returns (AssetInfo memory) {
for (uint8 i = 0; i < numAssets; ) {
AssetInfo memory assetInfo = getAssetInfo(i);
if (assetInfo.asset == asset) {
return assetInfo;
}
unchecked { i++; }
}
revert BadAsset();
}
/**
* @return The current timestamp
**/
function getNowInternal() virtual internal view returns (uint40) {
if (block.timestamp >= 2**40) revert TimestampTooLarge();
return uint40(block.timestamp);
}
/**
* @dev Calculate accrued interest indices for base token supply and borrows
**/
function accruedInterestIndices(uint timeElapsed) internal view returns (uint64, uint64) {
uint64 baseSupplyIndex_ = baseSupplyIndex;
uint64 baseBorrowIndex_ = baseBorrowIndex;
if (timeElapsed > 0) {
uint utilization = getUtilization();
uint supplyRate = getSupplyRate(utilization);
uint borrowRate = getBorrowRate(utilization);
baseSupplyIndex_ += safe64(mulFactor(baseSupplyIndex_, supplyRate * timeElapsed));
baseBorrowIndex_ += safe64(mulFactor(baseBorrowIndex_, borrowRate * timeElapsed));
}
return (baseSupplyIndex_, baseBorrowIndex_);
}
/**
* @dev Accrue interest (and rewards) in base token supply and borrows
**/
function accrueInternal() internal {
uint40 now_ = getNowInternal();
uint timeElapsed = uint256(now_ - lastAccrualTime);
if (timeElapsed > 0) {
(baseSupplyIndex, baseBorrowIndex) = accruedInterestIndices(timeElapsed);
if (totalSupplyBase >= baseMinForRewards) {
trackingSupplyIndex += safe64(divBaseWei(baseTrackingSupplySpeed * timeElapsed, totalSupplyBase));
}
if (totalBorrowBase >= baseMinForRewards) {
trackingBorrowIndex += safe64(divBaseWei(baseTrackingBorrowSpeed * timeElapsed, totalBorrowBase));
}
lastAccrualTime = now_;
}
}
/**
* @notice Accrue interest and rewards for an account
**/
function accrueAccount(address account) override external {
accrueInternal();
UserBasic memory basic = userBasic[account];
updateBasePrincipal(account, basic, basic.principal);
}
/**
* @dev Note: Does not accrue interest first
* @param utilization The utilization to check the supply rate for
* @return The per second supply rate at `utilization`
*/
function getSupplyRate(uint utilization) override public view returns (uint64) {
if (utilization <= supplyKink) {
// interestRateBase + interestRateSlopeLow * utilization
return safe64(supplyPerSecondInterestRateBase + mulFactor(supplyPerSecondInterestRateSlopeLow, utilization));
} else {
// interestRateBase + interestRateSlopeLow * kink + interestRateSlopeHigh * (utilization - kink)
return safe64(supplyPerSecondInterestRateBase + mulFactor(supplyPerSecondInterestRateSlopeLow, supplyKink) + mulFactor(supplyPerSecondInterestRateSlopeHigh, (utilization - supplyKink)));
}
}
/**
* @dev Note: Does not accrue interest first
* @param utilization The utilization to check the borrow rate for
* @return The per second borrow rate at `utilization`
*/
function getBorrowRate(uint utilization) override public view returns (uint64) {
if (utilization <= borrowKink) {
// interestRateBase + interestRateSlopeLow * utilization
return safe64(borrowPerSecondInterestRateBase + mulFactor(borrowPerSecondInterestRateSlopeLow, utilization));
} else {
// interestRateBase + interestRateSlopeLow * kink + interestRateSlopeHigh * (utilization - kink)
return safe64(borrowPerSecondInterestRateBase + mulFactor(borrowPerSecondInterestRateSlopeLow, borrowKink) + mulFactor(borrowPerSecondInterestRateSlopeHigh, (utilization - borrowKink)));
}
}
/**
* @dev Note: Does not accrue interest first
* @return The utilization rate of the base asset
*/
function getUtilization() override public view returns (uint) {
uint totalSupply_ = presentValueSupply(baseSupplyIndex, totalSupplyBase);
uint totalBorrow_ = presentValueBorrow(baseBorrowIndex, totalBorrowBase);
if (totalSupply_ == 0) {
return 0;
} else {
return totalBorrow_ * FACTOR_SCALE / totalSupply_;
}
}
/**
* @notice Get the current price from a feed
* @param priceFeed The address of a price feed
* @return The price, scaled by `PRICE_SCALE`
*/
function getPrice(address priceFeed) override public view returns (uint256) {
(, int price, , , ) = IPriceFeed(priceFeed).latestRoundData();
if (price <= 0) revert BadPrice();
return uint256(price);
}
/**
* @notice Gets the total balance of protocol collateral reserves for an asset
* @dev Note: Reverts if collateral reserves are somehow negative, which should not be possible
* @param asset The collateral asset
*/
function getCollateralReserves(address asset) override public view returns (uint) {
return IERC20NonStandard(asset).balanceOf(address(this)) - totalsCollateral[asset].totalSupplyAsset;
}
/**
* @notice Gets the total amount of protocol reserves of the base asset
*/
function getReserves() override public view returns (int) {
(uint64 baseSupplyIndex_, uint64 baseBorrowIndex_) = accruedInterestIndices(getNowInternal() - lastAccrualTime);
uint balance = IERC20NonStandard(baseToken).balanceOf(address(this));
uint totalSupply_ = presentValueSupply(baseSupplyIndex_, totalSupplyBase);
uint totalBorrow_ = presentValueBorrow(baseBorrowIndex_, totalBorrowBase);
return signed256(balance) - signed256(totalSupply_) + signed256(totalBorrow_);
}
/**
* @notice Check whether an account has enough collateral to borrow
* @param account The address to check
* @return Whether the account is minimally collateralized enough to borrow
*/
function isBorrowCollateralized(address account) override public view returns (bool) {
int104 principal = userBasic[account].principal;
if (principal >= 0) {
return true;
}
uint16 assetsIn = userBasic[account].assetsIn;
uint8 _reserved = userBasic[account]._reserved;
int liquidity = signedMulPrice(
presentValue(principal),
getPrice(baseTokenPriceFeed),
uint64(baseScale)
);
for (uint8 i = 0; i < numAssets; ) {
if (isInAsset(assetsIn, i, _reserved)) {
if (liquidity >= 0) {
return true;
}
AssetInfo memory asset = getAssetInfo(i);
uint newAmount = mulPrice(
userCollateral[account][asset.asset].balance,
getPrice(asset.priceFeed),
asset.scale
);
liquidity += signed256(mulFactor(
newAmount,
asset.borrowCollateralFactor
));
}
unchecked { i++; }
}
return liquidity >= 0;
}
/**
* @notice Check whether an account has enough collateral to not be liquidated
* @param account The address to check
* @return Whether the account is minimally collateralized enough to not be liquidated
*/
function isLiquidatable(address account) override public view returns (bool) {
int104 principal = userBasic[account].principal;
if (principal >= 0) {
return false;
}
uint16 assetsIn = userBasic[account].assetsIn;
uint8 _reserved = userBasic[account]._reserved;
int liquidity = signedMulPrice(
presentValue(principal),
getPrice(baseTokenPriceFeed),
uint64(baseScale)
);
for (uint8 i = 0; i < numAssets; ) {
if (isInAsset(assetsIn, i, _reserved)) {
if (liquidity >= 0) {
return false;
}
AssetInfo memory asset = getAssetInfo(i);
uint newAmount = mulPrice(
userCollateral[account][asset.asset].balance,
getPrice(asset.priceFeed),
asset.scale
);
liquidity += signed256(mulFactor(
newAmount,
asset.liquidateCollateralFactor
));
}
unchecked { i++; }
}
return liquidity < 0;
}
/**
* @dev The change in principal broken into repay and supply amounts
*/
function repayAndSupplyAmount(int104 oldPrincipal, int104 newPrincipal) internal pure returns (uint104, uint104) {
// If the new principal is less than the old principal, then no amount has been repaid or supplied
if (newPrincipal < oldPrincipal) return (0, 0);
if (newPrincipal <= 0) {
return (uint104(newPrincipal - oldPrincipal), 0);
} else if (oldPrincipal >= 0) {
return (0, uint104(newPrincipal - oldPrincipal));
} else {
return (uint104(-oldPrincipal), uint104(newPrincipal));
}
}
/**
* @dev The change in principal broken into withdraw and borrow amounts
*/
function withdrawAndBorrowAmount(int104 oldPrincipal, int104 newPrincipal) internal pure returns (uint104, uint104) {
// If the new principal is greater than the old principal, then no amount has been withdrawn or borrowed
if (newPrincipal > oldPrincipal) return (0, 0);
if (newPrincipal >= 0) {
return (uint104(oldPrincipal - newPrincipal), 0);
} else if (oldPrincipal <= 0) {
return (0, uint104(oldPrincipal - newPrincipal));
} else {
return (uint104(oldPrincipal), uint104(-newPrincipal));
}
}
/**
* @notice Pauses different actions within Comet
* @param supplyPaused Boolean for pausing supply actions
* @param transferPaused Boolean for pausing transfer actions
* @param withdrawPaused Boolean for pausing withdraw actions
* @param absorbPaused Boolean for pausing absorb actions
* @param buyPaused Boolean for pausing buy actions
*/
function pause(
bool supplyPaused,
bool transferPaused,
bool withdrawPaused,
bool absorbPaused,
bool buyPaused
) override external {
if (msg.sender != governor && msg.sender != pauseGuardian) revert Unauthorized();
pauseFlags =
uint8(0) |
(toUInt8(supplyPaused) << PAUSE_SUPPLY_OFFSET) |
(toUInt8(transferPaused) << PAUSE_TRANSFER_OFFSET) |
(toUInt8(withdrawPaused) << PAUSE_WITHDRAW_OFFSET) |
(toUInt8(absorbPaused) << PAUSE_ABSORB_OFFSET) |
(toUInt8(buyPaused) << PAUSE_BUY_OFFSET);
emit PauseAction(supplyPaused, transferPaused, withdrawPaused, absorbPaused, buyPaused);
}
/**
* @return Whether or not supply actions are paused
*/
function isSupplyPaused() override public view returns (bool) {
return toBool(pauseFlags & (uint8(1) << PAUSE_SUPPLY_OFFSET));
}
/**
* @return Whether or not transfer actions are paused
*/
function isTransferPaused() override public view returns (bool) {
return toBool(pauseFlags & (uint8(1) << PAUSE_TRANSFER_OFFSET));
}
/**
* @return Whether or not withdraw actions are paused
*/
function isWithdrawPaused() override public view returns (bool) {
return toBool(pauseFlags & (uint8(1) << PAUSE_WITHDRAW_OFFSET));
}
/**
* @return Whether or not absorb actions are paused
*/
function isAbsorbPaused() override public view returns (bool) {
return toBool(pauseFlags & (uint8(1) << PAUSE_ABSORB_OFFSET));
}
/**
* @return Whether or not buy actions are paused
*/
function isBuyPaused() override public view returns (bool) {
return toBool(pauseFlags & (uint8(1) << PAUSE_BUY_OFFSET));
}
/**
* @dev Multiply a number by a factor
*/
function mulFactor(uint n, uint factor) internal pure returns (uint) {
return n * factor / FACTOR_SCALE;
}
/**
* @dev Divide a number by an amount of base
*/
function divBaseWei(uint n, uint baseWei) internal view returns (uint) {
return n * baseScale / baseWei;
}
/**
* @dev Multiply a `fromScale` quantity by a price, returning a common price quantity
*/
function mulPrice(uint n, uint price, uint64 fromScale) internal pure returns (uint) {
return n * price / fromScale;
}
/**
* @dev Multiply a signed `fromScale` quantity by a price, returning a common price quantity
*/
function signedMulPrice(int n, uint price, uint64 fromScale) internal pure returns (int) {
return n * signed256(price) / int256(uint256(fromScale));
}
/**
* @dev Divide a common price quantity by a price, returning a `toScale` quantity
*/
function divPrice(uint n, uint price, uint64 toScale) internal pure returns (uint) {
return n * toScale / price;
}
/**
* @dev Whether user has a non-zero balance of an asset, given assetsIn flags
* @dev _reserved is used to check bits 16-23 of assetsIn
*/
function isInAsset(uint16 assetsIn, uint8 assetOffset, uint8 _reserved) internal pure returns (bool) {
if (assetOffset < 16) {
// check bit in assetsIn (for bits 0-15)
return (assetsIn & (uint16(1) << assetOffset)) != 0;
} else if (assetOffset < 24) {
// check bit in reserved (for bits 16-23)
return (_reserved & (uint8(1) << (assetOffset - 16))) != 0;
}
return false; // if assetOffset >= 24 (should not happen)
}
/**
* @dev Update assetsIn bit vector if user has entered or exited an asset
*/
function updateAssetsIn(
address account,
AssetInfo memory assetInfo,
uint128 initialUserBalance,
uint128 finalUserBalance
) internal {
if (initialUserBalance == 0 && finalUserBalance != 0) {
// set bit for asset
if (assetInfo.offset < 16) {
// set bit in assetsIn for bits 0-15
userBasic[account].assetsIn |= (uint16(1) << assetInfo.offset);
} else if (assetInfo.offset < 24) {
// set bit in _reserved for bits 16-23
userBasic[account]._reserved |= (uint8(1) << (assetInfo.offset - 16));
}
} else if (initialUserBalance != 0 && finalUserBalance == 0) {
// clear bit for asset
if (assetInfo.offset < 16) {
// clear bit in assetsIn for bits 0-15
userBasic[account].assetsIn &= ~(uint16(1) << assetInfo.offset);
} else if (assetInfo.offset < 24) {
// clear bit in _reserved for bits 16-23
userBasic[account]._reserved &= ~(uint8(1) << (assetInfo.offset - 16));
}
}
}
/**
* @dev Write updated principal to store and tracking participation
*/
function updateBasePrincipal(address account, UserBasic memory basic, int104 principalNew) internal {
int104 principal = basic.principal;
basic.principal = principalNew;
if (principal >= 0) {
uint indexDelta = uint256(trackingSupplyIndex - basic.baseTrackingIndex);
basic.baseTrackingAccrued += safe64(uint104(principal) * indexDelta / trackingIndexScale / accrualDescaleFactor);
} else {
uint indexDelta = uint256(trackingBorrowIndex - basic.baseTrackingIndex);
basic.baseTrackingAccrued += safe64(uint104(-principal) * indexDelta / trackingIndexScale / accrualDescaleFactor);
}
if (principalNew >= 0) {
basic.baseTrackingIndex = trackingSupplyIndex;
} else {
basic.baseTrackingIndex = trackingBorrowIndex;
}
userBasic[account] = basic;
}
/**
* @dev Safe ERC20 transfer in and returns the final amount transferred (taking into account any fees)
* @dev Note: Safely handles non-standard ERC-20 tokens that do not return a value. See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
*/
function doTransferIn(address asset, address from, uint amount) internal returns (uint) {
uint256 preTransferBalance = IERC20NonStandard(asset).balanceOf(address(this));
IERC20NonStandard(asset).transferFrom(from, address(this), amount);
bool success;
assembly ("memory-safe") {
switch returndatasize()
case 0 { // This is a non-standard ERC-20
success := not(0) // set success to true
}
case 32 { // This is a compliant ERC-20
returndatacopy(0, 0, 32)
success := mload(0) // Set `success = returndata` of override external call
}
default { // This is an excessively non-compliant ERC-20, revert.
revert(0, 0)
}
}
if (!success) revert TransferInFailed();
return IERC20NonStandard(asset).balanceOf(address(this)) - preTransferBalance;
}
/**
* @dev Safe ERC20 transfer out
* @dev Note: Safely handles non-standard ERC-20 tokens that do not return a value. See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
*/
function doTransferOut(address asset, address to, uint amount) internal {
IERC20NonStandard(asset).transfer(to, amount);
bool success;
assembly ("memory-safe") {
switch returndatasize()
case 0 { // This is a non-standard ERC-20
success := not(0) // set success to true
}
case 32 { // This is a compliant ERC-20
returndatacopy(0, 0, 32)
success := mload(0) // Set `success = returndata` of override external call
}
default { // This is an excessively non-compliant ERC-20, revert.
revert(0, 0)
}
}
if (!success) revert TransferOutFailed();
}
/**
* @notice Supply an amount of asset to the protocol
* @param asset The asset to supply
* @param amount The quantity to supply
*/
function supply(address asset, uint amount) override external {
return supplyInternal(msg.sender, msg.sender, msg.sender, asset, amount);
}
/**
* @notice Supply an amount of asset to dst
* @param dst The address which will hold the balance
* @param asset The asset to supply
* @param amount The quantity to supply
*/
function supplyTo(address dst, address asset, uint amount) override external {
return supplyInternal(msg.sender, msg.sender, dst, asset, amount);
}
/**
* @notice Supply an amount of asset from `from` to dst, if allowed
* @param from The supplier address
* @param dst The address which will hold the balance
* @param asset The asset to supply
* @param amount The quantity to supply
*/
function supplyFrom(address from, address dst, address asset, uint amount) override external {
return supplyInternal(msg.sender, from, dst, asset, amount);
}
/**
* @dev Supply either collateral or base asset, depending on the asset, if operator is allowed
* @dev Note: Specifying an `amount` of uint256.max will repay all of `dst`'s accrued base borrow balance
*/
function supplyInternal(address operator, address from, address dst, address asset, uint amount) internal nonReentrant {
if (isSupplyPaused()) revert Paused();
if (!hasPermission(from, operator)) revert Unauthorized();
if (asset == baseToken) {
if (amount == type(uint256).max) {
amount = borrowBalanceOf(dst);
}
return supplyBase(from, dst, amount);
} else {
return supplyCollateral(from, dst, asset, safe128(amount));
}
}
/**
* @dev Supply an amount of base asset from `from` to dst
*/
function supplyBase(address from, address dst, uint256 amount) internal {
amount = doTransferIn(baseToken, from, amount);
accrueInternal();
UserBasic memory dstUser = userBasic[dst];
int104 dstPrincipal = dstUser.principal;
int256 dstBalance = presentValue(dstPrincipal) + signed256(amount);
int104 dstPrincipalNew = principalValue(dstBalance);
(uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(dstPrincipal, dstPrincipalNew);
totalSupplyBase += supplyAmount;
totalBorrowBase -= repayAmount;
updateBasePrincipal(dst, dstUser, dstPrincipalNew);
emit Supply(from, dst, amount);
if (supplyAmount > 0) {
emit Transfer(address(0), dst, presentValueSupply(baseSupplyIndex, supplyAmount));
}
}
/**
* @dev Supply an amount of collateral asset from `from` to dst
*/
function supplyCollateral(address from, address dst, address asset, uint128 amount) internal {
amount = safe128(doTransferIn(asset, from, amount));
AssetInfo memory assetInfo = getAssetInfoByAddress(asset);
TotalsCollateral memory totals = totalsCollateral[asset];
totals.totalSupplyAsset += amount;
if (totals.totalSupplyAsset > assetInfo.supplyCap) revert SupplyCapExceeded();
uint128 dstCollateral = userCollateral[dst][asset].balance;
uint128 dstCollateralNew = dstCollateral + amount;
totalsCollateral[asset] = totals;
userCollateral[dst][asset].balance = dstCollateralNew;
updateAssetsIn(dst, assetInfo, dstCollateral, dstCollateralNew);
emit SupplyCollateral(from, dst, asset, amount);
}
/**
* @notice ERC20 transfer an amount of base token to dst
* @param dst The recipient address
* @param amount The quantity to transfer
* @return true
*/
function transfer(address dst, uint amount) override external returns (bool) {
transferInternal(msg.sender, msg.sender, dst, baseToken, amount);
return true;
}
/**
* @notice ERC20 transfer an amount of base token from src to dst, if allowed
* @param src The sender address
* @param dst The recipient address
* @param amount The quantity to transfer
* @return true
*/
function transferFrom(address src, address dst, uint amount) override external returns (bool) {
transferInternal(msg.sender, src, dst, baseToken, amount);
return true;
}
/**
* @notice Transfer an amount of asset to dst
* @param dst The recipient address
* @param asset The asset to transfer
* @param amount The quantity to transfer
*/
function transferAsset(address dst, address asset, uint amount) override external {
return transferInternal(msg.sender, msg.sender, dst, asset, amount);
}
/**
* @notice Transfer an amount of asset from src to dst, if allowed
* @param src The sender address
* @param dst The recipient address
* @param asset The asset to transfer
* @param amount The quantity to transfer
*/
function transferAssetFrom(address src, address dst, address asset, uint amount) override external {
return transferInternal(msg.sender, src, dst, asset, amount);
}
/**
* @dev Transfer either collateral or base asset, depending on the asset, if operator is allowed
* @dev Note: Specifying an `amount` of uint256.max will transfer all of `src`'s accrued base balance
*/
function transferInternal(address operator, address src, address dst, address asset, uint amount) internal nonReentrant {
if (isTransferPaused()) revert Paused();
if (!hasPermission(src, operator)) revert Unauthorized();
if (src == dst) revert NoSelfTransfer();
if (asset == baseToken) {
if (amount == type(uint256).max) {
amount = balanceOf(src);
}
return transferBase(src, dst, amount);
} else {
return transferCollateral(src, dst, asset, safe128(amount));
}
}
/**
* @dev Transfer an amount of base asset from src to dst, borrowing if possible/necessary
*/
function transferBase(address src, address dst, uint256 amount) internal {
accrueInternal();
UserBasic memory srcUser = userBasic[src];
UserBasic memory dstUser = userBasic[dst];
int104 srcPrincipal = srcUser.principal;
int104 dstPrincipal = dstUser.principal;
int256 srcBalance = presentValue(srcPrincipal) - signed256(amount);
int256 dstBalance = presentValue(dstPrincipal) + signed256(amount);
int104 srcPrincipalNew = principalValue(srcBalance);
int104 dstPrincipalNew = principalValue(dstBalance);
(uint104 withdrawAmount, uint104 borrowAmount) = withdrawAndBorrowAmount(srcPrincipal, srcPrincipalNew);
(uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(dstPrincipal, dstPrincipalNew);
// Note: Instead of `total += addAmount - subAmount` to avoid underflow errors.
totalSupplyBase = totalSupplyBase + supplyAmount - withdrawAmount;
totalBorrowBase = totalBorrowBase + borrowAmount - repayAmount;
updateBasePrincipal(src, srcUser, srcPrincipalNew);
updateBasePrincipal(dst, dstUser, dstPrincipalNew);
if (srcBalance < 0) {
if (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall();
if (!isBorrowCollateralized(src)) revert NotCollateralized();
}
if (withdrawAmount > 0) {
emit Transfer(src, address(0), presentValueSupply(baseSupplyIndex, withdrawAmount));
}
if (supplyAmount > 0) {
emit Transfer(address(0), dst, presentValueSupply(baseSupplyIndex, supplyAmount));
}
}
/**
* @dev Transfer an amount of collateral asset from src to dst
*/
function transferCollateral(address src, address dst, address asset, uint128 amount) internal {
uint128 srcCollateral = userCollateral[src][asset].balance;
uint128 dstCollateral = userCollateral[dst][asset].balance;
uint128 srcCollateralNew = srcCollateral - amount;
uint128 dstCollateralNew = dstCollateral + amount;
userCollateral[src][asset].balance = srcCollateralNew;
userCollateral[dst][asset].balance = dstCollateralNew;
AssetInfo memory assetInfo = getAssetInfoByAddress(asset);
updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew);
updateAssetsIn(dst, assetInfo, dstCollateral, dstCollateralNew);
// Note: no accrue interest, BorrowCF < LiquidationCF covers small changes
if (!isBorrowCollateralized(src)) revert NotCollateralized();
emit TransferCollateral(src, dst, asset, amount);
}
/**
* @notice Withdraw an amount of asset from the protocol
* @param asset The asset to withdraw
* @param amount The quantity to withdraw
*/
function withdraw(address asset, uint amount) override external {
return withdrawInternal(msg.sender, msg.sender, msg.sender, asset, amount);
}
/**
* @notice Withdraw an amount of asset to `to`
* @param to The recipient address
* @param asset The asset to withdraw
* @param amount The quantity to withdraw
*/
function withdrawTo(address to, address asset, uint amount) override external {
return withdrawInternal(msg.sender, msg.sender, to, asset, amount);
}
/**
* @notice Withdraw an amount of asset from src to `to`, if allowed
* @param src The sender address
* @param to The recipient address
* @param asset The asset to withdraw
* @param amount The quantity to withdraw
*/
function withdrawFrom(address src, address to, address asset, uint amount) override external {
return withdrawInternal(msg.sender, src, to, asset, amount);
}
/**
* @dev Withdraw either collateral or base asset, depending on the asset, if operator is allowed
* @dev Note: Specifying an `amount` of uint256.max will withdraw all of `src`'s accrued base balance
*/
function withdrawInternal(address operator, address src, address to, address asset, uint amount) internal nonReentrant {
if (isWithdrawPaused()) revert Paused();
if (!hasPermission(src, operator)) revert Unauthorized();
if (asset == baseToken) {
if (amount == type(uint256).max) {
amount = balanceOf(src);
}
return withdrawBase(src, to, amount);
} else {
return withdrawCollateral(src, to, asset, safe128(amount));
}
}
/**
* @dev Withdraw an amount of base asset from src to `to`, borrowing if possible/necessary
*/
function withdrawBase(address src, address to, uint256 amount) internal {
accrueInternal();
UserBasic memory srcUser = userBasic[src];
int104 srcPrincipal = srcUser.principal;
int256 srcBalance = presentValue(srcPrincipal) - signed256(amount);
int104 srcPrincipalNew = principalValue(srcBalance);
(uint104 withdrawAmount, uint104 borrowAmount) = withdrawAndBorrowAmount(srcPrincipal, srcPrincipalNew);
totalSupplyBase -= withdrawAmount;
totalBorrowBase += borrowAmount;
updateBasePrincipal(src, srcUser, srcPrincipalNew);
if (srcBalance < 0) {
if (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall();
if (!isBorrowCollateralized(src)) revert NotCollateralized();
}
doTransferOut(baseToken, to, amount);
emit Withdraw(src, to, amount);
if (withdrawAmount > 0) {
emit Transfer(src, address(0), presentValueSupply(baseSupplyIndex, withdrawAmount));
}
}
/**
* @dev Withdraw an amount of collateral asset from src to `to`
*/
function withdrawCollateral(address src, address to, address asset, uint128 amount) internal {
uint128 srcCollateral = userCollateral[src][asset].balance;
uint128 srcCollateralNew = srcCollateral - amount;
totalsCollateral[asset].totalSupplyAsset -= amount;
userCollateral[src][asset].balance = srcCollateralNew;
AssetInfo memory assetInfo = getAssetInfoByAddress(asset);
updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew);
// Note: no accrue interest, BorrowCF < LiquidationCF covers small changes
if (!isBorrowCollateralized(src)) revert NotCollateralized();
doTransferOut(asset, to, amount);
emit WithdrawCollateral(src, to, asset, amount);
}
/**
* @notice Absorb a list of underwater accounts onto the protocol balance sheet
* @param absorber The recipient of the incentive paid to the caller of absorb
* @param accounts The list of underwater accounts to absorb
*/
function absorb(address absorber, address[] calldata accounts) override external {
if (isAbsorbPaused()) revert Paused();
uint startGas = gasleft();
accrueInternal();
for (uint i = 0; i < accounts.length; ) {
absorbInternal(absorber, accounts[i]);
unchecked { i++; }
}
uint gasUsed = startGas - gasleft();
// Note: liquidator points are an imperfect tool for governance,
// to be used while evaluating strategies for incentivizing absorption.
// Using gas price instead of base fee would more accurately reflect spend,
// but is also subject to abuse if refunds were to be given automatically.
LiquidatorPoints memory points = liquidatorPoints[absorber];
points.numAbsorbs++;
points.numAbsorbed += safe64(accounts.length);
points.approxSpend += safe128(gasUsed * block.basefee);
liquidatorPoints[absorber] = points;
}
/**
* @dev Transfer user's collateral and debt to the protocol itself.
*/
function absorbInternal(address absorber, address account) internal {
if (!isLiquidatable(account)) revert NotLiquidatable();
UserBasic memory accountUser = userBasic[account];
int104 oldPrincipal = accountUser.principal;
int256 oldBalance = presentValue(oldPrincipal);
uint16 assetsIn = accountUser.assetsIn;
uint8 _reserved = accountUser._reserved;
uint256 basePrice = getPrice(baseTokenPriceFeed);
uint256 deltaValue = 0;
for (uint8 i = 0; i < numAssets; ) {
if (isInAsset(assetsIn, i, _reserved)) {
AssetInfo memory assetInfo = getAssetInfo(i);
address asset = assetInfo.asset;
uint128 seizeAmount = userCollateral[account][asset].balance;
userCollateral[account][asset].balance = 0;
totalsCollateral[asset].totalSupplyAsset -= seizeAmount;
uint256 value = mulPrice(seizeAmount, getPrice(assetInfo.priceFeed), assetInfo.scale);
deltaValue += mulFactor(value, assetInfo.liquidationFactor);
emit AbsorbCollateral(absorber, account, asset, seizeAmount, value);
}
unchecked { i++; }
}
uint256 deltaBalance = divPrice(deltaValue, basePrice, uint64(baseScale));
int256 newBalance = oldBalance + signed256(deltaBalance);
// New balance will not be negative, all excess debt absorbed by reserves
if (newBalance < 0) {
newBalance = 0;
}
int104 newPrincipal = principalValue(newBalance);
updateBasePrincipal(account, accountUser, newPrincipal);
// reset assetsIn
userBasic[account].assetsIn = 0;
userBasic[account]._reserved = 0;
(uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(oldPrincipal, newPrincipal);
// Reserves are decreased by increasing total supply and decreasing borrows
// the amount of debt repaid by reserves is `newBalance - oldBalance`
totalSupplyBase += supplyAmount;
totalBorrowBase -= repayAmount;
uint256 basePaidOut = unsigned256(newBalance - oldBalance);
uint256 valueOfBasePaidOut = mulPrice(basePaidOut, basePrice, uint64(baseScale));
emit AbsorbDebt(absorber, account, basePaidOut, valueOfBasePaidOut);
if (newPrincipal > 0) {
emit Transfer(address(0), account, presentValueSupply(baseSupplyIndex, unsigned104(newPrincipal)));
}
}
/**
* @notice Buy collateral from the protocol using base tokens, increasing protocol reserves
A minimum collateral amount should be specified to indicate the maximum slippage acceptable for the buyer.
* @param asset The asset to buy
* @param minAmount The minimum amount of collateral tokens that should be received by the buyer
* @param baseAmount The amount of base tokens used to buy the collateral
* @param recipient The recipient address
*/
function buyCollateral(address asset, uint minAmount, uint baseAmount, address recipient) override external nonReentrant {
if (isBuyPaused()) revert Paused();
int reserves = getReserves();
if (reserves >= 0 && uint(reserves) >= targetReserves) revert NotForSale();
// Note: Re-entrancy can skip the reserves check above on a second buyCollateral call.
baseAmount = doTransferIn(baseToken, msg.sender, baseAmount);
uint collateralAmount = quoteCollateral(asset, baseAmount);
if (collateralAmount < minAmount) revert TooMuchSlippage();
if (collateralAmount > getCollateralReserves(asset)) revert InsufficientReserves();
// Note: Pre-transfer hook can re-enter buyCollateral with a stale collateral ERC20 balance.
// Assets should not be listed which allow re-entry from pre-transfer now, as too much collateral could be bought.
// This is also a problem if quoteCollateral derives its discount from the collateral ERC20 balance.
doTransferOut(asset, recipient, safe128(collateralAmount));
emit BuyCollateral(msg.sender, asset, baseAmount, collateralAmount);
}
/**
* @notice Gets the quote for a collateral asset in exchange for an amount of base asset
* @param asset The collateral asset to get the quote for
* @param baseAmount The amount of the base asset to get the quote for
* @return The quote in terms of the collateral asset
*/
function quoteCollateral(address asset, uint baseAmount) override public view returns (uint) {
AssetInfo memory assetInfo = getAssetInfoByAddress(asset);
uint256 assetPrice = getPrice(assetInfo.priceFeed);
// Store front discount is derived from the collateral asset's liquidationFactor and storeFrontPriceFactor
// discount = storeFrontPriceFactor * (1e18 - liquidationFactor)
uint256 discountFactor = mulFactor(storeFrontPriceFactor, FACTOR_SCALE - assetInfo.liquidationFactor);
uint256 assetPriceDiscounted = mulFactor(assetPrice, FACTOR_SCALE - discountFactor);
uint256 basePrice = getPrice(baseTokenPriceFeed);
// # of collateral assets
// = (TotalValueOfBaseAmount / DiscountedPriceOfCollateralAsset) * assetScale
// = ((basePrice * baseAmount / baseScale) / assetPriceDiscounted) * assetScale
return basePrice * baseAmount * assetInfo.scale / assetPriceDiscounted / baseScale;
}
/**
* @notice Withdraws base token reserves if called by the governor
* @param to An address of the receiver of withdrawn reserves
* @param amount The amount of reserves to be withdrawn from the protocol
*/
function withdrawReserves(address to, uint amount) override external {
if (msg.sender != governor) revert Unauthorized();
int reserves = getReserves();
if (reserves < 0 || amount > unsigned256(reserves)) revert InsufficientReserves();
doTransferOut(baseToken, to, amount);
emit WithdrawReserves(to, amount);
}
/**
* @notice Sets Comet's ERC20 allowance of an asset for a manager
* @dev Only callable by governor
* @dev Note: Setting the `asset` as Comet's address will allow the manager
* to withdraw from Comet's Comet balance
* @dev Note: For USDT, if there is non-zero prior allowance, it must be reset to 0 first before setting a new value in proposal
* @param asset The asset that the manager will gain approval of
* @param manager The account which will be allowed or disallowed
* @param amount The amount of an asset to approve
*/
function approveThis(address manager, address asset, uint amount) override external {
if (msg.sender != governor) revert Unauthorized();
IERC20NonStandard(asset).approve(manager, amount);
}
/**
* @notice Get the total number of tokens in circulation
* @dev Note: uses updated interest indices to calculate
* @return The supply of tokens
**/
function totalSupply() override external view returns (uint256) {
(uint64 baseSupplyIndex_, ) = accruedInterestIndices(getNowInternal() - lastAccrualTime);
return presentValueSupply(baseSupplyIndex_, totalSupplyBase);
}
/**
* @notice Get the total amount of debt
* @dev Note: uses updated interest indices to calculate
* @return The amount of debt
**/
function totalBorrow() override external view returns (uint256) {
(, uint64 baseBorrowIndex_) = accruedInterestIndices(getNowInternal() - lastAccrualTime);
return presentValueBorrow(baseBorrowIndex_, totalBorrowBase);
}
/**
* @notice Query the current positive base balance of an account or zero
* @dev Note: uses updated interest indices to calculate
* @param account The account whose balance to query
* @return The present day base balance magnitude of the account, if positive
*/
function balanceOf(address account) override public view returns (uint256) {
(uint64 baseSupplyIndex_, ) = accruedInterestIndices(getNowInternal() - lastAccrualTime);
int104 principal = userBasic[account].principal;
return principal > 0 ? presentValueSupply(baseSupplyIndex_, unsigned104(principal)) : 0;
}
/**
* @notice Query the current negative base balance of an account or zero
* @dev Note: uses updated interest indices to calculate
* @param account The account whose balance to query
* @return The present day base balance magnitude of the account, if negative
*/
function borrowBalanceOf(address account) override public view returns (uint256) {
(, uint64 baseBorrowIndex_) = accruedInterestIndices(getNowInternal() - lastAccrualTime);
int104 principal = userBasic[account].principal;
return principal < 0 ? presentValueBorrow(baseBorrowIndex_, unsigned104(-principal)) : 0;
}
/**
* @notice Fallback to calling the extension delegate for everything else
*/
fallback() external payable {
address delegate = extensionDelegate;
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), delegate, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
/**
* @title Compound's Comet Configuration Interface
* @author Compound
*/
contract CometConfiguration {
struct ExtConfiguration {
bytes32 name32;
bytes32 symbol32;
}
struct Configuration {
address governor;
address pauseGuardian;
address baseToken;
address baseTokenPriceFeed;
address extensionDelegate;
uint64 supplyKink;
uint64 supplyPerYearInterestRateSlopeLow;
uint64 supplyPerYearInterestRateSlopeHigh;
uint64 supplyPerYearInterestRateBase;
uint64 borrowKink;
uint64 borrowPerYearInterestRateSlopeLow;
uint64 borrowPerYearInterestRateSlopeHigh;
uint64 borrowPerYearInterestRateBase;
uint64 storeFrontPriceFactor;
uint64 trackingIndexScale;
uint64 baseTrackingSupplySpeed;
uint64 baseTrackingBorrowSpeed;
uint104 baseMinForRewards;
uint104 baseBorrowMin;
uint104 targetReserves;
AssetConfig[] assetConfigs;
}
struct AssetConfig {
address asset;
address priceFeed;
uint8 decimals;
uint64 borrowCollateralFactor;
uint64 liquidateCollateralFactor;
uint64 liquidationFactor;
uint128 supplyCap;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
import "./CometConfiguration.sol";
import "./CometStorage.sol";
import "./CometMath.sol";
abstract contract CometCore is CometConfiguration, CometStorage, CometMath {
struct AssetInfo {
uint8 offset;
address asset;
address priceFeed;
uint64 scale;
uint64 borrowCollateralFactor;
uint64 liquidateCollateralFactor;
uint64 liquidationFactor;
uint128 supplyCap;
}
/** Internal constants **/
/// @dev The max number of assets this contract is hardcoded to support
/// Do not change this variable without updating all the fields throughout the contract,
// including the size of UserBasic.assetsIn and corresponding integer conversions.
uint8 internal constant MAX_ASSETS = 15;
/// @dev The max number of decimals base token can have
/// Note this cannot just be increased arbitrarily.
uint8 internal constant MAX_BASE_DECIMALS = 18;
/// @dev The max value for a collateral factor (1)
uint64 internal constant MAX_COLLATERAL_FACTOR = FACTOR_SCALE;
/// @dev Offsets for specific actions in the pause flag bit array
uint8 internal constant PAUSE_SUPPLY_OFFSET = 0;
uint8 internal constant PAUSE_TRANSFER_OFFSET = 1;
uint8 internal constant PAUSE_WITHDRAW_OFFSET = 2;
uint8 internal constant PAUSE_ABSORB_OFFSET = 3;
uint8 internal constant PAUSE_BUY_OFFSET = 4;
/// @dev The decimals required for a price feed
uint8 internal constant PRICE_FEED_DECIMALS = 8;
/// @dev 365 days * 24 hours * 60 minutes * 60 seconds
uint64 internal constant SECONDS_PER_YEAR = 31_536_000;
/// @dev The scale for base tracking accrual
uint64 internal constant BASE_ACCRUAL_SCALE = 1e6;
/// @dev The scale for base index (depends on time/rate scales, not base token)
uint64 internal constant BASE_INDEX_SCALE = 1e15;
/// @dev The scale for prices (in USD)
uint64 internal constant PRICE_SCALE = uint64(10 ** PRICE_FEED_DECIMALS);
/// @dev The scale for factors
uint64 internal constant FACTOR_SCALE = 1e18;
/// @dev The storage slot for reentrancy guard flags
bytes32 internal constant REENTRANCY_GUARD_FLAG_SLOT = bytes32(keccak256("comet.reentrancy.guard"));
/// @dev The reentrancy guard statuses
uint256 internal constant REENTRANCY_GUARD_NOT_ENTERED = 0;
uint256 internal constant REENTRANCY_GUARD_ENTERED = 1;
/**
* @notice Determine if the manager has permission to act on behalf of the owner
* @param owner The owner account
* @param manager The manager account
* @return Whether or not the manager has permission
*/
function hasPermission(address owner, address manager) public view returns (bool) {
return owner == manager || isAllowed[owner][manager];
}
/**
* @dev The positive present supply balance if positive or the negative borrow balance if negative
*/
function presentValue(int104 principalValue_) internal view returns (int256) {
if (principalValue_ >= 0) {
return signed256(presentValueSupply(baseSupplyIndex, uint104(principalValue_)));
} else {
return -signed256(presentValueBorrow(baseBorrowIndex, uint104(-principalValue_)));
}
}
/**
* @dev The principal amount projected forward by the supply index
*/
function presentValueSupply(uint64 baseSupplyIndex_, uint104 principalValue_) internal pure returns (uint256) {
return uint256(principalValue_) * baseSupplyIndex_ / BASE_INDEX_SCALE;
}
/**
* @dev The principal amount projected forward by the borrow index
*/
function presentValueBorrow(uint64 baseBorrowIndex_, uint104 principalValue_) internal pure returns (uint256) {
return uint256(principalValue_) * baseBorrowIndex_ / BASE_INDEX_SCALE;
}
/**
* @dev The positive principal if positive or the negative principal if negative
*/
function principalValue(int256 presentValue_) internal view returns (int104) {
if (presentValue_ >= 0) {
return signed104(principalValueSupply(baseSupplyIndex, uint256(presentValue_)));
} else {
return -signed104(principalValueBorrow(baseBorrowIndex, uint256(-presentValue_)));
}
}
/**
* @dev The present value projected backward by the supply index (rounded down)
* Note: This will overflow (revert) at 2^104/1e18=~20 trillion principal for assets with 18 decimals.
*/
function principalValueSupply(uint64 baseSupplyIndex_, uint256 presentValue_) internal pure returns (uint104) {
return safe104((presentValue_ * BASE_INDEX_SCALE) / baseSupplyIndex_);
}
/**
* @dev The present value projected backward by the borrow index (rounded up)
* Note: This will overflow (revert) at 2^104/1e18=~20 trillion principal for assets with 18 decimals.
*/
function principalValueBorrow(uint64 baseBorrowIndex_, uint256 presentValue_) internal pure returns (uint104) {
return safe104((presentValue_ * BASE_INDEX_SCALE + baseBorrowIndex_ - 1) / baseBorrowIndex_);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
import "./CometCore.sol";
/**
* @title Compound's Comet Main Interface (without Ext)
* @notice An efficient monolithic money market protocol
* @author Compound
*/
abstract contract CometMainInterface is CometCore {
error Absurd();
error AlreadyInitialized();
error BadAsset();
error BadDecimals();
error BadDiscount();
error BadMinimum();
error BadPrice();
error BorrowTooSmall();
error BorrowCFTooLarge();
error InsufficientReserves();
error LiquidateCFTooLarge();
error NoSelfTransfer();
error NotCollateralized();
error NotForSale();
error NotLiquidatable();
error Paused();
error ReentrantCallBlocked();
error SupplyCapExceeded();
error TimestampTooLarge();
error TooManyAssets();
error TooMuchSlippage();
error TransferInFailed();
error TransferOutFailed();
error Unauthorized();
event Supply(address indexed from, address indexed dst, uint amount);
event Transfer(address indexed from, address indexed to, uint amount);
event Withdraw(address indexed src, address indexed to, uint amount);
event SupplyCollateral(address indexed from, address indexed dst, address indexed asset, uint amount);
event TransferCollateral(address indexed from, address indexed to, address indexed asset, uint amount);
event WithdrawCollateral(address indexed src, address indexed to, address indexed asset, uint amount);
/// @notice Event emitted when a borrow position is absorbed by the protocol
event AbsorbDebt(address indexed absorber, address indexed borrower, uint basePaidOut, uint usdValue);
/// @notice Event emitted when a user's collateral is absorbed by the protocol
event AbsorbCollateral(address indexed absorber, address indexed borrower, address indexed asset, uint collateralAbsorbed, uint usdValue);
/// @notice Event emitted when a collateral asset is purchased from the protocol
event BuyCollateral(address indexed buyer, address indexed asset, uint baseAmount, uint collateralAmount);
/// @notice Event emitted when an action is paused/unpaused
event PauseAction(bool supplyPaused, bool transferPaused, bool withdrawPaused, bool absorbPaused, bool buyPaused);
/// @notice Event emitted when reserves are withdrawn by the governor
event WithdrawReserves(address indexed to, uint amount);
function supply(address asset, uint amount) virtual external;
function supplyTo(address dst, address asset, uint amount) virtual external;
function supplyFrom(address from, address dst, address asset, uint amount) virtual external;
function transfer(address dst, uint amount) virtual external returns (bool);
function transferFrom(address src, address dst, uint amount) virtual external returns (bool);
function transferAsset(address dst, address asset, uint amount) virtual external;
function transferAssetFrom(address src, address dst, address asset, uint amount) virtual external;
function withdraw(address asset, uint amount) virtual external;
function withdrawTo(address to, address asset, uint amount) virtual external;
function withdrawFrom(address src, address to, address asset, uint amount) virtual external;
function approveThis(address manager, address asset, uint amount) virtual external;
function withdrawReserves(address to, uint amount) virtual external;
function absorb(address absorber, address[] calldata accounts) virtual external;
function buyCollateral(address asset, uint minAmount, uint baseAmount, address recipient) virtual external;
function quoteCollateral(address asset, uint baseAmount) virtual public view returns (uint);
function getAssetInfo(uint8 i) virtual public view returns (AssetInfo memory);
function getAssetInfoByAddress(address asset) virtual public view returns (AssetInfo memory);
function getCollateralReserves(address asset) virtual public view returns (uint);
function getReserves() virtual public view returns (int);
function getPrice(address priceFeed) virtual public view returns (uint);
function isBorrowCollateralized(address account) virtual public view returns (bool);
function isLiquidatable(address account) virtual public view returns (bool);
function totalSupply() virtual external view returns (uint256);
function totalBorrow() virtual external view returns (uint256);
function balanceOf(address owner) virtual public view returns (uint256);
function borrowBalanceOf(address account) virtual public view returns (uint256);
function pause(bool supplyPaused, bool transferPaused, bool withdrawPaused, bool absorbPaused, bool buyPaused) virtual external;
function isSupplyPaused() virtual public view returns (bool);
function isTransferPaused() virtual public view returns (bool);
function isWithdrawPaused() virtual public view returns (bool);
function isAbsorbPaused() virtual public view returns (bool);
function isBuyPaused() virtual public view returns (bool);
function accrueAccount(address account) virtual external;
function getSupplyRate(uint utilization) virtual public view returns (uint64);
function getBorrowRate(uint utilization) virtual public view returns (uint64);
function getUtilization() virtual public view returns (uint);
function governor() virtual external view returns (address);
function pauseGuardian() virtual external view returns (address);
function baseToken() virtual external view returns (address);
function baseTokenPriceFeed() virtual external view returns (address);
function extensionDelegate() virtual external view returns (address);
/// @dev uint64
function supplyKink() virtual external view returns (uint);
/// @dev uint64
function supplyPerSecondInterestRateSlopeLow() virtual external view returns (uint);
/// @dev uint64
function supplyPerSecondInterestRateSlopeHigh() virtual external view returns (uint);
/// @dev uint64
function supplyPerSecondInterestRateBase() virtual external view returns (uint);
/// @dev uint64
function borrowKink() virtual external view returns (uint);
/// @dev uint64
function borrowPerSecondInterestRateSlopeLow() virtual external view returns (uint);
/// @dev uint64
function borrowPerSecondInterestRateSlopeHigh() virtual external view returns (uint);
/// @dev uint64
function borrowPerSecondInterestRateBase() virtual external view returns (uint);
/// @dev uint64
function storeFrontPriceFactor() virtual external view returns (uint);
/// @dev uint64
function baseScale() virtual external view returns (uint);
/// @dev uint64
function trackingIndexScale() virtual external view returns (uint);
/// @dev uint64
function baseTrackingSupplySpeed() virtual external view returns (uint);
/// @dev uint64
function baseTrackingBorrowSpeed() virtual external view returns (uint);
/// @dev uint104
function baseMinForRewards() virtual external view returns (uint);
/// @dev uint104
function baseBorrowMin() virtual external view returns (uint);
/// @dev uint104
function targetReserves() virtual external view returns (uint);
function numAssets() virtual external view returns (uint8);
function decimals() virtual external view returns (uint8);
function initializeStorage() virtual external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
/**
* @title Compound's Comet Math Contract
* @dev Pure math functions
* @author Compound
*/
contract CometMath {
/** Custom errors **/
error InvalidUInt64();
error InvalidUInt104();
error InvalidUInt128();
error InvalidInt104();
error InvalidInt256();
error NegativeNumber();
function safe64(uint n) internal pure returns (uint64) {
if (n > type(uint64).max) revert InvalidUInt64();
return uint64(n);
}
function safe104(uint n) internal pure returns (uint104) {
if (n > type(uint104).max) revert InvalidUInt104();
return uint104(n);
}
function safe128(uint n) internal pure returns (uint128) {
if (n > type(uint128).max) revert InvalidUInt128();
return uint128(n);
}
function signed104(uint104 n) internal pure returns (int104) {
if (n > uint104(type(int104).max)) revert InvalidInt104();
return int104(n);
}
function signed256(uint256 n) internal pure returns (int256) {
if (n > uint256(type(int256).max)) revert InvalidInt256();
return int256(n);
}
function unsigned104(int104 n) internal pure returns (uint104) {
if (n < 0) revert NegativeNumber();
return uint104(n);
}
function unsigned256(int256 n) internal pure returns (uint256) {
if (n < 0) revert NegativeNumber();
return uint256(n);
}
function toUInt8(bool x) internal pure returns (uint8) {
return x ? 1 : 0;
}
function toBool(uint8 x) internal pure returns (bool) {
return x != 0;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
/**
* @title Compound's Comet Storage Interface
* @dev Versions can enforce append-only storage slots via inheritance.
* @author Compound
*/
contract CometStorage {
// 512 bits total = 2 slots
struct TotalsBasic {
// 1st slot
uint64 baseSupplyIndex;
uint64 baseBorrowIndex;
uint64 trackingSupplyIndex;
uint64 trackingBorrowIndex;
// 2nd slot
uint104 totalSupplyBase;
uint104 totalBorrowBase;
uint40 lastAccrualTime;
uint8 pauseFlags;
}
struct TotalsCollateral {
uint128 totalSupplyAsset;
uint128 _reserved;
}
struct UserBasic {
int104 principal;
uint64 baseTrackingIndex;
uint64 baseTrackingAccrued;
uint16 assetsIn;
uint8 _reserved;
}
struct UserCollateral {
uint128 balance;
uint128 _reserved;
}
struct LiquidatorPoints {
uint32 numAbsorbs;
uint64 numAbsorbed;
uint128 approxSpend;
uint32 _reserved;
}
/// @dev Aggregate variables tracked for the entire market
uint64 internal baseSupplyIndex;
uint64 internal baseBorrowIndex;
uint64 internal trackingSupplyIndex;
uint64 internal trackingBorrowIndex;
uint104 internal totalSupplyBase;
uint104 internal totalBorrowBase;
uint40 internal lastAccrualTime;
uint8 internal pauseFlags;
/// @notice Aggregate variables tracked for each collateral asset
mapping(address => TotalsCollateral) public totalsCollateral;
/// @notice Mapping of users to accounts which may be permitted to manage the user account
mapping(address => mapping(address => bool)) public isAllowed;
/// @notice The next expected nonce for an address, for validating authorizations via signature
mapping(address => uint) public userNonce;
/// @notice Mapping of users to base principal and other basic data
mapping(address => UserBasic) public userBasic;
/// @notice Mapping of users to collateral data per collateral asset
mapping(address => mapping(address => UserCollateral)) public userCollateral;
/// @notice Mapping of magic liquidator points
mapping(address => LiquidatorPoints) public liquidatorPoints;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
import "./CometCore.sol";
/**
* @title Compound's Asset List
* @author Compound
*/
interface IAssetList {
function getAssetInfo(uint8 i) external view returns (CometCore.AssetInfo memory);
function numAssets() external view returns (uint8);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
import "./CometCore.sol";
/**
* @title Compound's Asset List Factory
* @author Compound
*/
interface IAssetListFactory {
/**
* @notice Create a new asset list
* @param assetConfigs The asset configurations
* @return assetList The address of the new asset list
*/
function createAssetList(CometCore.AssetConfig[] memory assetConfigs) external returns (address assetList);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
/**
* @title Compound's Asset List Factory Holder Interface
* @author Compound
*/
interface IAssetListFactoryHolder {
/**
* @notice Get the asset list factory
* @return assetListFactory The asset list factory address
*/
function assetListFactory() external view returns (address);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
/**
* @title IERC20NonStandard
* @dev Version of ERC20 with no return values for `approve`, `transfer`, and `transferFrom`
* See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
*/
interface IERC20NonStandard {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param spender The address of the account which may transfer tokens
* @param amount The number of tokens that are approved (-1 means infinite)
*/
function approve(address spender, uint256 amount) external;
/**
* @notice Transfer `value` tokens from `msg.sender` to `to`
* @param to The address of the destination account
* @param value The number of tokens to transfer
*/
function transfer(address to, uint256 value) external;
/**
* @notice Transfer `value` tokens from `from` to `to`
* @param from The address of the source account
* @param to The address of the destination account
* @param value The number of tokens to transfer
*/
function transferFrom(address from, address to, uint256 value) external;
/**
* @notice Gets the balance of the specified address
* @param account The address from which the balance will be retrieved
*/
function balanceOf(address account) external view returns (uint256);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
/**
* @dev Interface for price feeds used by Comet
* Note This is Chainlink's AggregatorV3Interface, but without the `getRoundData` function.
*/
interface IPriceFeed {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}{
"optimizer": {
"enabled": true,
"runs": 1,
"details": {
"yulDetails": {
"optimizerSteps": "dhfoDgvulfnTUtnIf [xa[r]scLM cCTUtTOntnfDIul Lcul Vcul [j] Tpeul xa[rul] xa[r]cL gvif CTUca[r]LsTOtfDnca[r]Iulc] jmul[jul] VcTOcul jmul"
}
}
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"viaIR": true,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"components":[{"internalType":"address","name":"governor","type":"address"},{"internalType":"address","name":"pauseGuardian","type":"address"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"baseTokenPriceFeed","type":"address"},{"internalType":"address","name":"extensionDelegate","type":"address"},{"internalType":"uint64","name":"supplyKink","type":"uint64"},{"internalType":"uint64","name":"supplyPerYearInterestRateSlopeLow","type":"uint64"},{"internalType":"uint64","name":"supplyPerYearInterestRateSlopeHigh","type":"uint64"},{"internalType":"uint64","name":"supplyPerYearInterestRateBase","type":"uint64"},{"internalType":"uint64","name":"borrowKink","type":"uint64"},{"internalType":"uint64","name":"borrowPerYearInterestRateSlopeLow","type":"uint64"},{"internalType":"uint64","name":"borrowPerYearInterestRateSlopeHigh","type":"uint64"},{"internalType":"uint64","name":"borrowPerYearInterestRateBase","type":"uint64"},{"internalType":"uint64","name":"storeFrontPriceFactor","type":"uint64"},{"internalType":"uint64","name":"trackingIndexScale","type":"uint64"},{"internalType":"uint64","name":"baseTrackingSupplySpeed","type":"uint64"},{"internalType":"uint64","name":"baseTrackingBorrowSpeed","type":"uint64"},{"internalType":"uint104","name":"baseMinForRewards","type":"uint104"},{"internalType":"uint104","name":"baseBorrowMin","type":"uint104"},{"internalType":"uint104","name":"targetReserves","type":"uint104"},{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint64","name":"borrowCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidateCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidationFactor","type":"uint64"},{"internalType":"uint128","name":"supplyCap","type":"uint128"}],"internalType":"struct CometConfiguration.AssetConfig[]","name":"assetConfigs","type":"tuple[]"}],"internalType":"struct CometConfiguration.Configuration","name":"config","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Absurd","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BadAsset","type":"error"},{"inputs":[],"name":"BadDecimals","type":"error"},{"inputs":[],"name":"BadDiscount","type":"error"},{"inputs":[],"name":"BadMinimum","type":"error"},{"inputs":[],"name":"BadPrice","type":"error"},{"inputs":[],"name":"BorrowCFTooLarge","type":"error"},{"inputs":[],"name":"BorrowTooSmall","type":"error"},{"inputs":[],"name":"InsufficientReserves","type":"error"},{"inputs":[],"name":"InvalidInt104","type":"error"},{"inputs":[],"name":"InvalidInt256","type":"error"},{"inputs":[],"name":"InvalidUInt104","type":"error"},{"inputs":[],"name":"InvalidUInt128","type":"error"},{"inputs":[],"name":"InvalidUInt64","type":"error"},{"inputs":[],"name":"LiquidateCFTooLarge","type":"error"},{"inputs":[],"name":"NegativeNumber","type":"error"},{"inputs":[],"name":"NoSelfTransfer","type":"error"},{"inputs":[],"name":"NotCollateralized","type":"error"},{"inputs":[],"name":"NotForSale","type":"error"},{"inputs":[],"name":"NotLiquidatable","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"ReentrantCallBlocked","type":"error"},{"inputs":[],"name":"SupplyCapExceeded","type":"error"},{"inputs":[],"name":"TimestampTooLarge","type":"error"},{"inputs":[],"name":"TooManyAssets","type":"error"},{"inputs":[],"name":"TooMuchSlippage","type":"error"},{"inputs":[],"name":"TransferInFailed","type":"error"},{"inputs":[],"name":"TransferOutFailed","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"absorber","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralAbsorbed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdValue","type":"uint256"}],"name":"AbsorbCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"absorber","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"basePaidOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdValue","type":"uint256"}],"name":"AbsorbDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"baseAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"BuyCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"supplyPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"transferPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"withdrawPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"absorbPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"buyPaused","type":"bool"}],"name":"PauseAction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Supply","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SupplyCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawReserves","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"absorber","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"absorb","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"accrueAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveThis","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"assetList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseBorrowMin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseMinForRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenPriceFeed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTrackingBorrowSpeed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTrackingSupplySpeed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"borrowBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowKink","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowPerSecondInterestRateBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowPerSecondInterestRateSlopeHigh","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowPerSecondInterestRateSlopeLow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"uint256","name":"baseAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"buyCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extensionDelegate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"i","type":"uint8"}],"name":"getAssetInfo","outputs":[{"components":[{"internalType":"uint8","name":"offset","type":"uint8"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint64","name":"scale","type":"uint64"},{"internalType":"uint64","name":"borrowCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidateCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidationFactor","type":"uint64"},{"internalType":"uint128","name":"supplyCap","type":"uint128"}],"internalType":"struct CometCore.AssetInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getAssetInfoByAddress","outputs":[{"components":[{"internalType":"uint8","name":"offset","type":"uint8"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint64","name":"scale","type":"uint64"},{"internalType":"uint64","name":"borrowCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidateCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidationFactor","type":"uint64"},{"internalType":"uint128","name":"supplyCap","type":"uint128"}],"internalType":"struct CometCore.AssetInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"utilization","type":"uint256"}],"name":"getBorrowRate","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getCollateralReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"priceFeed","type":"address"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"utilization","type":"uint256"}],"name":"getSupplyRate","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUtilization","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"manager","type":"address"}],"name":"hasPermission","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initializeStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isAbsorbPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isBorrowCollateralized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBuyPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isLiquidatable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSupplyPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTransferPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWithdrawPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"liquidatorPoints","outputs":[{"internalType":"uint32","name":"numAbsorbs","type":"uint32"},{"internalType":"uint64","name":"numAbsorbed","type":"uint64"},{"internalType":"uint128","name":"approxSpend","type":"uint128"},{"internalType":"uint32","name":"_reserved","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numAssets","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"supplyPaused","type":"bool"},{"internalType":"bool","name":"transferPaused","type":"bool"},{"internalType":"bool","name":"withdrawPaused","type":"bool"},{"internalType":"bool","name":"absorbPaused","type":"bool"},{"internalType":"bool","name":"buyPaused","type":"bool"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseGuardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"baseAmount","type":"uint256"}],"name":"quoteCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"storeFrontPriceFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"supply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"supplyFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyKink","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyPerSecondInterestRateBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyPerSecondInterestRateSlopeHigh","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyPerSecondInterestRateSlopeLow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"supplyTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalsCollateral","outputs":[{"internalType":"uint128","name":"totalSupplyAsset","type":"uint128"},{"internalType":"uint128","name":"_reserved","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trackingIndexScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferAssetFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBasic","outputs":[{"internalType":"int104","name":"principal","type":"int104"},{"internalType":"uint64","name":"baseTrackingIndex","type":"uint64"},{"internalType":"uint64","name":"baseTrackingAccrued","type":"uint64"},{"internalType":"uint16","name":"assetsIn","type":"uint16"},{"internalType":"uint8","name":"_reserved","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userCollateral","outputs":[{"internalType":"uint128","name":"balance","type":"uint128"},{"internalType":"uint128","name":"_reserved","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6103a0806040523462000a7c57620053b1803803809162000021828562000a97565b8339602082828101031262000a7c5781516001600160401b03811162000a7c576102a0818401838501031262000a7c5760405192620000636102a08562000a97565b6200007082820162000abb565b84526200008260208383010162000abb565b60208501526200009760408383010162000abb565b6040850152620000ac60608383010162000abb565b6060850152620000c160808383010162000abb565b6080850152620000d660a08383010162000ad0565b60a0850152620000eb60c08383010162000ad0565b60c08501526200010060e08383010162000ad0565b60e0850152620001166101008383010162000ad0565b6101008501526200012d6101208383010162000ad0565b610120850152620001446101408383010162000ad0565b6101408501526200015b6101608383010162000ad0565b610160850152620001726101808383010162000ad0565b610180850152620001896101a08383010162000ad0565b6101a0850152620001a06101c08383010162000ad0565b6101c0850152620001b76101e08383010162000ad0565b6101e0850152620001ce6102008383010162000ad0565b610200850152620001e56102208383010162000ae5565b610220850152620001fc6102408383010162000ae5565b610240850152620002136102608383010162000ae5565b6102608501528082016102800151926001600160401b03841162000a7c57808201601f858585010101121562000a7c57818301840151916001600160401b03831162000a8157604051946200026f60208560051b018762000a97565b8386526020860194838301602060e08702848487010101011162000a7c57828101820160200195915b602060e08702828487010101018710620009be5761028089018890526040808a0151905163313ce56760e01b81528a91602090829060049082906001600160a01b03165afa9081156200080f576000916200097c575b50601260ff821611620008ed576101a0820151670de0b6b3a76400006001600160401b03909116116200096a576018610280830151511162000958576102208201516001600160681b0316156200094657606082015160405163313ce56760e01b815290602090829060049082906001600160a01b03165afa9081156200080f57600091620008ff575b5060ff6008911603620008ed5781516001600160a01b0390811660809081526020840151821660a0526040840151821660c0526060840151821660e05283015116610100526101a08201516001600160401b039081166102205261032082905260ff909116600a0a81166102408190526101c083015190911661026052620f424011620008ed576102408051620f42409004610360526102208201516001600160681b039081166102c0526101e0808401516001600160401b039081166102809081526102008087015183166102a0529486015184166102e0526102608601519093166103005260a0850151811661012090815260c08601516301e13380908316819004831661014090815260e088015184168290048416610160908152610100808a015186168490048616610180908152948a015186166101a05291890151851683900485166101c0528801518416829004841690945290860151821604169092528201515160ff166103405251604051630e085c5b60e31b81529190602090839060049082906001600160a01b03165afa9182156200080f57600092620008a3575b50610280015190604051809263ba15b9d160e01b82526024820160206004840152815180915260206044840192019060005b8181106200081b57506020949284900392849250600091506001600160a01b03165af19081156200080f57600091620007ca575b50610380526040516148a762000b0a823960805181818161063801528181610d71015281816114110152611811015260a0518181816108780152610e77015260c05181818161081e01528181611390015281816115f90152818161187a01528181611932015281816126b301528181612f550152818161308d015281816138d801528181613d1c0152613dfd015260e051818181611a7001528181612818015281816142ac01526146c7015261010051818181610eb701526147ff01526101205181818161133e01526121a8015261014051818181610f55015281816121e4015261224e015261016051818181611064015261227e0152610180518181816111c6015261220b01526101a05181818161114e01526122b801526101c051818181610a27015281816122f4015261235e01526101e051818181610931015261238e015261020051818181610fe0015261231b0152610220518181816107ae015261468b015261024051818181610cf10152818161283e01528181612b950152818161431c01526146ff0152610260518181816113d00152612e300152610280518181816106ec015261207401526102a0518181816112020152611ffc01526102c05181818161118a0152611f6e01526102e051818181610aa101528181613b1e0152613e9c015261030051818181610b1c0152611a2001526103205181610adf01526103405181818161130101528181611d4d0152818161287501528181612a7e01526142da01526103605181612e570152610380518181816117b60152611c3601526148a790f35b6020813d60201162000806575b81620007e66020938362000a97565b810103126200080257620007fb915062000abb565b8162000582565b5080fd5b3d9150620007d7565b6040513d6000823e3d90fd5b825180516001600160a01b0390811686526020828101519091168187015260408083015160ff16908701526060808301516001600160401b039081169188019190915260808084015182169088015260a0808401519091169087015260c0918201516001600160801b03169186019190915287955060e090940193909201916001016200054e565b90916020823d602011620008e4575b81620008c16020938362000a97565b81010312620008e15750620008d96102809162000abb565b91906200051c565b80fd5b3d9150620008b2565b604051630456c65960e51b8152600490fd5b906020823d6020116200093d575b816200091c6020938362000a97565b81010312620008e1575060ff6200093560089262000afa565b915062000378565b3d91506200090d565b604051636e77247560e01b8152600490fd5b60405163df8153c760e01b8152600490fd5b6040516324dc918f60e11b8152600490fd5b906020823d602011620009b5575b81620009996020938362000a97565b81010312620008e15750620009ae9062000afa565b82620002ee565b3d91506200098a565b60e087868601031262000a7c5760405192620009dc60e08562000a97565b620009e78862000abb565b8452620009f76020890162000abb565b602085015262000a0a6040890162000afa565b604085015262000a1d6060890162000ad0565b606085015262000a306080890162000ad0565b608085015262000a4360a0890162000ad0565b60a085015260c0880151936001600160801b038516850362000a7c57602060e09282829760c08695015281520198019793505062000298565b600080fd5b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b0382119082101762000a8157604052565b51906001600160a01b038216820362000a7c57565b51906001600160401b038216820362000a7c57565b51906001600160681b038216820362000a7c57565b519060ff8216820362000a7c5756fe60806040526004361015610018575b6100166147f2565b005b60003560e01c8063042e02cf146105685780630902f1ac1461055f5780630bc47ad1146105565780630c340a241461054d57806318160ddd14610544578063189bb2f11461053b5780631c9f7fb9146105325780631f5954bd1461052957806323b872dd1461052057806324a3d62214610517578063264413181461050e5780632a48cf12146105055780632b92a07d146104fc5780632d05670b146104f35780632e04b8e7146104ea578063300e6beb146104e1578063313ce567146104d857806332176c49146104cf578063374c49b4146104c657806338aa813f146104bd5780633b3bec2e146104b457806341976e09146104ab5780634232cd63146104a2578063439e2e451461049957806344c1e5eb1461049057806344c35d071461048757806344ff241d1461047e57806359e017bd146104755780635a94b8d11461046c57806367800b5f1461046357806370a082311461045a5780637914acc7146104515780637ac88ed1146104485780637eb711311461043f578063804de71f146104365780638285ef401461042d5780638d5d814c14610424578063903231771461041b5780639241a561146104125780639364e18a1461040957806394920cca146104005780639ea99a5a146103f75780639fa83b5a146103ee5780639ff567f8146103e5578063a1654379146103dc578063a1a1ef43146103d3578063a46fe83b146103ca578063a5b4ff79146103c1578063a9059cbb146103b8578063aba7f15e146103af578063ad14777c146103a6578063bfe69c8d1461039d578063c1ee2c1814610394578063c3b35a7e1461038b578063c3cecfd214610382578063c55dae6314610379578063c5fa15cf14610370578063c8c7fe6b14610367578063cde680411461035e578063d8e5f61114610355578063d955759d1461034c578063dc4abafd14610343578063e372f03a1461033a578063e478795d14610331578063e4e6e77914610328578063e7dad6bd1461031f578063f2b9fdb8146103165763f3fef3a30361000e57610311611ad4565b61000e565b50610311611a9f565b50610311611a59565b506103116118d0565b506103116117e5565b5061031161179f565b5061031161172c565b5061031161170d565b506103116116e6565b506103116116ca565b506103116116a1565b50610311611628565b506103116115e2565b5061031161157d565b50610311611559565b50610311611533565b50610311611498565b506103116113f3565b506103116113b7565b50610311611361565b50610311611325565b506103116112e6565b506103116112bf565b5061031161127e565b50610311611256565b50610311611225565b506103116111e9565b506103116111ad565b50610311611171565b50610311611135565b5061031161110f565b506103116110e8565b50610311611087565b5061031161104b565b5061031161102f565b50610311611003565b50610311610fc7565b50610311610f9f565b50610311610f78565b50610311610f3c565b50610311610ee6565b50610311610ea0565b50610311610d21565b50610311610cd8565b50610311610cb4565b50610311610c90565b50610311610c68565b50610311610c33565b50610311610b67565b50610311610b3f565b50610311610b03565b50610311610ac4565b50610311610a88565b50610311610a4a565b50610311610a0e565b506103116109b9565b50610311610918565b506103116108de565b50610311610861565b506103116107fe565b50610311610795565b5061031161070f565b506103116106d3565b50610311610667565b50610311610621565b506103116105e8565b506103116105c4565b50610311610587565b6001600160a01b0381160361058257565b600080fd5b50346105825760203660031901126105825760206105af6004356105aa81610571565b612a35565b6040519015158152f35b600091031261058257565b50346105825760003660031901126105825760206105e0612661565b604051908152f35b50346105825760003660031901126105825760206001805460f81c161515604051908152f35b6001600160a01b03909116815260200190565b5034610582576000366003190112610582576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461058257600036600319011261058257602066038d7ea4c680006106ca61068e611dbe565b6106b1600154916106ab64ffffffffff91828560d01c1690611e49565b166120fd565b506001600160401b0316906001600160681b0316611e77565b04604051908152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b5034610582576000806003193601126107925760015464ffffffffff8160d01c166107815764ffffffffff60d01b610745611dbe565b64ffffffffff60d01b1990921660d09290921b161760015580546001600160801b0319166e038d7ea4c6800000038d7ea4c68000178155604051f35b60405162dc149f60e41b8152600490fd5b80fd5b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b908160609103126105825780356107e781610571565b91604060208301356107f881610571565b92013590565b5034610582576108446108123660046107d1565b919061081c612fd5565b7f000000000000000000000000000000000000000000000000000000000000000091336138a0565b600060008051602061485283398151915255602060405160018152f35b5034610582576000366003190112610582576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b91908260809103126105825781356108be81610571565b9160208101356108cd81610571565b91606060408301356107f881610571565b5034610582576109046108f23660046108a7565b926108fe929192612fd5565b33613ced565b600060008051602061485283398151915255005b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b9190826040910312610582576020823561096d81610571565b92013561097981610571565b90565b9060018060a01b0316600052602052604060002090565b6001600160801b031690565b6001600160801b0391821681529116602082015260400190565b503461058257610a0a6109ee6109d0366004610954565b6001600160a01b03909116600090815260066020526040902061097c565b54604051918291608081901c906001600160801b03168361099f565b0390f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b503461058257602036600319011261058257600435610a6881610571565b60018060a01b031660005260046020526020604060002054604051908152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b503461058257600036600319011261058257602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105825760203660031901126105825760206105e0600435610b6281610571565b6147aa565b50346105825760203660031901126105825760206105af600435610b8a81610571565b6127b4565b6001600160401b031690565b610c319092919260e08061010083019560ff815116845260018060a01b03806020830151166020860152604082015116604085015260018060401b036060820151166060850152610bfb6080820151608086019060018060401b03169052565b60a0818101516001600160401b03169085015260c0818101516001600160401b03169085015201516001600160801b0316910152565b565b503461058257602036600319011261058257610a0a610c5c600435610c5781610571565b611d3a565b60405191829182610b9b565b50346105825760203660031901126105825760206105e0600435610c8b81610571565b61249f565b503461058257610904610ca43660046107d1565b91610cad612fd5565b3333612f23565b503461058257610904610cc83660046107d1565b91610cd1612fd5565b33336138a0565b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3590811515820361058257565b50346105825760a036600319011261058257610d3d6004610d14565b610d476024610d14565b610d516044610d14565b91610d5c6064610d14565b92610d676084610d14565b60018060a01b03807f0000000000000000000000000000000000000000000000000000000000000000163314159081610e73575b50610e62577f3be39979091ae7ca962aa1c44e645f2df3c221b79f324afa5f44aedc8d2f690d94610e5d92610e28610de56000610dd788612b6e565b9060ff8080931691161b1690565b610df36001610dd78a612b6e565b17610e026002610dd785612b6e565b17610e116003610dd786612b6e565b17610e206004610dd787612b6e565b176001612b4b565b6040519586958693909594919260809360a0860197151586521515602086015215156040850152151560608401521515910152565b0390a1005b6040516282b42960e81b8152600490fd5b90507f00000000000000000000000000000000000000000000000000000000000000001633141538610d9b565b5034610582576000366003190112610582576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461058257602036600319011261058257600435610f0481610571565b6001600160a01b031660009081526002602052604090819020549051908190610a0a90608081901c906001600160801b03168361099f565b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b5034610582576000366003190112610582576020600460015460f81c161515604051908152f35b50346105825760203660031901126105825760206105e0600435610fc281610571565b61474c565b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105825760403660031901126105825760206105e060043561102681610571565b6024359061462d565b50346105825760003660031901126105825760206105e06123ec565b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b503461058257600036600319011261058257602066038d7ea4c680006106ca6110ae611dbe565b6110cb600154916106ab64ffffffffff91828560d01c1690611e49565b6001600160401b03169160681c6001600160681b03169050611e77565b5034610582576000366003190112610582576020600860015460f81c161515604051908152f35b5034610582576109046111233660046108a7565b9261112f929192612fd5565b33612f23565b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105825760203660031901126105825760206112446004356122b6565b6040516001600160401b039091168152f35b50346105825760203660031901126105825760206105e060043561127981610571565b612559565b503461058257602060ff6112b3611296366004610954565b6001600160a01b039091166000908152600385526040902061097c565b54166040519015158152f35b5034610582576000366003190112610582576020600260015460f81c161515604051908152f35b503461058257600036600319011261058257602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105825760403660031901126105825761084460043561138281610571565b61138a612fd5565b602435907f00000000000000000000000000000000000000000000000000000000000000009033336138a0565b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b5034610582576114043660046107d1565b91906001600160a01b03907f000000000000000000000000000000000000000000000000000000000000000082163303610e62571691823b1561058257611465926000928360405180968195829463095ea7b360e01b845260048401613ed6565b03925af1801561148b575b61147657005b80611485600061001693611b46565b806105b9565b611493611bfe565b611470565b5034610582576020366003190112610582576100166004356114b981610571565b6114c1611ece565b60018060a01b03811660005260056020526040600020611528604051916114e960a084611b46565b54600c81900b83526001600160401b03606882901c8116602085015260a882901c16604084015261ffff60e882901c16606084015260f81c6080830152565b8051600c0b91612db5565b5034610582576109046115473660046108a7565b92611553929192612fd5565b336138a0565b50346105825761090461156d3660046107d1565b91611576612fd5565b3333613ced565b50346105825760403660031901126105825760043561159b81610571565b602435906001600160401b03908183116105825736602384011215610582578260040135918211610582573660248360051b85010111610582576024610016930190614118565b5034610582576000366003190112610582576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346105825760203660031901126105825760043561164681610571565b60018060a01b0316600052600760205260806040600020546040519063ffffffff8116825260018060401b038160201c166020830152600180841b038160601c16604083015260e01c6060820152f35b60ff81160361058257565b503461058257602036600319011261058257610a0a610c5c6004356116c581611696565b611c0b565b50346105825760206105af6116e0366004610954565b90611b09565b5034610582576000366003190112610582576020601060015460f81c161515604051908152f35b50346105825760203660031901126105825760206112446004356121a6565b50346105825760203660031901126105825760043561174a81610571565b60018060a01b0316600052600560205260a06040600020546040519080600c0b825260018060401b03808260681c1660208401528160a81c16604083015261ffff8160e81c16606083015260f81c6080820152f35b5034610582576000366003190112610582576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346105825760403660031901126105825760043561180381610571565b602435906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081163303610e6257611840612661565b600081129081156118be575b506118ac578161189e847fec4431f2ba1a9382f6b0c4352b888cba6f7db91667d9f776abe5ad8ddc5401b6947f0000000000000000000000000000000000000000000000000000000000000000613ef1565b6040519384521691602090a2005b60405163128bd24d60e31b8152600490fd5b6118c89150614622565b83113861184c565b5034610582576080366003190112610582576004356118ee81610571565b606435906118fb82610571565b611903612fd5565b601060015460f81c16611a4757611918612661565b60008112159081611a1c575b50611a0a57611956604435337f00000000000000000000000000000000000000000000000000000000000000006133d8565b90611961828261462d565b9260243584106119f85761197482612559565b84116118ac577ff891b2a411b0e66a5f0a6ff1368670fefa287a13f541eb633a386a1a9cc7046b916119bb6119de926119b46119af88612faf565b610993565b9083613ef1565b6040805194855260208501959095526001600160a01b0316933393918291820190565b0390a3610016600060008051602061485283398151915255565b60405163fa6ad35560e01b8152600490fd5b604051631d99ddbf60e01b8152600490fd5b90507f0000000000000000000000000000000000000000000000000000000000000000111538611924565b6040516313d0ff5960e31b8152600490fd5b5034610582576000366003190112610582576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b503461058257604036600319011261058257610904600435611ac081610571565b611ac8612fd5565b60243590333333612f23565b503461058257604036600319011261058257610904600435611af581610571565b611afd612fd5565b60243590333333613ced565b6001600160a01b03808316911690811491908215611b2657505090565b60ff925090611b41916000526003602052604060002061097c565b541690565b601f909101601f19168101906001600160401b03821190821017611b6957604052565b634e487b7160e01b600052604160045260246000fd5b60405190611b8f61010083611b46565b8160e06000918281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b5190610c3182611696565b5190610c3182610571565b51906001600160401b038216820361058257565b51906001600160801b038216820361058257565b506040513d6000823e3d90fd5b611c13611b7f565b5060405163c8c7fe6b60e01b815260ff91909116600482015261010080826024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa918215611d2d575b600092611c7457505090565b90918282813d8311611d26575b611c8b8183611b46565b81010312610792575060e0611d1e91611ca76040519485611b46565b611cb081611bc0565b8452611cbe60208201611bcb565b6020850152611ccf60408201611bcb565b6040850152611ce060608201611bd6565b6060850152611cf160808201611bd6565b6080850152611d0260a08201611bd6565b60a0850152611d1360c08201611bd6565b60c085015201611bea565b60e082015290565b503d611c81565b611d35611bfe565b611c68565b90611d43611b7f565b5060009060ff92837f000000000000000000000000000000000000000000000000000000000000000016925b8385821610611d8a57604051633640530560e01b8152600490fd5b611d9381611c0b565b60208101516001600160a01b03848116911614611db557506001018416611d6f565b93505050915090565b600160281b421015611dd55764ffffffffff421690565b604051633d32ffdb60e01b8152600490fd5b90604051611df660a082611b46565b608081935480600c0b835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c910152565b50634e487b7160e01b600052601160045260246000fd5b64ffffffffff9182169116818110611e5f570390565b611e67611e32565b0390565b6001600160681b031690565b8060001904821181151516611e8a570290565b611e92611e32565b0290565b6001600160401b0391821691908116908290038111611eb3570190565b611ebb611e32565b0190565b60681c6001600160681b031690565b611ed6611dbe565b611f00611ef6611ef060015464ffffffffff9060d01c1690565b83611e49565b64ffffffffff1690565b9081611f0a575050565b81611f61611f1a610c31946120fd565b60008054600160401b600160801b03191660409290921b600160401b600160801b0316919091178155919082546001600160401b0319166001600160401b03909116178255565b611f6c600154611e6b565b7f000000000000000000000000000000000000000000000000000000000000000092906001600160681b031683811015612061575b50611fb5611fb0600154611ebf565b611e6b565b92831015611fe9575b50506001805464ffffffffff60d01b191660d09390931b64ffffffffff60d01b169290921790915550565b61202a61202561205994612020612039947f0000000000000000000000000000000000000000000000000000000000000000611e77565b612b8f565b6120d7565b825460c01c611e96565b611e96565b81546001600160c01b031660c09190911b6001600160c01b031916179055565b388080611fbe565b6120ab6120986120256120d193612020867f0000000000000000000000000000000000000000000000000000000000000000611e77565b845460801c6001600160401b0316611e96565b8354600160801b600160c01b03191660809190911b600160801b600160c01b0316178355565b38611fa1565b6001600160401b03908181116120eb571690565b6040516372a1cb5160e11b8152600490fd5b6000546001600160401b03604082901c81169392918116919081612122575b50509190565b8161217561216f61214f97946121816121879761217b8761215661217b996121486123ec565b9e8f6121a6565b169d6122b6565b169b61217561216f670de0b6b3a7640000998a93611e77565b84611e77565b046120d7565b90611e96565b98611e77565b91388061211c565b81198111611eb3570190565b818110611e5f570390565b7f000000000000000000000000000000000000000000000000000000000000000080821161222f5750612025670de0b6b3a7640000612208610979937f0000000000000000000000000000000000000000000000000000000000000000611e77565b047f000000000000000000000000000000000000000000000000000000000000000061218f565b61097991612025916122a2670de0b6b3a76400009161227283612208837f0000000000000000000000000000000000000000000000000000000000000000611e77565b938181106122a9575b037f0000000000000000000000000000000000000000000000000000000000000000611e77565b049061218f565b6122b1611e32565b61227b565b7f000000000000000000000000000000000000000000000000000000000000000080821161233f5750612025670de0b6b3a7640000612318610979937f0000000000000000000000000000000000000000000000000000000000000000611e77565b047f000000000000000000000000000000000000000000000000000000000000000061218f565b61097991612025916122a2670de0b6b3a76400009161238283612318837f0000000000000000000000000000000000000000000000000000000000000000611e77565b938181106123b2575b037f0000000000000000000000000000000000000000000000000000000000000000611e77565b6123ba611e32565b61238b565b50634e487b7160e01b600052601260045260246000fd5b81156123e0570490565b6123e86123bf565b0490565b60005460015466038d7ea4c680009061242e906001600160681b036001600160401b038461241e828816848616611e77565b049560401c169160681c16611e77565b048161243b575050600090565b670de0b6b3a764000090806000190482118115151661245957020490565b612461611e32565b020490565b66038d7ea4c68000916123e8916001600160401b0316906001600160681b0316611e77565b51906001600160501b038216820361058257565b604051633fabe5a360e21b81529060a090829060049082906001600160a01b03165afa90811561253d575b6000916124f1575b5060008113156124df5790565b60405163fd1ee34960e01b8152600490fd5b9060a0823d8211612535575b8161250a60a09383611b46565b81010312610792575061251c8161248b565b5061252e60806020830151920161248b565b50386124d2565b3d91506124fd565b612545611bfe565b6124ca565b90816020910312610582575190565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa9182156125e4575b6000926125b4575b506000908152600260205260409020546001600160801b031690818110611e5f570390565b6125d691925060203d81116125dd575b6125ce8183611b46565b81019061254a565b903861258f565b503d6125c4565b6125ec611bfe565b612587565b600082128015600160ff1b840183121661261b575b6001600160ff1b038301821316611e5f570390565b612623611e32565b612606565b6000811280156001600160ff1b03839003841316612654575b600160ff1b829003831216611eb3570190565b61265c611e32565b612641565b61097961266c611dbe565b61268f61268a611ef66001549364ffffffffff8560d01c1690611e49565b6120fd565b90604051926370a0823160e01b8452602084806126af306004830161060e565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa938415612784575b60009461274c575b509161274061273a61273a936127336127469666038d7ea4c680009260018060401b03846127268260018060681b039416848616611e77565b0497169160681c16611e77565b0495612791565b91612791565b906125f1565b90612628565b6127469391945061273a61273a936127336127776127409460203d81116125dd576125ce8183611b46565b97949650509350506126ed565b61278c611bfe565b6126e5565b6001600160ff1b0381116127a25790565b60405163e7e828ad60e01b8152600490fd5b6127c96127c282600561097c565b54600c0b90565b906000918281600c0b1215612981576127f16127e683600561097c565b5460e81c61ffff1690565b9061286c61281361280d61280686600561097c565b5460f81c90565b926129c0565b61283c7f000000000000000000000000000000000000000000000000000000000000000061249f565b7f00000000000000000000000000000000000000000000000000000000000000006001600160401b031691612bda565b92849160ff93847f000000000000000000000000000000000000000000000000000000000000000016935b84868216106128ab57505050505050121590565b6128b6838284612cc0565b6128c5575b6001018516612897565b958781121561297457600161296b87926127466129668861296061295b60808f6129236129166129026128fa61295394611c0b565b97600661097c565b60208801516001600160a01b03169061097c565b546001600160801b031690565b604086015161293a906001600160a01b031661249f565b6129476060880151610b8f565b918c80861b0316612bba565b930151610b8f565b610b8f565b90612b7c565b612791565b979150506128bb565b5050505050505050600190565b505050600190565b600c0b6001600160671b031981146129a2575b60000390565b6129aa611e32565b61299c565b600160ff1b81146129a25760000390565b6000600c82900b12612a00576000546109799166038d7ea4c68000916129fa916001600160401b03909116906001600160681b0316611e77565b04612791565b612a3061296661097992612a2160018060401b0360005460401c1691612989565b6001600160681b031690612466565b6129af565b612a436127c282600561097c565b906000918281600c0b1215612b4657612a606127e683600561097c565b90612a7561281361280d61280686600561097c565b92849160ff93847f000000000000000000000000000000000000000000000000000000000000000016935b8486821610612ab3575050505050501290565b612abe838284612cc0565b612acd575b6001018516612aa0565b9587811215612b3c576001612b3387926127466129668861296061295b60a08f612b026129166129026128fa61295394611c0b565b6040860151612b19906001600160a01b031661249f565b612b266060880151610b8f565b918c8060801b0316612bba565b97915050612ac3565b5050505050505090565b505090565b80546001600160f81b031660f89290921b6001600160f81b031916919091179055565b600090156109795750600190565b670de0b6b3a7640000916123e891611e77565b6123d6907f000000000000000000000000000000000000000000000000000000000000000090611e77565b90612bc491611e77565b6001600160401b039091169081156123e0570490565b9190612be590612791565b6000808413939082136001600160ff1b03858216848204841116612ca1575b600160ff1b95600085129185918316858905831216612c94575b60008512938416828905861216612c87575b058312911616612c7a575b6001600160401b03909216929102908215612c6d575b8114600019831416612c61570590565b612c69611e32565b0590565b612c756123bf565b612c51565b612c82611e32565b612c3b565b612c8f611e32565b612c30565b612c9c611e32565b612c1e565b612ca9611e32565b612c04565b60ff9182169116818110611e5f570390565b9060ff169160108310600014612cdf5750600161ffff921b1616151590565b905060188210612cf0575050600090565b600160ff8093600f1901161b1616151590565b6001600160401b039182169116818110611e5f570390565b805461ffff60e81b191660e89290921b61ffff60e81b16919091179055565b81518154602084015160408501516001600160e81b03199092166001600160681b039093169290921760689290921b600160681b600160a81b03169190911760a89190911b600160a81b600160e81b03161781556060820151610c319260ff9160809190612dac9061ffff1685612d1b565b01511690612b4b565b612ecc90610c3193612dc88451600c0b90565b600c82900b855260009182918683600c83900b8113612ee357612e55612e2e612e9b94612e1f61295b612e7c96612e196020612e11612025995460018060401b039060801c1690565b920151610b8f565b90612d03565b906001600160681b0316611e77565b7f0000000000000000000000000000000000000000000000000000000000000000906123d6565b7f0000000000000000000000000000000000000000000000000000000000000000906123d6565b612e8e60408901916120348351610b8f565b6001600160401b03169052565b600c0b12612ed15754612ec59060801c6001600160401b03165b6001600160401b03166020850152565b600561097c565b612d3a565b54612ede9060c01c612eb5565b612ec5565b612e55612e2e612f1e94612f19611fb0611e6b612f1361295b612e7c99612e196020612e116120259c5460c01c90565b93612989565b611e77565b612e9b565b939290936001805460f81c16611a4757612f40612f449186611b09565b1590565b610e62576001600160a01b038181167f000000000000000000000000000000000000000000000000000000000000000090911603612f9b5750610c31926000198303613082579150612f95816147aa565b91613082565b90612fa9610c319493612faf565b926135fc565b6001600160801b0390818111612fc3571690565b60405163762ea71160e11b8152600490fd5b6000805160206148528339815191526001815414612ff35760019055565b60405163139b643560e21b8152600490fd5b6001600160681b0391821691908116908290038111611eb3570190565b80546001600160681b0319166001600160681b03909216919091179055565b6001600160681b039182169116818110611e5f570390565b8054600160681b600160d01b03191660689290921b600160681b600160d01b0316919091179055565b6130b161312f9293827f00000000000000000000000000000000000000000000000000000000000000006133d8565b6130b9611ece565b61313c6130cf6130ca86600561097c565b611de7565b8051600c0b906131366130ff6130f86130f36130ea866129c0565b61274689612791565b6131c6565b809461335c565b979061311f6131188a613113600154611e6b565b613005565b6001613022565b61312a600154611ebf565b613041565b6001613059565b86612db5565b6040519081526001600160a01b0393841693849216907fd1cf3d156d5f8f0d50f6c122ed609cec09d35c9b9fb3fff6ea0959134dae424e90602090a36001600160681b03811661318a575050565b6000805160206148328339815191526131c16131b16000936131ac8554610b8f565b612466565b6040519081529081906020820190565b0390a3565b600081126131ec57600054610979916131e7916001600160401b0316613275565b6132eb565b6132496131e76109799261320d60018060401b0360005460401c16916129af565b613232826000199266038d7ea4c6800090808504821181151516613268575b0261218f565b6001811061325b575b821561324e575b01046132c5565b612989565b6132566123bf565b613242565b613263611e32565b61323b565b613270611e32565b61322c565b906109799166038d7ea4c680009082600019048211831515166132b8575b6001600160401b03169182156132ab575b02046132c5565b6132b36123bf565b6132a4565b6132c0611e32565b613293565b6001600160681b03908181116132d9571690565b604051630dc7925560e11b8152600490fd5b6001600160681b03166001600160671b03811161330857600c0b90565b604051639369ae3560e01b8152600490fd5b600c91820b910b6000821280156001600160671b0319840183121661334f575b6001600160671b038301821316611e5f570390565b613357611e32565b61333a565b91909180600c0b83600c0b8181126133cb5760001261338f5750613380919261331a565b6001600160681b031690600090565b6000136133b2576133a0919261331a565b6000916001600160681b039190911690565b6133bb90612989565b6001600160681b03908116921690565b5050509050600090600090565b6040516370a0823160e01b8082529390926020926001600160a01b03169190838580613407306004830161060e565b0381865afa948515613545575b600095613526575b50823b15610582576040516323b872dd60e01b81526001600160a01b03919091166004820152306024820152604481019190915260008160648183865af18015613519575b613504575b503d80156134fb5760201461347a57600080fd5b816000803e6000515b156134e9578161097994604051928391825281806134a4306004830161060e565b03915afa9182156134dc575b6000926134bf575b505061219b565b6134d59250803d106125dd576125ce8183611b46565b38806134b8565b6134e4611bfe565b6134b0565b60405163073d1efd60e51b8152600490fd5b50600019613483565b80611485600061351393611b46565b38613466565b613521611bfe565b613461565b61353e919550843d86116125dd576125ce8183611b46565b933861341c565b61354d611bfe565b613414565b90604051613561604082611b46565b91546001600160801b038116835260801c6020830152565b6001600160801b0391821691908116908290038111611eb3570190565b80546001600160801b0319166001600160801b03909216919091179055565b90602060018060801b03916135cd8382511685613596565b0151825490911660809190911b6001600160801b031916179055565b6001600160801b03909116815260200190565b91909261361b61361660018060801b0380931685856133d8565b612faf565b9161362581611d3a565b9061363961363482600261097c565b613552565b9261365d6136508661364b8751610993565b613579565b6001600160801b03168552565b6136678451610993565b906136786119af60e0860151610993565b911611613722576136fd6136eb8561371d946136f77ffa56f7b24f17183d81894d3ac2ee654e3c26388d17a28dbd9549b8114304e1f4976136f2876136cc8e6136d86136d1612916856136cc85600661097c565b61097c565b9889613579565b9889956136e685600261097c565b6135b5565b600661097c565b613596565b89613734565b6040516001600160a01b03918216968216959091169390918291826135e9565b0390a4565b604051637ac7b99d60e11b8152600490fd5b909290916001600160801b03908116158080613895575b156137f15750505061375e825160ff1690565b60ff811660108110156137b0575050613798613790613781610c31945160ff1690565b600160ff9091161b61ffff1690565b91600561097c565b906137a9825461ffff9060e81c1690565b1790612d1b565b6018919350106137be575050565b6137de6137906137d26010610c3195612cae565b600160ff9182161b1690565b906137ea825460f81c90565b1790612b4b565b15918261388a575b5050613803575050565b815160ff1680601081101561384b57505061383361379061382b613781610c31955160ff1690565b1961ffff1690565b90613844825461ffff9060e81c1690565b1690612d1b565b601891935010613859575050565b6138776137906138706137d26010610c3196612cae565b1960ff1690565b90613883825460f81c90565b1690612b4b565b1615905038806137f9565b50818316151561374b565b93929093600260015460f81c16611a4757612f406138be9186611b09565b610e62576001600160a01b038481168382161461393657807f000000000000000000000000000000000000000000000000000000000000000016908216146000146139225750610c3192600019830361394857915061391c8261474c565b91613948565b90613930610c319493612faf565b92613be1565b60405163e397a99b60e01b8152600490fd5b919091613953611ece565b61395e81600561097c565b61396790611de7565b61397284600561097c565b61397b90611de7565b92815161398890600c0b90565b93805161399590600c0b90565b9261399f866129c0565b6139a884612791565b6139b1916125f1565b926139bb856129c0565b906139c590612791565b6139ce91612628565b906139d8846131c6565b6139e281936131c6565b9788936139ee91613b7c565b986139f9919761335c565b98878a600154613a0890611e6b565b90613a1291613005565b90613a1c91613041565b613a27906001613022565b600154613a3390611ebf565b90613a3d91613005565b90613a4791613041565b613a52906001613059565b613a5c9187612db5565b613a669187612db5565b60008112613b13575b506001600160681b0391818316613acb575b50508116613a8d575050565b6000805160206148328339815191526131c1613aaf6000936131ac8554610b8f565b6040519081526001600160a01b03909416939081906020820190565b600080516020614832833981519152613b09613aed6000946131ac8654610b8f565b6040519081526001600160a01b03909316929081906020820190565b0390a33880613a81565b613b1c906129af565b7f000000000000000000000000000000000000000000000000000000000000000011613b6a57613b4e612f40836127b4565b613b585738613a6f565b604051630a62fbdb60e11b8152600490fd5b604051637139da2360e11b8152600490fd5b919082600c0b81600c0b8181136133cb57600013613b9f5750613380919261331a565b600012613bb0576133a0919261331a565b613bb990612989565b6001600160681b03928316921690565b6001600160801b039182169116818110611e5f570390565b6001600160a01b0380821660008181526006602052604090206001600160801b03959194919391908690613c1690869061097c565b54168382169687600052600660205285604060002090613c359161097c565b5416613c418983613bc9565b613c4b8a83613579565b928188613c5988600661097c565b90613c639161097c565b90613c6d91613596565b8388613c7a87600661097c565b90613c849161097c565b90613c8e91613596565b613c9788611d3a565b91613ca3918388613734565b613cac93613734565b613cb5906127b4565b15613b58577f29db89d45e1a802b4d55e202984fce9faf1d30aedf86503ff1ea0ed9ebb642019161371d6040519283921696826135e9565b93929093600460015460f81c16611a4757612f40613d0b9186611b09565b610e62576001600160a01b038181167f000000000000000000000000000000000000000000000000000000000000000090911603613d625750610c31926000198303613d76579150613d5c8261474c565b91613d76565b90613d70610c319493612faf565b92613f99565b909161312f92613d84611ece565b613d926130ca84600561097c565b613dec613da08251600c0b90565b613db5613dac826129c0565b61274087612791565b92613136613dcc613dc5866131c6565b8094613b7c565b613de16131188361312a60019e959e54611e6b565b613113600154611ebf565b60008112613e91575b50613e2182827f0000000000000000000000000000000000000000000000000000000000000000613ef1565b6040519182526001600160a01b0392831692169082907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90602090a36001600160681b038216613e6f575050565b6000805160206148328339815191526131c16131b16000946131ac8654610b8f565b613e9a906129af565b7f000000000000000000000000000000000000000000000000000000000000000011613b6a57613ecc612f40846127b4565b613b585738613df5565b6001600160a01b039091168152602081019190915260400190565b6001600160a01b03169291833b1561058257613f2b90604051809581809563a9059cbb60e01b825260009889968796879360048401613ed6565b03925af18015613f8c575b613f7c575b503d90508015613f7157602014613f50575080fd5b90602081803e515b15613f5f57565b60405163cefaffeb60e01b8152600490fd5b509050600019613f58565b613f8591611b46565b3882613f3b565b613f94611bfe565b613f36565b6001600160a01b038082166000818152600660205260408120909695919491936001600160801b03918290613fcf90879061097c565b5416613fdb8882613bc9565b80878781169b8c81526002602052604081208c8882541690613ffc91613bc9565b61400591613596565b8a81526006602052604090209061401b9161097c565b9061402591613596565b61402e87611d3a565b916140399284613734565b614042906127b4565b15613b58577fd6d480d5b3068db003533b170d67561494d72e3bf9fa40a266471351ebba9e16938261407692881691613ef1565b61371d6040519283921695826135e9565b91908110156140975760051b0190565b634e487b7160e01b600052603260045260246000fd5b3561097981610571565b906040516140c6608082611b46565b915463ffffffff81168352602081811c6001600160401b031690840152606081811c6001600160801b0316604085015260e09190911c90830152565b60019063ffffffff809116908114611eb3570190565b9291909260016008815460f81c16611a47575a94614134611ece565b60005b84811061422e575050506141d9906141d26141b361361661415d610c3197985a9061219b565b6141ac61419a61417661417188600761097c565b6140b7565b9861202561419061418b8c5163ffffffff1690565b614102565b63ffffffff168b52565b612e8e60208a01916120348351610b8f565b4890611e77565b6141c5604086019161364b8351610993565b6001600160801b03169052565b600761097c565b815160208084015160408501516060958601516001600160e01b031960e09190911b16600160601b600160e01b039190961b1663ffffffff909316600160201b600160601b039190921b161717919091179055565b8061424c61424661424186948987614087565b6140ad565b86614252565b01614137565b9061425f612f4082612a35565b6145e7576142716130ca82600561097c565b9061427d8251600c0b90565b90614287826129c0565b91614297606085015161ffff1690565b906142a6608086015160ff1690565b936142d07f000000000000000000000000000000000000000000000000000000000000000061249f565b92600095865b60ff7f00000000000000000000000000000000000000000000000000000000000000001660ff82161061448f5750505061434e6143486129668561434360018060401b037f000000000000000000000000000000000000000000000000000000000000000016809a611e77565b6123d6565b82612628565b9160008312614486575b614361836131c6565b968761436d9187612db5565b61437885600561097c565b600061438391612d1b565b8661438f86600561097c565b600061439a91612b4b565b6143a39161335c565b6001546143af90611e6b565b906143b991613005565b6143c4906001613022565b6001546143d090611ebf565b906143da91613041565b6143e5906001613059565b6143ee916125f1565b6143f790614622565b926144029184612bba565b6040805193845260208401919091526001600160a01b039182169485939216917f1547a878dc89ad3c367b6338b4be6a65a5dd74fb77ae044da1e8747ef1f4f62f9190a380600c0b600012614455575050565b6000805160206148328339815191526131c16131b160009361448061447a8654610b8f565b916145f9565b90612466565b60009250614358565b61449a828285612cc0565b6144aa575b60010160ff166142d6565b868a6144b583611c0b565b602081015183906001600160a01b03169b8c6006816144d4858361097c565b906144de9161097c565b546001600160801b0316936144f29161097c565b906144fc9161097c565b600061450791613596565b6145128d600261097c565b82815461451e90610993565b9061452891613bc9565b61453191613596565b60408301516001600160a01b03166145489061249f565b606084015161455690610b8f565b614569916001600160801b038516612bba565b9260c0015161457790610b8f565b61458090610b8f565b61458a9084612b7c565b6145939161218f565b604080516001600160801b0393909316835260208301939093529b6001600160a01b039081169481169316917f9850ab1af75177e4a9201c65a2cf7976d5d28e40ef63494b44366f86b2f9412e91a461449f565b604051636ef5bcdd60e11b8152600490fd5b600081600c0b12614610576001600160681b031690565b60405163363b64b760e11b8152600490fd5b600081126146105790565b906146f561463d61097993611d3a565b6146c060606146eb61465a60018060a01b0360408601511661249f565b60c08501516001600160401b0394670de0b6b3a764000092909183906146af908890811680841061473f575b8303167f0000000000000000000000000000000000000000000000000000000000000000611e77565b04808410614732575b830390611e77565b0495612f197f000000000000000000000000000000000000000000000000000000000000000061249f565b9201511690611e77565b908015614725575b7f000000000000000000000000000000000000000000000000000000000000000091046123d6565b61472d6123bf565b6146fd565b61473a611e32565b6146b8565b614747611e32565b614686565b61476f614757611dbe565b6106ab64ffffffffff918260015460d01c1690611e49565b506001600160a01b03909116600090815260056020526040812054600c0b9190808313156147a45750614480610979926145f9565b91505090565b6147b5614757611dbe565b6001600160a01b03909216600090815260056020526040812054600c0b929150808312156147a457506144806147ed61097993612989565b6145f9565b50600036818037808036817f00000000000000000000000000000000000000000000000000000000000000005af43d82803e1561482d573d90f35b3d90fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc98c7730ba19013824f711a9ab74801459b27e6ff7685cb924587c89aeda53aca2646970667358221220dd4d8e5db53112439967db2c464c1ea494a86bff16c12971539081501f5c364364736f6c634300080f00330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a020000000000000000000000003cb4653f3b45f448d9100b118b75a1503281d2ee000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc0000000000000000000000002330aae3bca5f05169d5f4597964d44522f629300000000000000000000000003c30b5a5a04656565686f800481580ac4e7ed1780000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000bfd8b6c1df00000000000000000000000000000000000000000000000000002a1aeeecd889000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000002f2f39fc6c54000000000000000000000000000000000000000000000000000000354a6ba7a180000000000000000000000000000000000000000000000000000853a0d2313c000000000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000108b2a2c2802909400000000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005875eee11cf8398102fdad704c9e96607675467a000000000000000000000000c3a73a70d1577cd5b02da0ba91c0afc8fa434daf00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000ce80612991d00000000000000000000000000000000000000000000000000000d2f13f7789f00000000000000000000000000000000000000000000000000000d529ae9e86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cbb7c0000ab88b473b1f5afd9ef808440eed33bf00000000000000000000000007da0e54543a844a80abe69c8a12f22b3aa59f9d00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000d2f13f7789f00000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361015610018575b6100166147f2565b005b60003560e01c8063042e02cf146105685780630902f1ac1461055f5780630bc47ad1146105565780630c340a241461054d57806318160ddd14610544578063189bb2f11461053b5780631c9f7fb9146105325780631f5954bd1461052957806323b872dd1461052057806324a3d62214610517578063264413181461050e5780632a48cf12146105055780632b92a07d146104fc5780632d05670b146104f35780632e04b8e7146104ea578063300e6beb146104e1578063313ce567146104d857806332176c49146104cf578063374c49b4146104c657806338aa813f146104bd5780633b3bec2e146104b457806341976e09146104ab5780634232cd63146104a2578063439e2e451461049957806344c1e5eb1461049057806344c35d071461048757806344ff241d1461047e57806359e017bd146104755780635a94b8d11461046c57806367800b5f1461046357806370a082311461045a5780637914acc7146104515780637ac88ed1146104485780637eb711311461043f578063804de71f146104365780638285ef401461042d5780638d5d814c14610424578063903231771461041b5780639241a561146104125780639364e18a1461040957806394920cca146104005780639ea99a5a146103f75780639fa83b5a146103ee5780639ff567f8146103e5578063a1654379146103dc578063a1a1ef43146103d3578063a46fe83b146103ca578063a5b4ff79146103c1578063a9059cbb146103b8578063aba7f15e146103af578063ad14777c146103a6578063bfe69c8d1461039d578063c1ee2c1814610394578063c3b35a7e1461038b578063c3cecfd214610382578063c55dae6314610379578063c5fa15cf14610370578063c8c7fe6b14610367578063cde680411461035e578063d8e5f61114610355578063d955759d1461034c578063dc4abafd14610343578063e372f03a1461033a578063e478795d14610331578063e4e6e77914610328578063e7dad6bd1461031f578063f2b9fdb8146103165763f3fef3a30361000e57610311611ad4565b61000e565b50610311611a9f565b50610311611a59565b506103116118d0565b506103116117e5565b5061031161179f565b5061031161172c565b5061031161170d565b506103116116e6565b506103116116ca565b506103116116a1565b50610311611628565b506103116115e2565b5061031161157d565b50610311611559565b50610311611533565b50610311611498565b506103116113f3565b506103116113b7565b50610311611361565b50610311611325565b506103116112e6565b506103116112bf565b5061031161127e565b50610311611256565b50610311611225565b506103116111e9565b506103116111ad565b50610311611171565b50610311611135565b5061031161110f565b506103116110e8565b50610311611087565b5061031161104b565b5061031161102f565b50610311611003565b50610311610fc7565b50610311610f9f565b50610311610f78565b50610311610f3c565b50610311610ee6565b50610311610ea0565b50610311610d21565b50610311610cd8565b50610311610cb4565b50610311610c90565b50610311610c68565b50610311610c33565b50610311610b67565b50610311610b3f565b50610311610b03565b50610311610ac4565b50610311610a88565b50610311610a4a565b50610311610a0e565b506103116109b9565b50610311610918565b506103116108de565b50610311610861565b506103116107fe565b50610311610795565b5061031161070f565b506103116106d3565b50610311610667565b50610311610621565b506103116105e8565b506103116105c4565b50610311610587565b6001600160a01b0381160361058257565b600080fd5b50346105825760203660031901126105825760206105af6004356105aa81610571565b612a35565b6040519015158152f35b600091031261058257565b50346105825760003660031901126105825760206105e0612661565b604051908152f35b50346105825760003660031901126105825760206001805460f81c161515604051908152f35b6001600160a01b03909116815260200190565b5034610582576000366003190112610582576040517f000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a026001600160a01b03168152602090f35b503461058257600036600319011261058257602066038d7ea4c680006106ca61068e611dbe565b6106b1600154916106ab64ffffffffff91828560d01c1690611e49565b166120fd565b506001600160401b0316906001600160681b0316611e77565b04604051908152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b5034610582576000806003193601126107925760015464ffffffffff8160d01c166107815764ffffffffff60d01b610745611dbe565b64ffffffffff60d01b1990921660d09290921b161760015580546001600160801b0319166e038d7ea4c6800000038d7ea4c68000178155604051f35b60405162dc149f60e41b8152600490fd5b80fd5b50346105825760003660031901126105825760206040517f0000000000000000000000000000000000000000000000000853a0d2313c00008152f35b908160609103126105825780356107e781610571565b91604060208301356107f881610571565b92013590565b5034610582576108446108123660046107d1565b919061081c612fd5565b7f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc91336138a0565b600060008051602061485283398151915255602060405160018152f35b5034610582576000366003190112610582576040517f0000000000000000000000003cb4653f3b45f448d9100b118b75a1503281d2ee6001600160a01b03168152602090f35b91908260809103126105825781356108be81610571565b9160208101356108cd81610571565b91606060408301356107f881610571565b5034610582576109046108f23660046108a7565b926108fe929192612fd5565b33613ced565b600060008051602061485283398151915255005b50346105825760003660031901126105825760206040517f000000000000000000000000000000000000000000000000000000191a2c4ac88152f35b9190826040910312610582576020823561096d81610571565b92013561097981610571565b90565b9060018060a01b0316600052602052604060002090565b6001600160801b031690565b6001600160801b0391821681529116602082015260400190565b503461058257610a0a6109ee6109d0366004610954565b6001600160a01b03909116600090815260066020526040902061097c565b54604051918291608081901c906001600160801b03168361099f565b0390f35b50346105825760003660031901126105825760206040517f000000000000000000000000000000000000000000000000000000005e80a6bf8152f35b503461058257602036600319011261058257600435610a6881610571565b60018060a01b031660005260046020526020604060002054604051908152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000018152f35b503461058257600036600319011261058257602060405160ff7f0000000000000000000000000000000000000000000000000000000000000012168152f35b50346105825760003660031901126105825760206040517f000000000000000000000000000000000000000000108b2a2c280290940000008152f35b50346105825760203660031901126105825760206105e0600435610b6281610571565b6147aa565b50346105825760203660031901126105825760206105af600435610b8a81610571565b6127b4565b6001600160401b031690565b610c319092919260e08061010083019560ff815116845260018060a01b03806020830151166020860152604082015116604085015260018060401b036060820151166060850152610bfb6080820151608086019060018060401b03169052565b60a0818101516001600160401b03169085015260c0818101516001600160401b03169085015201516001600160801b0316910152565b565b503461058257602036600319011261058257610a0a610c5c600435610c5781610571565b611d3a565b60405191829182610b9b565b50346105825760203660031901126105825760206105e0600435610c8b81610571565b61249f565b503461058257610904610ca43660046107d1565b91610cad612fd5565b3333612f23565b503461058257610904610cc83660046107d1565b91610cd1612fd5565b33336138a0565b50346105825760003660031901126105825760206040517f0000000000000000000000000000000000000000000000000de0b6b3a76400008152f35b3590811515820361058257565b50346105825760a036600319011261058257610d3d6004610d14565b610d476024610d14565b610d516044610d14565b91610d5c6064610d14565b92610d676084610d14565b60018060a01b03807f000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a02163314159081610e73575b50610e62577f3be39979091ae7ca962aa1c44e645f2df3c221b79f324afa5f44aedc8d2f690d94610e5d92610e28610de56000610dd788612b6e565b9060ff8080931691161b1690565b610df36001610dd78a612b6e565b17610e026002610dd785612b6e565b17610e116003610dd786612b6e565b17610e206004610dd787612b6e565b176001612b4b565b6040519586958693909594919260809360a0860197151586521515602086015215156040850152151560608401521515910152565b0390a1005b6040516282b42960e81b8152600490fd5b90507f0000000000000000000000003cb4653f3b45f448d9100b118b75a1503281d2ee1633141538610d9b565b5034610582576000366003190112610582576040517f0000000000000000000000003c30b5a5a04656565686f800481580ac4e7ed1786001600160a01b03168152602090f35b503461058257602036600319011261058257600435610f0481610571565b6001600160a01b031660009081526002602052604090819020549051908190610a0a90608081901c906001600160801b03168361099f565b50346105825760003660031901126105825760206040517f000000000000000000000000000000000000000000000000000000006610103f8152f35b5034610582576000366003190112610582576020600460015460f81c161515604051908152f35b50346105825760203660031901126105825760206105e0600435610fc281610571565b61474c565b50346105825760003660031901126105825760206040517f000000000000000000000000000000000000000000000000000000001c59cb9f8152f35b50346105825760403660031901126105825760206105e060043561102681610571565b6024359061462d565b50346105825760003660031901126105825760206105e06123ec565b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000016666a158e8152f35b503461058257600036600319011261058257602066038d7ea4c680006106ca6110ae611dbe565b6110cb600154916106ab64ffffffffff91828560d01c1690611e49565b6001600160401b03169160681c6001600160681b03169050611e77565b5034610582576000366003190112610582576020600860015460f81c161515604051908152f35b5034610582576109046111233660046108a7565b9261112f929192612fd5565b33612f23565b50346105825760003660031901126105825760206040517f0000000000000000000000000000000000000000000000000c7d713b49da00008152f35b50346105825760003660031901126105825760206040517f000000000000000000000000000000000000000000000000000000003b9aca008152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346105825760203660031901126105825760206112446004356122b6565b6040516001600160401b039091168152f35b50346105825760203660031901126105825760206105e060043561127981610571565b612559565b503461058257602060ff6112b3611296366004610954565b6001600160a01b039091166000908152600385526040902061097c565b54166040519015158152f35b5034610582576000366003190112610582576020600260015460f81c161515604051908152f35b503461058257600036600319011261058257602060405160ff7f0000000000000000000000000000000000000000000000000000000000000002168152f35b50346105825760003660031901126105825760206040517f0000000000000000000000000000000000000000000000000c7d713b49da00008152f35b50346105825760403660031901126105825761084460043561138281610571565b61138a612fd5565b602435907f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc9033336138a0565b50346105825760003660031901126105825760206040517f00000000000000000000000000000000000000000000000000038d7ea4c680008152f35b5034610582576114043660046107d1565b91906001600160a01b03907f000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a0282163303610e62571691823b1561058257611465926000928360405180968195829463095ea7b360e01b845260048401613ed6565b03925af1801561148b575b61147657005b80611485600061001693611b46565b806105b9565b611493611bfe565b611470565b5034610582576020366003190112610582576100166004356114b981610571565b6114c1611ece565b60018060a01b03811660005260056020526040600020611528604051916114e960a084611b46565b54600c81900b83526001600160401b03606882901c8116602085015260a882901c16604084015261ffff60e882901c16606084015260f81c6080830152565b8051600c0b91612db5565b5034610582576109046115473660046108a7565b92611553929192612fd5565b336138a0565b50346105825761090461156d3660046107d1565b91611576612fd5565b3333613ced565b50346105825760403660031901126105825760043561159b81610571565b602435906001600160401b03908183116105825736602384011215610582578260040135918211610582573660248360051b85010111610582576024610016930190614118565b5034610582576000366003190112610582576040517f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc6001600160a01b03168152602090f35b50346105825760203660031901126105825760043561164681610571565b60018060a01b0316600052600760205260806040600020546040519063ffffffff8116825260018060401b038160201c166020830152600180841b038160601c16604083015260e01c6060820152f35b60ff81160361058257565b503461058257602036600319011261058257610a0a610c5c6004356116c581611696565b611c0b565b50346105825760206105af6116e0366004610954565b90611b09565b5034610582576000366003190112610582576020601060015460f81c161515604051908152f35b50346105825760203660031901126105825760206112446004356121a6565b50346105825760203660031901126105825760043561174a81610571565b60018060a01b0316600052600560205260a06040600020546040519080600c0b825260018060401b03808260681c1660208401528160a81c16604083015261ffff8160e81c16606083015260f81c6080820152f35b5034610582576000366003190112610582576040517f0000000000000000000000003f4061d0a3093745f05b9eed8d91031670843f5a6001600160a01b03168152602090f35b50346105825760403660031901126105825760043561180381610571565b602435906001600160a01b037f000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a0281163303610e6257611840612661565b600081129081156118be575b506118ac578161189e847fec4431f2ba1a9382f6b0c4352b888cba6f7db91667d9f776abe5ad8ddc5401b6947f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc613ef1565b6040519384521691602090a2005b60405163128bd24d60e31b8152600490fd5b6118c89150614622565b83113861184c565b5034610582576080366003190112610582576004356118ee81610571565b606435906118fb82610571565b611903612fd5565b601060015460f81c16611a4757611918612661565b60008112159081611a1c575b50611a0a57611956604435337f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc6133d8565b90611961828261462d565b9260243584106119f85761197482612559565b84116118ac577ff891b2a411b0e66a5f0a6ff1368670fefa287a13f541eb633a386a1a9cc7046b916119bb6119de926119b46119af88612faf565b610993565b9083613ef1565b6040805194855260208501959095526001600160a01b0316933393918291820190565b0390a3610016600060008051602061485283398151915255565b60405163fa6ad35560e01b8152600490fd5b604051631d99ddbf60e01b8152600490fd5b90507f000000000000000000000000000000000000000000108b2a2c28029094000000111538611924565b6040516313d0ff5960e31b8152600490fd5b5034610582576000366003190112610582576040517f0000000000000000000000002330aae3bca5f05169d5f4597964d44522f629306001600160a01b03168152602090f35b503461058257604036600319011261058257610904600435611ac081610571565b611ac8612fd5565b60243590333333612f23565b503461058257604036600319011261058257610904600435611af581610571565b611afd612fd5565b60243590333333613ced565b6001600160a01b03808316911690811491908215611b2657505090565b60ff925090611b41916000526003602052604060002061097c565b541690565b601f909101601f19168101906001600160401b03821190821017611b6957604052565b634e487b7160e01b600052604160045260246000fd5b60405190611b8f61010083611b46565b8160e06000918281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b5190610c3182611696565b5190610c3182610571565b51906001600160401b038216820361058257565b51906001600160801b038216820361058257565b506040513d6000823e3d90fd5b611c13611b7f565b5060405163c8c7fe6b60e01b815260ff91909116600482015261010080826024817f0000000000000000000000003f4061d0a3093745f05b9eed8d91031670843f5a6001600160a01b03165afa918215611d2d575b600092611c7457505090565b90918282813d8311611d26575b611c8b8183611b46565b81010312610792575060e0611d1e91611ca76040519485611b46565b611cb081611bc0565b8452611cbe60208201611bcb565b6020850152611ccf60408201611bcb565b6040850152611ce060608201611bd6565b6060850152611cf160808201611bd6565b6080850152611d0260a08201611bd6565b60a0850152611d1360c08201611bd6565b60c085015201611bea565b60e082015290565b503d611c81565b611d35611bfe565b611c68565b90611d43611b7f565b5060009060ff92837f000000000000000000000000000000000000000000000000000000000000000216925b8385821610611d8a57604051633640530560e01b8152600490fd5b611d9381611c0b565b60208101516001600160a01b03848116911614611db557506001018416611d6f565b93505050915090565b600160281b421015611dd55764ffffffffff421690565b604051633d32ffdb60e01b8152600490fd5b90604051611df660a082611b46565b608081935480600c0b835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c910152565b50634e487b7160e01b600052601160045260246000fd5b64ffffffffff9182169116818110611e5f570390565b611e67611e32565b0390565b6001600160681b031690565b8060001904821181151516611e8a570290565b611e92611e32565b0290565b6001600160401b0391821691908116908290038111611eb3570190565b611ebb611e32565b0190565b60681c6001600160681b031690565b611ed6611dbe565b611f00611ef6611ef060015464ffffffffff9060d01c1690565b83611e49565b64ffffffffff1690565b9081611f0a575050565b81611f61611f1a610c31946120fd565b60008054600160401b600160801b03191660409290921b600160401b600160801b0316919091178155919082546001600160401b0319166001600160401b03909116178255565b611f6c600154611e6b565b7f000000000000000000000000000000000000000000000000000000003b9aca0092906001600160681b031683811015612061575b50611fb5611fb0600154611ebf565b611e6b565b92831015611fe9575b50506001805464ffffffffff60d01b191660d09390931b64ffffffffff60d01b169290921790915550565b61202a61202561205994612020612039947f0000000000000000000000000000000000000000000000000000000000000000611e77565b612b8f565b6120d7565b825460c01c611e96565b611e96565b81546001600160c01b031660c09190911b6001600160c01b031916179055565b388080611fbe565b6120ab6120986120256120d193612020867f0000000000000000000000000000000000000000000000000000000000000000611e77565b845460801c6001600160401b0316611e96565b8354600160801b600160c01b03191660809190911b600160801b600160c01b0316178355565b38611fa1565b6001600160401b03908181116120eb571690565b6040516372a1cb5160e11b8152600490fd5b6000546001600160401b03604082901c81169392918116919081612122575b50509190565b8161217561216f61214f97946121816121879761217b8761215661217b996121486123ec565b9e8f6121a6565b169d6122b6565b169b61217561216f670de0b6b3a7640000998a93611e77565b84611e77565b046120d7565b90611e96565b98611e77565b91388061211c565b81198111611eb3570190565b818110611e5f570390565b7f0000000000000000000000000000000000000000000000000c7d713b49da000080821161222f5750612025670de0b6b3a7640000612208610979937f000000000000000000000000000000000000000000000000000000006610103f611e77565b047f000000000000000000000000000000000000000000000000000000000000000061218f565b61097991612025916122a2670de0b6b3a76400009161227283612208837f000000000000000000000000000000000000000000000000000000006610103f611e77565b938181106122a9575b037f00000000000000000000000000000000000000000000000000000016666a158e611e77565b049061218f565b6122b1611e32565b61227b565b7f0000000000000000000000000000000000000000000000000c7d713b49da000080821161233f5750612025670de0b6b3a7640000612318610979937f000000000000000000000000000000000000000000000000000000005e80a6bf611e77565b047f000000000000000000000000000000000000000000000000000000001c59cb9f61218f565b61097991612025916122a2670de0b6b3a76400009161238283612318837f000000000000000000000000000000000000000000000000000000005e80a6bf611e77565b938181106123b2575b037f000000000000000000000000000000000000000000000000000000191a2c4ac8611e77565b6123ba611e32565b61238b565b50634e487b7160e01b600052601260045260246000fd5b81156123e0570490565b6123e86123bf565b0490565b60005460015466038d7ea4c680009061242e906001600160681b036001600160401b038461241e828816848616611e77565b049560401c169160681c16611e77565b048161243b575050600090565b670de0b6b3a764000090806000190482118115151661245957020490565b612461611e32565b020490565b66038d7ea4c68000916123e8916001600160401b0316906001600160681b0316611e77565b51906001600160501b038216820361058257565b604051633fabe5a360e21b81529060a090829060049082906001600160a01b03165afa90811561253d575b6000916124f1575b5060008113156124df5790565b60405163fd1ee34960e01b8152600490fd5b9060a0823d8211612535575b8161250a60a09383611b46565b81010312610792575061251c8161248b565b5061252e60806020830151920161248b565b50386124d2565b3d91506124fd565b612545611bfe565b6124ca565b90816020910312610582575190565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa9182156125e4575b6000926125b4575b506000908152600260205260409020546001600160801b031690818110611e5f570390565b6125d691925060203d81116125dd575b6125ce8183611b46565b81019061254a565b903861258f565b503d6125c4565b6125ec611bfe565b612587565b600082128015600160ff1b840183121661261b575b6001600160ff1b038301821316611e5f570390565b612623611e32565b612606565b6000811280156001600160ff1b03839003841316612654575b600160ff1b829003831216611eb3570190565b61265c611e32565b612641565b61097961266c611dbe565b61268f61268a611ef66001549364ffffffffff8560d01c1690611e49565b6120fd565b90604051926370a0823160e01b8452602084806126af306004830161060e565b03817f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc6001600160a01b03165afa938415612784575b60009461274c575b509161274061273a61273a936127336127469666038d7ea4c680009260018060401b03846127268260018060681b039416848616611e77565b0497169160681c16611e77565b0495612791565b91612791565b906125f1565b90612628565b6127469391945061273a61273a936127336127776127409460203d81116125dd576125ce8183611b46565b97949650509350506126ed565b61278c611bfe565b6126e5565b6001600160ff1b0381116127a25790565b60405163e7e828ad60e01b8152600490fd5b6127c96127c282600561097c565b54600c0b90565b906000918281600c0b1215612981576127f16127e683600561097c565b5460e81c61ffff1690565b9061286c61281361280d61280686600561097c565b5460f81c90565b926129c0565b61283c7f0000000000000000000000002330aae3bca5f05169d5f4597964d44522f6293061249f565b7f0000000000000000000000000000000000000000000000000de0b6b3a76400006001600160401b031691612bda565b92849160ff93847f000000000000000000000000000000000000000000000000000000000000000216935b84868216106128ab57505050505050121590565b6128b6838284612cc0565b6128c5575b6001018516612897565b958781121561297457600161296b87926127466129668861296061295b60808f6129236129166129026128fa61295394611c0b565b97600661097c565b60208801516001600160a01b03169061097c565b546001600160801b031690565b604086015161293a906001600160a01b031661249f565b6129476060880151610b8f565b918c80861b0316612bba565b930151610b8f565b610b8f565b90612b7c565b612791565b979150506128bb565b5050505050505050600190565b505050600190565b600c0b6001600160671b031981146129a2575b60000390565b6129aa611e32565b61299c565b600160ff1b81146129a25760000390565b6000600c82900b12612a00576000546109799166038d7ea4c68000916129fa916001600160401b03909116906001600160681b0316611e77565b04612791565b612a3061296661097992612a2160018060401b0360005460401c1691612989565b6001600160681b031690612466565b6129af565b612a436127c282600561097c565b906000918281600c0b1215612b4657612a606127e683600561097c565b90612a7561281361280d61280686600561097c565b92849160ff93847f000000000000000000000000000000000000000000000000000000000000000216935b8486821610612ab3575050505050501290565b612abe838284612cc0565b612acd575b6001018516612aa0565b9587811215612b3c576001612b3387926127466129668861296061295b60a08f612b026129166129026128fa61295394611c0b565b6040860151612b19906001600160a01b031661249f565b612b266060880151610b8f565b918c8060801b0316612bba565b97915050612ac3565b5050505050505090565b505090565b80546001600160f81b031660f89290921b6001600160f81b031916919091179055565b600090156109795750600190565b670de0b6b3a7640000916123e891611e77565b6123d6907f0000000000000000000000000000000000000000000000000de0b6b3a764000090611e77565b90612bc491611e77565b6001600160401b039091169081156123e0570490565b9190612be590612791565b6000808413939082136001600160ff1b03858216848204841116612ca1575b600160ff1b95600085129185918316858905831216612c94575b60008512938416828905861216612c87575b058312911616612c7a575b6001600160401b03909216929102908215612c6d575b8114600019831416612c61570590565b612c69611e32565b0590565b612c756123bf565b612c51565b612c82611e32565b612c3b565b612c8f611e32565b612c30565b612c9c611e32565b612c1e565b612ca9611e32565b612c04565b60ff9182169116818110611e5f570390565b9060ff169160108310600014612cdf5750600161ffff921b1616151590565b905060188210612cf0575050600090565b600160ff8093600f1901161b1616151590565b6001600160401b039182169116818110611e5f570390565b805461ffff60e81b191660e89290921b61ffff60e81b16919091179055565b81518154602084015160408501516001600160e81b03199092166001600160681b039093169290921760689290921b600160681b600160a81b03169190911760a89190911b600160a81b600160e81b03161781556060820151610c319260ff9160809190612dac9061ffff1685612d1b565b01511690612b4b565b612ecc90610c3193612dc88451600c0b90565b600c82900b855260009182918683600c83900b8113612ee357612e55612e2e612e9b94612e1f61295b612e7c96612e196020612e11612025995460018060401b039060801c1690565b920151610b8f565b90612d03565b906001600160681b0316611e77565b7f00000000000000000000000000000000000000000000000000038d7ea4c68000906123d6565b7f000000000000000000000000000000000000000000000000000000e8d4a51000906123d6565b612e8e60408901916120348351610b8f565b6001600160401b03169052565b600c0b12612ed15754612ec59060801c6001600160401b03165b6001600160401b03166020850152565b600561097c565b612d3a565b54612ede9060c01c612eb5565b612ec5565b612e55612e2e612f1e94612f19611fb0611e6b612f1361295b612e7c99612e196020612e116120259c5460c01c90565b93612989565b611e77565b612e9b565b939290936001805460f81c16611a4757612f40612f449186611b09565b1590565b610e62576001600160a01b038181167f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc90911603612f9b5750610c31926000198303613082579150612f95816147aa565b91613082565b90612fa9610c319493612faf565b926135fc565b6001600160801b0390818111612fc3571690565b60405163762ea71160e11b8152600490fd5b6000805160206148528339815191526001815414612ff35760019055565b60405163139b643560e21b8152600490fd5b6001600160681b0391821691908116908290038111611eb3570190565b80546001600160681b0319166001600160681b03909216919091179055565b6001600160681b039182169116818110611e5f570390565b8054600160681b600160d01b03191660689290921b600160681b600160d01b0316919091179055565b6130b161312f9293827f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc6133d8565b6130b9611ece565b61313c6130cf6130ca86600561097c565b611de7565b8051600c0b906131366130ff6130f86130f36130ea866129c0565b61274689612791565b6131c6565b809461335c565b979061311f6131188a613113600154611e6b565b613005565b6001613022565b61312a600154611ebf565b613041565b6001613059565b86612db5565b6040519081526001600160a01b0393841693849216907fd1cf3d156d5f8f0d50f6c122ed609cec09d35c9b9fb3fff6ea0959134dae424e90602090a36001600160681b03811661318a575050565b6000805160206148328339815191526131c16131b16000936131ac8554610b8f565b612466565b6040519081529081906020820190565b0390a3565b600081126131ec57600054610979916131e7916001600160401b0316613275565b6132eb565b6132496131e76109799261320d60018060401b0360005460401c16916129af565b613232826000199266038d7ea4c6800090808504821181151516613268575b0261218f565b6001811061325b575b821561324e575b01046132c5565b612989565b6132566123bf565b613242565b613263611e32565b61323b565b613270611e32565b61322c565b906109799166038d7ea4c680009082600019048211831515166132b8575b6001600160401b03169182156132ab575b02046132c5565b6132b36123bf565b6132a4565b6132c0611e32565b613293565b6001600160681b03908181116132d9571690565b604051630dc7925560e11b8152600490fd5b6001600160681b03166001600160671b03811161330857600c0b90565b604051639369ae3560e01b8152600490fd5b600c91820b910b6000821280156001600160671b0319840183121661334f575b6001600160671b038301821316611e5f570390565b613357611e32565b61333a565b91909180600c0b83600c0b8181126133cb5760001261338f5750613380919261331a565b6001600160681b031690600090565b6000136133b2576133a0919261331a565b6000916001600160681b039190911690565b6133bb90612989565b6001600160681b03908116921690565b5050509050600090600090565b6040516370a0823160e01b8082529390926020926001600160a01b03169190838580613407306004830161060e565b0381865afa948515613545575b600095613526575b50823b15610582576040516323b872dd60e01b81526001600160a01b03919091166004820152306024820152604481019190915260008160648183865af18015613519575b613504575b503d80156134fb5760201461347a57600080fd5b816000803e6000515b156134e9578161097994604051928391825281806134a4306004830161060e565b03915afa9182156134dc575b6000926134bf575b505061219b565b6134d59250803d106125dd576125ce8183611b46565b38806134b8565b6134e4611bfe565b6134b0565b60405163073d1efd60e51b8152600490fd5b50600019613483565b80611485600061351393611b46565b38613466565b613521611bfe565b613461565b61353e919550843d86116125dd576125ce8183611b46565b933861341c565b61354d611bfe565b613414565b90604051613561604082611b46565b91546001600160801b038116835260801c6020830152565b6001600160801b0391821691908116908290038111611eb3570190565b80546001600160801b0319166001600160801b03909216919091179055565b90602060018060801b03916135cd8382511685613596565b0151825490911660809190911b6001600160801b031916179055565b6001600160801b03909116815260200190565b91909261361b61361660018060801b0380931685856133d8565b612faf565b9161362581611d3a565b9061363961363482600261097c565b613552565b9261365d6136508661364b8751610993565b613579565b6001600160801b03168552565b6136678451610993565b906136786119af60e0860151610993565b911611613722576136fd6136eb8561371d946136f77ffa56f7b24f17183d81894d3ac2ee654e3c26388d17a28dbd9549b8114304e1f4976136f2876136cc8e6136d86136d1612916856136cc85600661097c565b61097c565b9889613579565b9889956136e685600261097c565b6135b5565b600661097c565b613596565b89613734565b6040516001600160a01b03918216968216959091169390918291826135e9565b0390a4565b604051637ac7b99d60e11b8152600490fd5b909290916001600160801b03908116158080613895575b156137f15750505061375e825160ff1690565b60ff811660108110156137b0575050613798613790613781610c31945160ff1690565b600160ff9091161b61ffff1690565b91600561097c565b906137a9825461ffff9060e81c1690565b1790612d1b565b6018919350106137be575050565b6137de6137906137d26010610c3195612cae565b600160ff9182161b1690565b906137ea825460f81c90565b1790612b4b565b15918261388a575b5050613803575050565b815160ff1680601081101561384b57505061383361379061382b613781610c31955160ff1690565b1961ffff1690565b90613844825461ffff9060e81c1690565b1690612d1b565b601891935010613859575050565b6138776137906138706137d26010610c3196612cae565b1960ff1690565b90613883825460f81c90565b1690612b4b565b1615905038806137f9565b50818316151561374b565b93929093600260015460f81c16611a4757612f406138be9186611b09565b610e62576001600160a01b038481168382161461393657807f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc16908216146000146139225750610c3192600019830361394857915061391c8261474c565b91613948565b90613930610c319493612faf565b92613be1565b60405163e397a99b60e01b8152600490fd5b919091613953611ece565b61395e81600561097c565b61396790611de7565b61397284600561097c565b61397b90611de7565b92815161398890600c0b90565b93805161399590600c0b90565b9261399f866129c0565b6139a884612791565b6139b1916125f1565b926139bb856129c0565b906139c590612791565b6139ce91612628565b906139d8846131c6565b6139e281936131c6565b9788936139ee91613b7c565b986139f9919761335c565b98878a600154613a0890611e6b565b90613a1291613005565b90613a1c91613041565b613a27906001613022565b600154613a3390611ebf565b90613a3d91613005565b90613a4791613041565b613a52906001613059565b613a5c9187612db5565b613a669187612db5565b60008112613b13575b506001600160681b0391818316613acb575b50508116613a8d575050565b6000805160206148328339815191526131c1613aaf6000936131ac8554610b8f565b6040519081526001600160a01b03909416939081906020820190565b600080516020614832833981519152613b09613aed6000946131ac8654610b8f565b6040519081526001600160a01b03909316929081906020820190565b0390a33880613a81565b613b1c906129af565b7f000000000000000000000000000000000000000000000000000000000000000111613b6a57613b4e612f40836127b4565b613b585738613a6f565b604051630a62fbdb60e11b8152600490fd5b604051637139da2360e11b8152600490fd5b919082600c0b81600c0b8181136133cb57600013613b9f5750613380919261331a565b600012613bb0576133a0919261331a565b613bb990612989565b6001600160681b03928316921690565b6001600160801b039182169116818110611e5f570390565b6001600160a01b0380821660008181526006602052604090206001600160801b03959194919391908690613c1690869061097c565b54168382169687600052600660205285604060002090613c359161097c565b5416613c418983613bc9565b613c4b8a83613579565b928188613c5988600661097c565b90613c639161097c565b90613c6d91613596565b8388613c7a87600661097c565b90613c849161097c565b90613c8e91613596565b613c9788611d3a565b91613ca3918388613734565b613cac93613734565b613cb5906127b4565b15613b58577f29db89d45e1a802b4d55e202984fce9faf1d30aedf86503ff1ea0ed9ebb642019161371d6040519283921696826135e9565b93929093600460015460f81c16611a4757612f40613d0b9186611b09565b610e62576001600160a01b038181167f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc90911603613d625750610c31926000198303613d76579150613d5c8261474c565b91613d76565b90613d70610c319493612faf565b92613f99565b909161312f92613d84611ece565b613d926130ca84600561097c565b613dec613da08251600c0b90565b613db5613dac826129c0565b61274087612791565b92613136613dcc613dc5866131c6565b8094613b7c565b613de16131188361312a60019e959e54611e6b565b613113600154611ebf565b60008112613e91575b50613e2182827f000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc613ef1565b6040519182526001600160a01b0392831692169082907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90602090a36001600160681b038216613e6f575050565b6000805160206148328339815191526131c16131b16000946131ac8654610b8f565b613e9a906129af565b7f000000000000000000000000000000000000000000000000000000000000000111613b6a57613ecc612f40846127b4565b613b585738613df5565b6001600160a01b039091168152602081019190915260400190565b6001600160a01b03169291833b1561058257613f2b90604051809581809563a9059cbb60e01b825260009889968796879360048401613ed6565b03925af18015613f8c575b613f7c575b503d90508015613f7157602014613f50575080fd5b90602081803e515b15613f5f57565b60405163cefaffeb60e01b8152600490fd5b509050600019613f58565b613f8591611b46565b3882613f3b565b613f94611bfe565b613f36565b6001600160a01b038082166000818152600660205260408120909695919491936001600160801b03918290613fcf90879061097c565b5416613fdb8882613bc9565b80878781169b8c81526002602052604081208c8882541690613ffc91613bc9565b61400591613596565b8a81526006602052604090209061401b9161097c565b9061402591613596565b61402e87611d3a565b916140399284613734565b614042906127b4565b15613b58577fd6d480d5b3068db003533b170d67561494d72e3bf9fa40a266471351ebba9e16938261407692881691613ef1565b61371d6040519283921695826135e9565b91908110156140975760051b0190565b634e487b7160e01b600052603260045260246000fd5b3561097981610571565b906040516140c6608082611b46565b915463ffffffff81168352602081811c6001600160401b031690840152606081811c6001600160801b0316604085015260e09190911c90830152565b60019063ffffffff809116908114611eb3570190565b9291909260016008815460f81c16611a47575a94614134611ece565b60005b84811061422e575050506141d9906141d26141b361361661415d610c3197985a9061219b565b6141ac61419a61417661417188600761097c565b6140b7565b9861202561419061418b8c5163ffffffff1690565b614102565b63ffffffff168b52565b612e8e60208a01916120348351610b8f565b4890611e77565b6141c5604086019161364b8351610993565b6001600160801b03169052565b600761097c565b815160208084015160408501516060958601516001600160e01b031960e09190911b16600160601b600160e01b039190961b1663ffffffff909316600160201b600160601b039190921b161717919091179055565b8061424c61424661424186948987614087565b6140ad565b86614252565b01614137565b9061425f612f4082612a35565b6145e7576142716130ca82600561097c565b9061427d8251600c0b90565b90614287826129c0565b91614297606085015161ffff1690565b906142a6608086015160ff1690565b936142d07f0000000000000000000000002330aae3bca5f05169d5f4597964d44522f6293061249f565b92600095865b60ff7f00000000000000000000000000000000000000000000000000000000000000021660ff82161061448f5750505061434e6143486129668561434360018060401b037f0000000000000000000000000000000000000000000000000de0b6b3a764000016809a611e77565b6123d6565b82612628565b9160008312614486575b614361836131c6565b968761436d9187612db5565b61437885600561097c565b600061438391612d1b565b8661438f86600561097c565b600061439a91612b4b565b6143a39161335c565b6001546143af90611e6b565b906143b991613005565b6143c4906001613022565b6001546143d090611ebf565b906143da91613041565b6143e5906001613059565b6143ee916125f1565b6143f790614622565b926144029184612bba565b6040805193845260208401919091526001600160a01b039182169485939216917f1547a878dc89ad3c367b6338b4be6a65a5dd74fb77ae044da1e8747ef1f4f62f9190a380600c0b600012614455575050565b6000805160206148328339815191526131c16131b160009361448061447a8654610b8f565b916145f9565b90612466565b60009250614358565b61449a828285612cc0565b6144aa575b60010160ff166142d6565b868a6144b583611c0b565b602081015183906001600160a01b03169b8c6006816144d4858361097c565b906144de9161097c565b546001600160801b0316936144f29161097c565b906144fc9161097c565b600061450791613596565b6145128d600261097c565b82815461451e90610993565b9061452891613bc9565b61453191613596565b60408301516001600160a01b03166145489061249f565b606084015161455690610b8f565b614569916001600160801b038516612bba565b9260c0015161457790610b8f565b61458090610b8f565b61458a9084612b7c565b6145939161218f565b604080516001600160801b0393909316835260208301939093529b6001600160a01b039081169481169316917f9850ab1af75177e4a9201c65a2cf7976d5d28e40ef63494b44366f86b2f9412e91a461449f565b604051636ef5bcdd60e11b8152600490fd5b600081600c0b12614610576001600160681b031690565b60405163363b64b760e11b8152600490fd5b600081126146105790565b906146f561463d61097993611d3a565b6146c060606146eb61465a60018060a01b0360408601511661249f565b60c08501516001600160401b0394670de0b6b3a764000092909183906146af908890811680841061473f575b8303167f0000000000000000000000000000000000000000000000000853a0d2313c0000611e77565b04808410614732575b830390611e77565b0495612f197f0000000000000000000000002330aae3bca5f05169d5f4597964d44522f6293061249f565b9201511690611e77565b908015614725575b7f0000000000000000000000000000000000000000000000000de0b6b3a764000091046123d6565b61472d6123bf565b6146fd565b61473a611e32565b6146b8565b614747611e32565b614686565b61476f614757611dbe565b6106ab64ffffffffff918260015460d01c1690611e49565b506001600160a01b03909116600090815260056020526040812054600c0b9190808313156147a45750614480610979926145f9565b91505090565b6147b5614757611dbe565b6001600160a01b03909216600090815260056020526040812054600c0b929150808312156147a457506144806147ed61097993612989565b6145f9565b50600036818037808036817f0000000000000000000000003c30b5a5a04656565686f800481580ac4e7ed1785af43d82803e1561482d573d90f35b3d90fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc98c7730ba19013824f711a9ab74801459b27e6ff7685cb924587c89aeda53aca2646970667358221220dd4d8e5db53112439967db2c464c1ea494a86bff16c12971539081501f5c364364736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a020000000000000000000000003cb4653f3b45f448d9100b118b75a1503281d2ee000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc0000000000000000000000002330aae3bca5f05169d5f4597964d44522f629300000000000000000000000003c30b5a5a04656565686f800481580ac4e7ed1780000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000bfd8b6c1df00000000000000000000000000000000000000000000000000002a1aeeecd889000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000002f2f39fc6c54000000000000000000000000000000000000000000000000000000354a6ba7a180000000000000000000000000000000000000000000000000000853a0d2313c000000000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000108b2a2c2802909400000000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000020000000000000000000000005875eee11cf8398102fdad704c9e96607675467a000000000000000000000000c3a73a70d1577cd5b02da0ba91c0afc8fa434daf00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000ce80612991d00000000000000000000000000000000000000000000000000000d2f13f7789f00000000000000000000000000000000000000000000000000000d529ae9e86000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cbb7c0000ab88b473b1f5afd9ef808440eed33bf00000000000000000000000007da0e54543a844a80abe69c8a12f22b3aa59f9d00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000d2f13f7789f00000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : config (tuple):
Arg [1] : governor (address): 0xCC3E7c85Bb0EE4f09380e041fee95a0caeDD4a02
Arg [2] : pauseGuardian (address): 0x3cb4653F3B45F448D9100b118B75a1503281d2ee
Arg [3] : baseToken (address): 0x820C137fa70C8691f0e44Dc420a5e53c168921Dc
Arg [4] : baseTokenPriceFeed (address): 0x2330aaE3bca5F05169d5f4597964D44522F62930
Arg [5] : extensionDelegate (address): 0x3C30B5a5A04656565686f800481580Ac4E7ed178
Arg [6] : supplyKink (uint64): 900000000000000000
Arg [7] : supplyPerYearInterestRateSlopeLow (uint64): 54000000000000000
Arg [8] : supplyPerYearInterestRateSlopeHigh (uint64): 3034000000000000000
Arg [9] : supplyPerYearInterestRateBase (uint64): 0
Arg [10] : borrowKink (uint64): 900000000000000000
Arg [11] : borrowPerYearInterestRateSlopeLow (uint64): 50000000000000000
Arg [12] : borrowPerYearInterestRateSlopeHigh (uint64): 3400000000000000000
Arg [13] : borrowPerYearInterestRateBase (uint64): 15000000000000000
Arg [14] : storeFrontPriceFactor (uint64): 600000000000000000
Arg [15] : trackingIndexScale (uint64): 1000000000000000
Arg [16] : baseTrackingSupplySpeed (uint64): 0
Arg [17] : baseTrackingBorrowSpeed (uint64): 0
Arg [18] : baseMinForRewards (uint104): 1000000000
Arg [19] : baseBorrowMin (uint104): 1
Arg [20] : targetReserves (uint104): 20000000000000000000000000
Arg [21] : assetConfigs (tuple[]):
Arg [1] : asset (address): 0x5875eEE11Cf8398102FdAd704C9E96607675467a
Arg [2] : priceFeed (address): 0xC3a73A70d1577CD5B02da0bA91C0Afc8fA434DAF
Arg [3] : decimals (uint8): 18
Arg [4] : borrowCollateralFactor (uint64): 930000000000000000
Arg [5] : liquidateCollateralFactor (uint64): 950000000000000000
Arg [6] : liquidationFactor (uint64): 960000000000000000
Arg [7] : supplyCap (uint128): 0
,
Arg [1] : asset (address): 0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf
Arg [2] : priceFeed (address): 0x07DA0E54543a844a80ABE69c8A12F22B3aA59f9D
Arg [3] : decimals (uint8): 8
Arg [4] : borrowCollateralFactor (uint64): 800000000000000000
Arg [5] : liquidateCollateralFactor (uint64): 850000000000000000
Arg [6] : liquidationFactor (uint64): 950000000000000000
Arg [7] : supplyCap (uint128): 0
-----Encoded View---------------
37 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a02
Arg [2] : 0000000000000000000000003cb4653f3b45f448d9100b118b75a1503281d2ee
Arg [3] : 000000000000000000000000820c137fa70c8691f0e44dc420a5e53c168921dc
Arg [4] : 0000000000000000000000002330aae3bca5f05169d5f4597964d44522f62930
Arg [5] : 0000000000000000000000003c30b5a5a04656565686f800481580ac4e7ed178
Arg [6] : 0000000000000000000000000000000000000000000000000c7d713b49da0000
Arg [7] : 00000000000000000000000000000000000000000000000000bfd8b6c1df0000
Arg [8] : 0000000000000000000000000000000000000000000000002a1aeeecd8890000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000c7d713b49da0000
Arg [11] : 00000000000000000000000000000000000000000000000000b1a2bc2ec50000
Arg [12] : 0000000000000000000000000000000000000000000000002f2f39fc6c540000
Arg [13] : 00000000000000000000000000000000000000000000000000354a6ba7a18000
Arg [14] : 0000000000000000000000000000000000000000000000000853a0d2313c0000
Arg [15] : 00000000000000000000000000000000000000000000000000038d7ea4c68000
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [17] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [18] : 000000000000000000000000000000000000000000000000000000003b9aca00
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [20] : 000000000000000000000000000000000000000000108b2a2c28029094000000
Arg [21] : 00000000000000000000000000000000000000000000000000000000000002a0
Arg [22] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [23] : 0000000000000000000000005875eee11cf8398102fdad704c9e96607675467a
Arg [24] : 000000000000000000000000c3a73a70d1577cd5b02da0ba91c0afc8fa434daf
Arg [25] : 0000000000000000000000000000000000000000000000000000000000000012
Arg [26] : 0000000000000000000000000000000000000000000000000ce80612991d0000
Arg [27] : 0000000000000000000000000000000000000000000000000d2f13f7789f0000
Arg [28] : 0000000000000000000000000000000000000000000000000d529ae9e8600000
Arg [29] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [30] : 000000000000000000000000cbb7c0000ab88b473b1f5afd9ef808440eed33bf
Arg [31] : 00000000000000000000000007da0e54543a844a80abe69c8a12f22b3aa59f9d
Arg [32] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [33] : 0000000000000000000000000000000000000000000000000b1a2bc2ec500000
Arg [34] : 0000000000000000000000000000000000000000000000000bcbce7f1b150000
Arg [35] : 0000000000000000000000000000000000000000000000000d2f13f7789f0000
Arg [36] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.