Overview
MNT Balance
MNT Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xB2ebCAe7...12594D167 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
Configurator
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 "./CometFactory.sol";
import "./CometConfiguration.sol";
import "./ConfiguratorStorage.sol";
contract Configurator is ConfiguratorStorage {
/** Custom events **/
event AddAsset(address indexed cometProxy, AssetConfig assetConfig);
event CometDeployed(address indexed cometProxy, address indexed newComet);
event GovernorTransferred(address indexed oldGovernor, address indexed newGovernor);
event SetFactory(address indexed cometProxy, address indexed oldFactory, address indexed newFactory);
event SetGovernor(address indexed cometProxy, address indexed oldGovernor, address indexed newGovernor);
event SetConfiguration(address indexed cometProxy, Configuration oldConfiguration, Configuration newConfiguration);
event SetPauseGuardian(address indexed cometProxy, address indexed oldPauseGuardian, address indexed newPauseGuardian);
event SetBaseTokenPriceFeed(address indexed cometProxy, address indexed oldBaseTokenPriceFeed, address indexed newBaseTokenPriceFeed);
event SetExtensionDelegate(address indexed cometProxy, address indexed oldExt, address indexed newExt);
event SetSupplyKink(address indexed cometProxy,uint64 oldKink, uint64 newKink);
event SetSupplyPerYearInterestRateSlopeLow(address indexed cometProxy,uint64 oldIRSlopeLow, uint64 newIRSlopeLow);
event SetSupplyPerYearInterestRateSlopeHigh(address indexed cometProxy,uint64 oldIRSlopeHigh, uint64 newIRSlopeHigh);
event SetSupplyPerYearInterestRateBase(address indexed cometProxy,uint64 oldIRBase, uint64 newIRBase);
event SetBorrowKink(address indexed cometProxy,uint64 oldKink, uint64 newKink);
event SetBorrowPerYearInterestRateSlopeLow(address indexed cometProxy,uint64 oldIRSlopeLow, uint64 newIRSlopeLow);
event SetBorrowPerYearInterestRateSlopeHigh(address indexed cometProxy,uint64 oldIRSlopeHigh, uint64 newIRSlopeHigh);
event SetBorrowPerYearInterestRateBase(address indexed cometProxy,uint64 oldIRBase, uint64 newIRBase);
event SetStoreFrontPriceFactor(address indexed cometProxy, uint64 oldStoreFrontPriceFactor, uint64 newStoreFrontPriceFactor);
event SetBaseTrackingSupplySpeed(address indexed cometProxy, uint64 oldBaseTrackingSupplySpeed, uint64 newBaseTrackingSupplySpeed);
event SetBaseTrackingBorrowSpeed(address indexed cometProxy, uint64 oldBaseTrackingBorrowSpeed, uint64 newBaseTrackingBorrowSpeed);
event SetBaseMinForRewards(address indexed cometProxy, uint104 oldBaseMinForRewards, uint104 newBaseMinForRewards);
event SetBaseBorrowMin(address indexed cometProxy, uint104 oldBaseBorrowMin, uint104 newBaseBorrowMin);
event SetTargetReserves(address indexed cometProxy, uint104 oldTargetReserves, uint104 newTargetReserves);
event UpdateAsset(address indexed cometProxy, AssetConfig oldAssetConfig, AssetConfig newAssetConfig);
event UpdateAssetPriceFeed(address indexed cometProxy, address indexed asset, address oldPriceFeed, address newPriceFeed);
event UpdateAssetBorrowCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldBorrowCF, uint64 newBorrowCF);
event UpdateAssetLiquidateCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidateCF, uint64 newLiquidateCF);
event UpdateAssetLiquidationFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidationFactor, uint64 newLiquidationFactor);
event UpdateAssetSupplyCap(address indexed cometProxy, address indexed asset, uint128 oldSupplyCap, uint128 newSupplyCap);
/** Custom errors **/
error AlreadyInitialized();
error AssetDoesNotExist();
error ConfigurationAlreadyExists();
error InvalidAddress();
error Unauthorized();
/**
* @notice Constructs a new Configurator instance
**/
constructor() {
// Set a high version to prevent the implementation contract from being initialized
version = type(uint256).max;
}
/**
* @notice Initializes the storage for Configurator
* @param governor_ The address of the governor
**/
function initialize(address governor_) public {
if (version != 0) revert AlreadyInitialized();
if (governor_ == address(0)) revert InvalidAddress();
governor = governor_;
version = 1;
}
/**
* @notice Sets the factory for a Comet proxy
* @dev Note: Only callable by governor
**/
function setFactory(address cometProxy, address newFactory) external {
if (msg.sender != governor) revert Unauthorized();
address oldFactory = factory[cometProxy];
factory[cometProxy] = newFactory;
emit SetFactory(cometProxy, oldFactory, newFactory);
}
/**
* @notice Sets the entire Configuration for a Comet proxy
* @dev Note: All params can later be updated by the governor except for `baseToken` and `trackingIndexScale`
**/
function setConfiguration(address cometProxy, Configuration calldata newConfiguration) external {
if (msg.sender != governor) revert Unauthorized();
Configuration memory oldConfiguration = configuratorParams[cometProxy];
if (oldConfiguration.baseToken != address(0) &&
(oldConfiguration.baseToken != newConfiguration.baseToken ||
oldConfiguration.trackingIndexScale != newConfiguration.trackingIndexScale))
revert ConfigurationAlreadyExists();
configuratorParams[cometProxy] = newConfiguration;
emit SetConfiguration(cometProxy, oldConfiguration, newConfiguration);
}
/** Governance setters for Comet-related configuration **/
function setGovernor(address cometProxy, address newGovernor) external {
if (msg.sender != governor) revert Unauthorized();
address oldGovernor = configuratorParams[cometProxy].governor;
configuratorParams[cometProxy].governor = newGovernor;
emit SetGovernor(cometProxy, oldGovernor, newGovernor);
}
function setPauseGuardian(address cometProxy, address newPauseGuardian) external {
if (msg.sender != governor) revert Unauthorized();
address oldPauseGuardian = configuratorParams[cometProxy].pauseGuardian;
configuratorParams[cometProxy].pauseGuardian = newPauseGuardian;
emit SetPauseGuardian(cometProxy, oldPauseGuardian, newPauseGuardian);
}
function setBaseTokenPriceFeed(address cometProxy, address newBaseTokenPriceFeed) external {
if (msg.sender != governor) revert Unauthorized();
address oldBaseTokenPriceFeed = configuratorParams[cometProxy].baseTokenPriceFeed;
configuratorParams[cometProxy].baseTokenPriceFeed = newBaseTokenPriceFeed;
emit SetBaseTokenPriceFeed(cometProxy, oldBaseTokenPriceFeed, newBaseTokenPriceFeed);
}
function setExtensionDelegate(address cometProxy, address newExtensionDelegate) external {
if (msg.sender != governor) revert Unauthorized();
address oldExtensionDelegate = configuratorParams[cometProxy].extensionDelegate;
configuratorParams[cometProxy].extensionDelegate = newExtensionDelegate;
emit SetExtensionDelegate(cometProxy, oldExtensionDelegate, newExtensionDelegate);
}
function setSupplyKink(address cometProxy, uint64 newSupplyKink) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldSupplyKink = configuratorParams[cometProxy].supplyKink;
configuratorParams[cometProxy].supplyKink = newSupplyKink;
emit SetSupplyKink(cometProxy, oldSupplyKink, newSupplyKink);
}
function setSupplyPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow;
configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow = newSlope;
emit SetSupplyPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope);
}
function setSupplyPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh;
configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh = newSlope;
emit SetSupplyPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope);
}
function setSupplyPerYearInterestRateBase(address cometProxy, uint64 newBase) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldBase = configuratorParams[cometProxy].supplyPerYearInterestRateBase;
configuratorParams[cometProxy].supplyPerYearInterestRateBase = newBase;
emit SetSupplyPerYearInterestRateBase(cometProxy, oldBase, newBase);
}
function setBorrowKink(address cometProxy, uint64 newBorrowKink) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldBorrowKink = configuratorParams[cometProxy].borrowKink;
configuratorParams[cometProxy].borrowKink = newBorrowKink;
emit SetBorrowKink(cometProxy, oldBorrowKink, newBorrowKink);
}
function setBorrowPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow;
configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow = newSlope;
emit SetBorrowPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope);
}
function setBorrowPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh;
configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh = newSlope;
emit SetBorrowPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope);
}
function setBorrowPerYearInterestRateBase(address cometProxy, uint64 newBase) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldBase = configuratorParams[cometProxy].borrowPerYearInterestRateBase;
configuratorParams[cometProxy].borrowPerYearInterestRateBase = newBase;
emit SetBorrowPerYearInterestRateBase(cometProxy, oldBase, newBase);
}
function setStoreFrontPriceFactor(address cometProxy, uint64 newStoreFrontPriceFactor) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldStoreFrontPriceFactor = configuratorParams[cometProxy].storeFrontPriceFactor;
configuratorParams[cometProxy].storeFrontPriceFactor = newStoreFrontPriceFactor;
emit SetStoreFrontPriceFactor(cometProxy, oldStoreFrontPriceFactor, newStoreFrontPriceFactor);
}
function setBaseTrackingSupplySpeed(address cometProxy, uint64 newBaseTrackingSupplySpeed) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldBaseTrackingSupplySpeed = configuratorParams[cometProxy].baseTrackingSupplySpeed;
configuratorParams[cometProxy].baseTrackingSupplySpeed = newBaseTrackingSupplySpeed;
emit SetBaseTrackingSupplySpeed(cometProxy, oldBaseTrackingSupplySpeed, newBaseTrackingSupplySpeed);
}
function setBaseTrackingBorrowSpeed(address cometProxy, uint64 newBaseTrackingBorrowSpeed) external {
if (msg.sender != governor) revert Unauthorized();
uint64 oldBaseTrackingBorrowSpeed = configuratorParams[cometProxy].baseTrackingBorrowSpeed;
configuratorParams[cometProxy].baseTrackingBorrowSpeed = newBaseTrackingBorrowSpeed;
emit SetBaseTrackingBorrowSpeed(cometProxy, oldBaseTrackingBorrowSpeed, newBaseTrackingBorrowSpeed);
}
function setBaseMinForRewards(address cometProxy, uint104 newBaseMinForRewards) external {
if (msg.sender != governor) revert Unauthorized();
uint104 oldBaseMinForRewards = configuratorParams[cometProxy].baseMinForRewards;
configuratorParams[cometProxy].baseMinForRewards = newBaseMinForRewards;
emit SetBaseMinForRewards(cometProxy, oldBaseMinForRewards, newBaseMinForRewards);
}
function setBaseBorrowMin(address cometProxy, uint104 newBaseBorrowMin) external {
if (msg.sender != governor) revert Unauthorized();
uint104 oldBaseBorrowMin = configuratorParams[cometProxy].baseBorrowMin;
configuratorParams[cometProxy].baseBorrowMin = newBaseBorrowMin;
emit SetBaseBorrowMin(cometProxy, oldBaseBorrowMin, newBaseBorrowMin);
}
function setTargetReserves(address cometProxy, uint104 newTargetReserves) external {
if (msg.sender != governor) revert Unauthorized();
uint104 oldTargetReserves = configuratorParams[cometProxy].targetReserves;
configuratorParams[cometProxy].targetReserves = newTargetReserves;
emit SetTargetReserves(cometProxy, oldTargetReserves, newTargetReserves);
}
function addAsset(address cometProxy, AssetConfig calldata assetConfig) external {
if (msg.sender != governor) revert Unauthorized();
configuratorParams[cometProxy].assetConfigs.push(assetConfig);
emit AddAsset(cometProxy, assetConfig);
}
function updateAsset(address cometProxy, AssetConfig calldata newAssetConfig) external {
if (msg.sender != governor) revert Unauthorized();
uint assetIndex = getAssetIndex(cometProxy, newAssetConfig.asset);
AssetConfig memory oldAssetConfig = configuratorParams[cometProxy].assetConfigs[assetIndex];
configuratorParams[cometProxy].assetConfigs[assetIndex] = newAssetConfig;
emit UpdateAsset(cometProxy, oldAssetConfig, newAssetConfig);
}
function updateAssetPriceFeed(address cometProxy, address asset, address newPriceFeed) external {
if (msg.sender != governor) revert Unauthorized();
uint assetIndex = getAssetIndex(cometProxy, asset);
address oldPriceFeed = configuratorParams[cometProxy].assetConfigs[assetIndex].priceFeed;
configuratorParams[cometProxy].assetConfigs[assetIndex].priceFeed = newPriceFeed;
emit UpdateAssetPriceFeed(cometProxy, asset, oldPriceFeed, newPriceFeed);
}
function updateAssetBorrowCollateralFactor(address cometProxy, address asset, uint64 newBorrowCF) external {
if (msg.sender != governor) revert Unauthorized();
uint assetIndex = getAssetIndex(cometProxy, asset);
uint64 oldBorrowCF = configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor;
configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor = newBorrowCF;
emit UpdateAssetBorrowCollateralFactor(cometProxy, asset, oldBorrowCF, newBorrowCF);
}
function updateAssetLiquidateCollateralFactor(address cometProxy, address asset, uint64 newLiquidateCF) external {
if (msg.sender != governor) revert Unauthorized();
uint assetIndex = getAssetIndex(cometProxy, asset);
uint64 oldLiquidateCF = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor;
configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor = newLiquidateCF;
emit UpdateAssetLiquidateCollateralFactor(cometProxy, asset, oldLiquidateCF, newLiquidateCF);
}
function updateAssetLiquidationFactor(address cometProxy, address asset, uint64 newLiquidationFactor) external {
if (msg.sender != governor) revert Unauthorized();
uint assetIndex = getAssetIndex(cometProxy, asset);
uint64 oldLiquidationFactor = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor;
configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor = newLiquidationFactor;
emit UpdateAssetLiquidationFactor(cometProxy, asset, oldLiquidationFactor, newLiquidationFactor);
}
function updateAssetSupplyCap(address cometProxy, address asset, uint128 newSupplyCap) external {
if (msg.sender != governor) revert Unauthorized();
uint assetIndex = getAssetIndex(cometProxy, asset);
uint128 oldSupplyCap = configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap;
configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap = newSupplyCap;
emit UpdateAssetSupplyCap(cometProxy, asset, oldSupplyCap, newSupplyCap);
}
/** Other helpers **/
/**
* @dev Determine index of asset that matches given address
*/
function getAssetIndex(address cometProxy, address asset) public view returns (uint) {
AssetConfig[] memory assetConfigs = configuratorParams[cometProxy].assetConfigs;
uint numAssets = assetConfigs.length;
for (uint i = 0; i < numAssets; ) {
if (assetConfigs[i].asset == asset) {
return i;
}
unchecked { i++; }
}
revert AssetDoesNotExist();
}
/**
* @return The currently configured params for a Comet proxy
**/
function getConfiguration(address cometProxy) external view returns (Configuration memory) {
return configuratorParams[cometProxy];
}
/**
* @notice Deploy a new Comet implementation using the factory and Configuration for that Comet proxy
* @dev Note: Callable by anyone
*/
function deploy(address cometProxy) external returns (address) {
address newComet = CometFactory(factory[cometProxy]).clone(configuratorParams[cometProxy]);
emit CometDeployed(cometProxy, newComet);
return newComet;
}
/**
* @notice Transfers the governor rights to a new address
*/
function transferGovernor(address newGovernor) external {
if (msg.sender != governor) revert Unauthorized();
address oldGovernor = governor;
governor = newGovernor;
emit GovernorTransferred(oldGovernor, newGovernor);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;
import "./CometMainInterface.sol";
import "./IERC20NonStandard.sol";
import "./IPriceFeed.sol";
/**
* @title Compound's Comet Contract
* @notice An efficient monolithic money market protocol
* @author Compound
*/
contract Comet 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;
/** Collateral asset configuration (packed) **/
uint256 internal immutable asset00_a;
uint256 internal immutable asset00_b;
uint256 internal immutable asset01_a;
uint256 internal immutable asset01_b;
uint256 internal immutable asset02_a;
uint256 internal immutable asset02_b;
uint256 internal immutable asset03_a;
uint256 internal immutable asset03_b;
uint256 internal immutable asset04_a;
uint256 internal immutable asset04_b;
uint256 internal immutable asset05_a;
uint256 internal immutable asset05_b;
uint256 internal immutable asset06_a;
uint256 internal immutable asset06_b;
uint256 internal immutable asset07_a;
uint256 internal immutable asset07_b;
uint256 internal immutable asset08_a;
uint256 internal immutable asset08_b;
uint256 internal immutable asset09_a;
uint256 internal immutable asset09_b;
uint256 internal immutable asset10_a;
uint256 internal immutable asset10_b;
uint256 internal immutable asset11_a;
uint256 internal immutable asset11_b;
/**
* @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) 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);
(asset00_a, asset00_b) = getPackedAssetInternal(config.assetConfigs, 0);
(asset01_a, asset01_b) = getPackedAssetInternal(config.assetConfigs, 1);
(asset02_a, asset02_b) = getPackedAssetInternal(config.assetConfigs, 2);
(asset03_a, asset03_b) = getPackedAssetInternal(config.assetConfigs, 3);
(asset04_a, asset04_b) = getPackedAssetInternal(config.assetConfigs, 4);
(asset05_a, asset05_b) = getPackedAssetInternal(config.assetConfigs, 5);
(asset06_a, asset06_b) = getPackedAssetInternal(config.assetConfigs, 6);
(asset07_a, asset07_b) = getPackedAssetInternal(config.assetConfigs, 7);
(asset08_a, asset08_b) = getPackedAssetInternal(config.assetConfigs, 8);
(asset09_a, asset09_b) = getPackedAssetInternal(config.assetConfigs, 9);
(asset10_a, asset10_b) = getPackedAssetInternal(config.assetConfigs, 10);
(asset11_a, asset11_b) = getPackedAssetInternal(config.assetConfigs, 11);
}
/**
* @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;
}
/**
* @dev Checks and gets the packed asset info for storage
*/
function getPackedAssetInternal(AssetConfig[] memory assetConfigs, uint i) internal view returns (uint256, uint256) {
AssetConfig memory assetConfig;
if (i < assetConfigs.length) {
assembly {
assetConfig := mload(add(add(assetConfigs, 0x20), mul(i, 0x20)))
}
} else {
return (0, 0);
}
address asset = assetConfig.asset;
address priceFeed = assetConfig.priceFeed;
uint8 decimals_ = assetConfig.decimals;
// Short-circuit if asset is nil
if (asset == address(0)) {
return (0, 0);
}
// Sanity check price feed and asset decimals
if (IPriceFeed(priceFeed).decimals() != PRICE_FEED_DECIMALS) revert BadDecimals();
if (IERC20NonStandard(asset).decimals() != decimals_) revert BadDecimals();
// Ensure collateral factors are within range
if (assetConfig.borrowCollateralFactor >= assetConfig.liquidateCollateralFactor) revert BorrowCFTooLarge();
if (assetConfig.liquidateCollateralFactor > MAX_COLLATERAL_FACTOR) revert LiquidateCFTooLarge();
unchecked {
// Keep 4 decimals for each factor
uint64 descale = FACTOR_SCALE / 1e4;
uint16 borrowCollateralFactor = uint16(assetConfig.borrowCollateralFactor / descale);
uint16 liquidateCollateralFactor = uint16(assetConfig.liquidateCollateralFactor / descale);
uint16 liquidationFactor = uint16(assetConfig.liquidationFactor / descale);
// Be nice and check descaled values are still within range
if (borrowCollateralFactor >= liquidateCollateralFactor) revert BorrowCFTooLarge();
// Keep whole units of asset for supply cap
uint64 supplyCap = uint64(assetConfig.supplyCap / (10 ** decimals_));
uint256 word_a = (uint160(asset) << 0 |
uint256(borrowCollateralFactor) << 160 |
uint256(liquidateCollateralFactor) << 176 |
uint256(liquidationFactor) << 192);
uint256 word_b = (uint160(priceFeed) << 0 |
uint256(decimals_) << 160 |
uint256(supplyCap) << 168);
return (word_a, word_b);
}
}
/**
* @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) {
if (i >= numAssets) revert BadAsset();
uint256 word_a;
uint256 word_b;
if (i == 0) {
word_a = asset00_a;
word_b = asset00_b;
} else if (i == 1) {
word_a = asset01_a;
word_b = asset01_b;
} else if (i == 2) {
word_a = asset02_a;
word_b = asset02_b;
} else if (i == 3) {
word_a = asset03_a;
word_b = asset03_b;
} else if (i == 4) {
word_a = asset04_a;
word_b = asset04_b;
} else if (i == 5) {
word_a = asset05_a;
word_b = asset05_b;
} else if (i == 6) {
word_a = asset06_a;
word_b = asset06_b;
} else if (i == 7) {
word_a = asset07_a;
word_b = asset07_b;
} else if (i == 8) {
word_a = asset08_a;
word_b = asset08_b;
} else if (i == 9) {
word_a = asset09_a;
word_b = asset09_b;
} else if (i == 10) {
word_a = asset10_a;
word_b = asset10_b;
} else if (i == 11) {
word_a = asset11_a;
word_b = asset11_b;
} else {
revert Absurd();
}
address asset = address(uint160(word_a & type(uint160).max));
uint64 rescale = FACTOR_SCALE / 1e4;
uint64 borrowCollateralFactor = uint64(((word_a >> 160) & type(uint16).max) * rescale);
uint64 liquidateCollateralFactor = uint64(((word_a >> 176) & type(uint16).max) * rescale);
uint64 liquidationFactor = uint64(((word_a >> 192) & type(uint16).max) * rescale);
address priceFeed = address(uint160(word_b & type(uint160).max));
uint8 decimals_ = uint8(((word_b >> 160) & type(uint8).max));
uint64 scale = uint64(10 ** decimals_);
uint128 supplyCap = uint128(((word_b >> 168) & type(uint64).max) * scale);
return AssetInfo({
offset: i,
asset: asset,
priceFeed: priceFeed,
scale: scale,
borrowCollateralFactor: borrowCollateralFactor,
liquidateCollateralFactor: liquidateCollateralFactor,
liquidationFactor: liquidationFactor,
supplyCap: supplyCap
});
}
/**
* @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;
int liquidity = signedMulPrice(
presentValue(principal),
getPrice(baseTokenPriceFeed),
uint64(baseScale)
);
for (uint8 i = 0; i < numAssets; ) {
if (isInAsset(assetsIn, i)) {
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;
int liquidity = signedMulPrice(
presentValue(principal),
getPrice(baseTokenPriceFeed),
uint64(baseScale)
);
for (uint8 i = 0; i < numAssets; ) {
if (isInAsset(assetsIn, i)) {
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
*/
function isInAsset(uint16 assetsIn, uint8 assetOffset) internal pure returns (bool) {
return (assetsIn & (uint16(1) << assetOffset) != 0);
}
/**
* @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
userBasic[account].assetsIn |= (uint16(1) << assetInfo.offset);
} else if (initialUserBalance != 0 && finalUserBalance == 0) {
// clear bit for asset
userBasic[account].assetsIn &= ~(uint16(1) << assetInfo.offset);
}
}
/**
* @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;
uint256 basePrice = getPrice(baseTokenPriceFeed);
uint256 deltaValue = 0;
for (uint8 i = 0; i < numAssets; ) {
if (isInAsset(assetsIn, i)) {
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;
(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 "./Comet.sol";
import "./CometConfiguration.sol";
contract CometFactory is CometConfiguration {
function clone(Configuration calldata config) external returns (address) {
return address(new Comet(config));
}
}// 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 "./CometConfiguration.sol";
/**
* @title Compound's Comet Configuration Storage Interface
* @dev Versions can enforce append-only storage slots via inheritance.
* @author Compound
*/
contract ConfiguratorStorage is CometConfiguration {
/// @notice The current version of Configurator. This version should be
/// checked in the initializer function.
uint public version;
/// @notice Mapping of Comet proxy addresses to their Configuration settings
/// @dev This needs to be internal to avoid a `CompilerError: Stack too deep
/// when compiling inline assembly` error that is caused by the default
/// getters created for public variables.
mapping(address => Configuration) internal configuratorParams;
/// @notice The governor of the protocol
address public governor;
/// @notice Mapping of Comet proxy addresses to their Comet factory contracts
mapping(address => address) public factory;
}// 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":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AssetDoesNotExist","type":"error"},{"inputs":[],"name":"ConfigurationAlreadyExists","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"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"}],"indexed":false,"internalType":"struct CometConfiguration.AssetConfig","name":"assetConfig","type":"tuple"}],"name":"AddAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"newComet","type":"address"}],"name":"CometDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernor","type":"address"}],"name":"GovernorTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint104","name":"oldBaseBorrowMin","type":"uint104"},{"indexed":false,"internalType":"uint104","name":"newBaseBorrowMin","type":"uint104"}],"name":"SetBaseBorrowMin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint104","name":"oldBaseMinForRewards","type":"uint104"},{"indexed":false,"internalType":"uint104","name":"newBaseMinForRewards","type":"uint104"}],"name":"SetBaseMinForRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"oldBaseTokenPriceFeed","type":"address"},{"indexed":true,"internalType":"address","name":"newBaseTokenPriceFeed","type":"address"}],"name":"SetBaseTokenPriceFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldBaseTrackingBorrowSpeed","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newBaseTrackingBorrowSpeed","type":"uint64"}],"name":"SetBaseTrackingBorrowSpeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldBaseTrackingSupplySpeed","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newBaseTrackingSupplySpeed","type":"uint64"}],"name":"SetBaseTrackingSupplySpeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldKink","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newKink","type":"uint64"}],"name":"SetBorrowKink","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldIRBase","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newIRBase","type":"uint64"}],"name":"SetBorrowPerYearInterestRateBase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldIRSlopeHigh","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newIRSlopeHigh","type":"uint64"}],"name":"SetBorrowPerYearInterestRateSlopeHigh","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldIRSlopeLow","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newIRSlopeLow","type":"uint64"}],"name":"SetBorrowPerYearInterestRateSlopeLow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"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[]"}],"indexed":false,"internalType":"struct CometConfiguration.Configuration","name":"oldConfiguration","type":"tuple"},{"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[]"}],"indexed":false,"internalType":"struct CometConfiguration.Configuration","name":"newConfiguration","type":"tuple"}],"name":"SetConfiguration","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"oldExt","type":"address"},{"indexed":true,"internalType":"address","name":"newExt","type":"address"}],"name":"SetExtensionDelegate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"oldFactory","type":"address"},{"indexed":true,"internalType":"address","name":"newFactory","type":"address"}],"name":"SetFactory","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"oldGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernor","type":"address"}],"name":"SetGovernor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"oldPauseGuardian","type":"address"},{"indexed":true,"internalType":"address","name":"newPauseGuardian","type":"address"}],"name":"SetPauseGuardian","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldStoreFrontPriceFactor","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newStoreFrontPriceFactor","type":"uint64"}],"name":"SetStoreFrontPriceFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldKink","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newKink","type":"uint64"}],"name":"SetSupplyKink","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldIRBase","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newIRBase","type":"uint64"}],"name":"SetSupplyPerYearInterestRateBase","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldIRSlopeHigh","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newIRSlopeHigh","type":"uint64"}],"name":"SetSupplyPerYearInterestRateSlopeHigh","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldIRSlopeLow","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newIRSlopeLow","type":"uint64"}],"name":"SetSupplyPerYearInterestRateSlopeLow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":false,"internalType":"uint104","name":"oldTargetReserves","type":"uint104"},{"indexed":false,"internalType":"uint104","name":"newTargetReserves","type":"uint104"}],"name":"SetTargetReserves","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"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"}],"indexed":false,"internalType":"struct CometConfiguration.AssetConfig","name":"oldAssetConfig","type":"tuple"},{"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"}],"indexed":false,"internalType":"struct CometConfiguration.AssetConfig","name":"newAssetConfig","type":"tuple"}],"name":"UpdateAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldBorrowCF","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newBorrowCF","type":"uint64"}],"name":"UpdateAssetBorrowCollateralFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldLiquidateCF","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newLiquidateCF","type":"uint64"}],"name":"UpdateAssetLiquidateCollateralFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint64","name":"oldLiquidationFactor","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"newLiquidationFactor","type":"uint64"}],"name":"UpdateAssetLiquidationFactor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"address","name":"oldPriceFeed","type":"address"},{"indexed":false,"internalType":"address","name":"newPriceFeed","type":"address"}],"name":"UpdateAssetPriceFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"cometProxy","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint128","name":"oldSupplyCap","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"newSupplyCap","type":"uint128"}],"name":"UpdateAssetSupplyCap","type":"event"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"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":"assetConfig","type":"tuple"}],"name":"addAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"}],"name":"deploy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"asset","type":"address"}],"name":"getAssetIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"}],"name":"getConfiguration","outputs":[{"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":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"governor_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint104","name":"newBaseBorrowMin","type":"uint104"}],"name":"setBaseBorrowMin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint104","name":"newBaseMinForRewards","type":"uint104"}],"name":"setBaseMinForRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"newBaseTokenPriceFeed","type":"address"}],"name":"setBaseTokenPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newBaseTrackingBorrowSpeed","type":"uint64"}],"name":"setBaseTrackingBorrowSpeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newBaseTrackingSupplySpeed","type":"uint64"}],"name":"setBaseTrackingSupplySpeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newBorrowKink","type":"uint64"}],"name":"setBorrowKink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newBase","type":"uint64"}],"name":"setBorrowPerYearInterestRateBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newSlope","type":"uint64"}],"name":"setBorrowPerYearInterestRateSlopeHigh","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newSlope","type":"uint64"}],"name":"setBorrowPerYearInterestRateSlopeLow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"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":"newConfiguration","type":"tuple"}],"name":"setConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"newExtensionDelegate","type":"address"}],"name":"setExtensionDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"newFactory","type":"address"}],"name":"setFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"newGovernor","type":"address"}],"name":"setGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"newPauseGuardian","type":"address"}],"name":"setPauseGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newStoreFrontPriceFactor","type":"uint64"}],"name":"setStoreFrontPriceFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newSupplyKink","type":"uint64"}],"name":"setSupplyKink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newBase","type":"uint64"}],"name":"setSupplyPerYearInterestRateBase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newSlope","type":"uint64"}],"name":"setSupplyPerYearInterestRateSlopeHigh","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint64","name":"newSlope","type":"uint64"}],"name":"setSupplyPerYearInterestRateSlopeLow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"uint104","name":"newTargetReserves","type":"uint104"}],"name":"setTargetReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newGovernor","type":"address"}],"name":"transferGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"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":"newAssetConfig","type":"tuple"}],"name":"updateAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint64","name":"newBorrowCF","type":"uint64"}],"name":"updateAssetBorrowCollateralFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint64","name":"newLiquidateCF","type":"uint64"}],"name":"updateAssetLiquidateCollateralFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint64","name":"newLiquidationFactor","type":"uint64"}],"name":"updateAssetLiquidationFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"newPriceFeed","type":"address"}],"name":"updateAssetPriceFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cometProxy","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint128","name":"newSupplyCap","type":"uint128"}],"name":"updateAssetSupplyCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
0x6080806040523461001c5760001960005561283490816100228239f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c908163058e415514612070575080630c340a2414612047578063240dd96d14611fb8578063294be43314611ee757806335e67c1014611e55578063395c0fda14611e155780633dd4036514611d865780634a900c5a14611ce65780634c96a38914611a2857806354fd4d5014611a0a5780635bfb83731461197d5780635c9ae499146118ee5780635e8255641461185f57806374b20ab8146117d057806377a7dafd146116ed578063786f0ac41461165e5780637d5e1840146115be5780638145ae7d1461152a578063886fe70b146114e55780638d2ed08d146114565780639340d433146113c95780639a01fe821461132b5780639a0fd80814611255578063a2ced7fd1461117f578063b2f5ee19146110df578063b73585f114611016578063b8cc9ce614610fa2578063c1252f90146107c7578063c44b11f71461059d578063c4d66de81461052c578063d89e834f1461048c578063e1a533ed146103fa578063e8623ec514610357578063ea31a447146102955763ecb9a875146101a057600080fd5b34610290576060366003190112610290576001600160a01b036004358181169081810361029057602435908382169384830361029057604435916001600160401b039182841684036102905760025416330361027f5782600261026461022a7f4bce180f5fbcc3f04e85605e3179ceaa66041248373ced1a406d4c44d91e37979761026b95612775565b948860005260016020528261024687600a604060002001612743565b50015460401c1694886000526001602052600a604060002001612743565b5001612452565b61027a6040519283928361270f565b0390a3005b6040516282b42960e81b8152600490fd5b600080fd5b3461029057610100366003190112610290576004356001600160a01b03818116918290036102905760e03660231901126102905760025416330361027f576000818152600160205260409020600a018054600160401b811015610341576103078161030d936001602494018155612743565b90612579565b7f1f7dcc7122c2fe2d685db789d8cde941d28c9d5bf456dcd260705c8d4aef4ef860e060405161033e816024612671565ba2005b634e487b7160e01b600052604160045260246000fd5b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f576000838152600160205260409081902060060180547fec47838861ac4faa72ef1cf4d982f923880203912cd0c53d6fea2e611562f82c94921c909116906103e6908390612452565b6103f56040519283928361270f565b0390a2005b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f5760008281526001602052604080822060030180546001600160a01b0319811685179091559051919491939116907f1e3daca7fe0d6c7ab58271d196454f1d9e867a09de95666bcad4ab688e750f1a8585a4f35b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160681b039060243590828216908183036102905760025416330361027f576000848152600160205260409081902060080180546001600160681b031981169093179055517f635524bd339ec1b914f9b13607c72592cfa9538a3c56170a59094dde834bb41d93909283926103f5921683612729565b34610290576020366003190112610290576004356001600160a01b038116908190036102905760005461058c57801561057a57600280546001600160a01b0319169190911790556001600055005b60405163e6c4247b60e01b8152600490fd5b60405162dc149f60e41b8152600490fd5b34610290576020366003190112610290576004356001600160a01b03811681036102905760606102806040516105d56102a082612311565b60008152600060208201526000604082015260008382015260006080820152600060a0820152600060c0820152600060e08201526000610100820152600061012082015260006101408201526000610160820152600061018082015260006101a082015260006101c082015260006101e08201526000610200820152600061022082015260006102408201526000610260820152015260018060a01b031660005260016020526107c360406000206107a9600a604051926106986102a085612311565b80546001600160a01b0390811685526001820154811660208601526002820154811660408087019190915260038301548216606087015260048301549182166080808801919091526001600160401b0360a093841c811693880193909352600584015480841660c0808a019190915281841c851660e08a015281831c85166101008a015290811c61012089015260068501548085166101408a015280841c85166101608a015280831c85166101808a0152901c6101a088015260078401548084166101c08901529182901c83166101e08801521c1661020085015260088101546001600160681b0380821661022087015260689190911c81166102408601526009820154166102608501520161239f565b6102808201526040519182916020835260208301906121ad565b0390f35b346102905760031960403682011261029057600435906001600160a01b0382168203610290576001600160401b0360243511610290576102a09060243536030112610290576002546001600160a01b0316330361027f5760018060a01b03811660005260016020526040600020610849600a604051926106986102a085612311565b61028082015260408101516001600160a01b03168015159081610f50575b50610f3e576001600160a01b03828116600090815260016020526040902090610894600460243501612401565b82546001600160a01b03191691161781556001600160a01b036108ba6024803501612401565b600183018054919092166001600160a01b0319909116179055600281016001600160a01b036108ed604460243501612401565b82546001600160a01b0319169116179055600381016001600160a01b03610918602435606401612401565b82546001600160a01b031916911617905561096b600482016001600160a01b03610946602435608401612401565b82546001600160a01b031916911617815561096560243560a401612415565b90612429565b6001600160401b0361098160243560c401612415565b1660018060401b03196005830154161760058201556109b06109a760e460243501612415565b60058301612452565b6109cb6109c261010460243501612415565b6005830161247b565b6109e66109dd61012460243501612415565b600583016124a4565b6001600160401b036109fd60243561014401612415565b1660018060401b0319600683015416176006820155610a2d610a2461016460243501612415565b60068301612452565b610a48610a3f61018460243501612415565b6006830161247b565b610a63610a5a6101a460243501612415565b600683016124a4565b6001600160401b03610a7a6024356101c401612415565b1660018060401b0319600783015416176007820155610aaa610aa16101e460243501612415565b60078301612452565b610ac5610abc61020460243501612415565b6007830161247b565b6001600160681b03610adc602435610224016124c7565b1660018060681b0319600883015416176008820155610b0c610b03610244602435016124c7565b600883016124db565b6001600160681b03610b23602435610264016124c7565b16600982019060018060681b0319825416179055602219602435360301610284602435013512156102905760243561028481013501906001600160401b036004830135116102905760e06004830135023603602483011361029057600160401b60048301351161034157600a81018054600484013591829055908111610ee8575b50600a01600090815260208120602483015b60048401358310610ec5578585610bd8604051916040835260408301906121ad565b8181036020830152916001600160a01b03610bf760046024350161210e565b1683526001600160a01b03610c0f602480350161210e565b1660208401526001600160a01b03610c2b60243560440161210e565b1660408401526001600160a01b03610c4760243560640161210e565b1660608401526001600160a01b03610c6360243560840161210e565b1660808401526001600160401b03610c7f60243560a401612122565b1660a08401526001600160401b03610c9b60243560c401612122565b1660c08401526001600160401b03610cb760243560e401612122565b1660e08401526001600160401b03610cd460243561010401612122565b166101008401526001600160401b03610cf260243561012401612122565b166101208401526001600160401b03610d1060243561014401612122565b166101408401526001600160401b03610d2e60243561016401612122565b166101608401526001600160401b03610d4c60243561018401612122565b166101808401526001600160401b03610d6a6024356101a401612122565b166101a08401526001600160401b03610d886024356101c401612122565b166101c08401526001600160401b03610da66024356101e401612122565b166101e08401526001600160401b03610dc460243561020401612122565b166102008401526001600160681b03610de260243561022401612136565b166102208401526001600160681b03610e0060243561024401612136565b166102408401526001600160681b03610e1e60243561026401612136565b166102608401526024356102846024350135016024600482013591019360018060401b0382116102905760e082023603851361029057806102a06102806102c0930152826102a082015201939060005b818110610ea7576001600160a01b0384167f11750c0169cdcebd42703782ec1a557a8ddebc9c3239aaf46662cd6c81cdb90b86880387a2005b90919460e08082610eba6001948a612671565b019601929101610e6e565b6001600360e083610eda600495600088612579565b019301930192919050610bb6565b610ef3906003612504565b610f0260048401356003612504565b90600a830160005260206000209182015b8183018110610f23575050610ba4565b80600060039255600060018201556000600282015501610f13565b604051630735e0fd60e51b8152600490fd5b90506001600160a01b03610f68602435604401612401565b1614801590610f78575b83610867565b506101c08101516001600160401b0390811690610f9a6024356101c401612415565b161415610f72565b34610290576020366003190112610290576001600160a01b0360043581811690819003610290576002549182169081330361027f576001600160a01b0319909216821760025560405160009290917f6fadb1c244276388aee22be93b919985a18748c021e5d48553957a48101a25608484a3f35b34610290576060366003190112610290576001600160a01b036004358181169081810361029057602435908382169384830361029057604435916001600160401b039182841684036102905760025416330361027f578260016110d86110a07f14bba7d3df0797b2f5143e4f2087f29fcd3ee3ec3197d38a7f77f85dc0d0ec639761026b95612775565b948860005282602052826110bb87600a604060002001612743565b50015460a81c16948860005282602052600a604060002001612743565b500161252d565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b039060243590828216908183036102905760025416330361027f576000848152600160205260409081902060060180546001600160401b031981169093179055517fe5d8ea5f9f9bc1e3132e593561d5b440062de5e0d5585a7046c87ca172a60d4693909283926103f592168361270f565b34610290576060366003190112610290576001600160a01b036004358181169081810361029057602435908382169384830361029057604435906001600160801b038216908183036102905760025416330361027f576112486112057f561b42b6b7ded5005c55634f0a6bd24d306cb04b04533bab7e1a644b6724548695604095612775565b9286600052600160205260026112418161122587600a8a60002001612743565b50015460801c95896000526001602052600a8860002001612743565b5001612556565b82519182526020820152a3005b3461029057610100366003190112610290576001600160a01b03600435818116918282036102905760e0366023190112610290578060025416330361027f576024359081168103610290576112ce6101c0917ff0d2e933bc5a83ab653c27f5ae312ee5f4a394a45c34bb90e8c790bf0ed3834193612775565b83600052600160205261131060246103076112f96112f385600a604060002001612743565b50612334565b93876000526001602052600a604060002001612743565b61131d604051809261214a565b61033e60e082016024612671565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160681b03906024359082821682036102905760025416330361027f57600083815260016020526040902060080180547f2cc4a6aedb45911a1034b2320f16567fa4e2eca3f1f5d3b46804f6bc42b7c3f29360689190911c16906113ba9083906124db565b6103f560405192839283612729565b34610290576040366003190112610290576004356001600160a01b038181169182900361029057602435906001600160401b03821682036102905760025416330361027f57600082815260016020526040902060060180547f864cdb8aef050e3718f73f8f3512418f04745083156b40523b128e79b411fc2d929160c09190911c906103e69083906124a4565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f57600083815260016020526040902060070180547fcd38d79accad9a0b2cec7a7f94a4ceb7d9b0df5f35bdcb6ee4212b695fad0aa19360809190911c16906103e690839061247b565b34610290576040366003190112610290576001600160a01b0360043581811681036102905760243591821682036102905760209161152291612775565b604051908152f35b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f57600082815260016020819052604080832090910180546001600160a01b0319811685179091559051919491939116907fb60cc4e8fd32e3f131099a821d4716afdb1e906f90421b5edb21070d209d0ee28585a4f35b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160681b039060243590828216908183036102905760025416330361027f576000848152600160205260409081902060090180546001600160681b031981169093179055517f0fcb429b7790258a8e50ab0f30505a67d74d6571119febb9690e6264594e2e2993909283926103f5921683612729565b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f5760008281526001602052604080822080546001600160a01b0319811685179091559051919491939116907f54b27c9d187943783592d79e0380d54f9a545d098bd921e5919d4b3305bd603f8585a4f35b34610290576060366003190112610290576004356001600160a01b038082169081830361029057602435908082169384830361029057604435916001600160401b0391828416918285036102905760025416330361027f576117ac6117757fbdfea73f1d581ded04f608d47cd124146963b03795e30c9f9e16d57bb1fed65296600293612775565b938760005260016020528261179186600a604060002001612743565b5001541693876000526001602052600a604060002001612743565b500180546001600160401b031916909117905560405191829161027a91908361270f565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f57600083815260016020526040902060060180547f7e237d05d262a573a6b2d126c2065264a3bcabb68e67a1d5a1e88b1dbef6666d9360809190911c16906103e690839061247b565b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f5760008281526003602052604080822080546001600160a01b0319811685179091559051919491939116907fcc826d20934cb90e9329d09ff55b4e43831c5bb3a3305fb536842ad49041e7d58585a4f35b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f576000838152600160205260409081902060050180547f9fd77f9236bc26e7c30eaa679ccff4200f9a813e5950b2904c29f11d0b5f2a5e94921c909116906103e6908390612452565b34610290576040366003190112610290576004356001600160a01b038181169182900361029057602435906001600160401b03821682036102905760025416330361027f57600082815260016020526040902060050180547fe4e8221220a251ab6772c13e04f6c54532602ec260a26f48ff23fa8b11f41be7929160c09190911c906103e69083906124a4565b34610290576000366003190112610290576020600054604051908152f35b34610290576020366003190112610290576004356001600160a01b0381168103610290576001600160a01b0381811660009081526003602081815260408084205460018084528286208351632d52643960e01b8152600480820187905282548a166024830152928201548916604482015260028201548916606482015295810154881660848701529081015480881660a487015260a01c6001600160401b0390811660c4870152600582015480821660e488015280851c8216610104880152608081811c831661012489015260c091821c61014489015260068401548084166101648a015280871c84166101848a015280821c84166101a48a015290911c6101c488015260078301548083166101e48901529485901c82166102048801529390931c90921661022485015260088201546001600160681b0380821661024487015260689190911c81166102648601526009830154166102848501526102a06102a4850152600a90910180546102c48501819052908552918420929594169285926102e484019290915b818110611c6657505050918160008160209503925af18015611c5a57600090611c15575b60405160209350916001600160a01b03918216918291167f3da528dfe78562a1f409134989443b5f21ee92023a64b90dedeb2002415189b6600085a38152f35b50906020813d602011611c52575b81611c3060209383612311565b810103126102905751906001600160a01b038216820361029057602091611bd5565b3d9150611c23565b6040513d6000823e3d90fd5b82546001600160a01b039081168552600180850154918216602087015260a082811c60ff1660408089019190915260a89390931c6001600160401b03908116606089015260028701548082166080808b01919091529481901c9091169188019190915290911c60c086015288955060e09094019360039093019201611bb1565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b039060243590828216908183036102905760025416330361027f576000848152600160205260409081902060050180546001600160401b031981169093179055517fc936b3eb07b584b686d11042214266fed11036dbc226159d67b3cfaa4ce26f7893909283926103f592168361270f565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f57600083815260016020526040902060050180547f56027dd4756fabe0c40c7de2c732b95d170796feaf975883a17a087b3718e6b99360809190911c16906103e690839061247b565b34610290576020366003190112610290576004356001600160a01b0381811691829003610290576020916000526003825260406000205416604051908152f35b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f5760008281526001602052604080822060040180546001600160a01b0319811685179091559051919491939116907fc86eba353c79b422cdb4d71fcc7db3615603457a42c0559fcf1b31dfd66920b38585a4f35b34610290576060366003190112610290576001600160a01b0360043581811690818103610290576024358381169384820361029057604435818116809103610290578160025416330361027f576001611f99611f666040957f1736faf0e37344d44b8757867808a35e1d4961804de8c3dec2896bf1c1d6fc5197612775565b93876000528260205282611f8086600a8960002001612743565b50015416938760005282602052600a8660002001612743565b500180546001600160a01b0319168217905582519182526020820152a3005b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f576000838152600160205260409081902060070180547faf80475c4b413d347b2ac9b71b6c734ba09a6f4771aba12edc65346cffe273f594921c909116906103e6908390612452565b34610290576000366003190112610290576002546040516001600160a01b039091168152602090f35b34610290576040366003190112610290576004356001600160a01b038181169182900361029057602435906001600160401b039081831683036102905760025416330361210057600083815260016020526040902060040180547f35ebb489f572b08259fa0a007e62d8390043159fcf4a6c9a517dd1eb4dc77dfc939260a09190911c16906103e6908390612429565b6282b42960e81b8452600484fd5b35906001600160a01b038216820361029057565b35906001600160401b038216820361029057565b35906001600160681b038216820361029057565b60c09060018060a01b03808251168452602082015116602084015260ff604082015116604084015260018060401b0380606083015116606085015280608083015116608085015260a08201511660a08401528160018060801b0391015116910152565b906102a0908181019060018060a01b038085511682526102c0602092828493848901511684830152806040890151166040830152806060890151166060830152608088015116608082015260018060401b03958660a08901511660a08301528660c08901511660c083015260e09680888a0151168884015261010081818b0151169084015261012081818b0151169084015261014081818b0151169084015261016081818b0151169084015261018081818b015116908401526101a081818b015116908401526101c081818b015116908401526101e081818b0151169084015261020090818a0151169083015260018060681b0361022081818b0151169084015261024081818b0151169084015261026090818a0151169083015261028080980151978201528651809552019401926000905b8382106122ef57505050505090565b90919293948382826123046001948a5161214a565b01960194939201906122e0565b601f909101601f19168101906001600160401b0382119082101761034157604052565b9060405161234360e082612311565b60c08193600260018060a01b03918281541685526001810154928316602086015260ff8360a01c16604086015260018060401b03809360a81c16606086015201549080821660808501528160401c1660a084015260801c910152565b80549091906001600160401b038111610341576040519260206123c7818460051b0186612311565b82855260009182528082208186015b8484106123e4575050505050565b6003836001926123f385612334565b8152019201930192906123d6565b356001600160a01b03811681036102905790565b356001600160401b03811681036102905790565b8054600160a01b600160e01b03191660a09290921b600160a01b600160e01b0316919091179055565b8054600160401b600160801b03191660409290921b600160401b600160801b0316919091179055565b8054600160801b600160c01b03191660809290921b600160801b600160c01b0316919091179055565b80546001600160c01b031660c09290921b6001600160c01b031916919091179055565b356001600160681b03811681036102905790565b8054600160681b600160d01b03191660689290921b600160681b600160d01b0316919091179055565b8060001904821181151516612517570290565b634e487b7160e01b600052601160045260246000fd5b8054600160a81b600160e81b03191660a89290921b600160a81b600160e81b0316919091179055565b80546001600160801b031660809290921b6001600160801b031916919091179055565b9061265b576001600160a01b038061259084612401565b169160018060a01b0319928382541617815560018101916125b360208601612401565b169182815494851617815560408501359060ff821682036102905760c0946002946126029360ff60a01b9060a01b169160018060a81b031916171781556125fc60608701612415565b9061252d565b01916001600160401b0361261860808301612415565b84546001600160401b031916911617835561263e61263860a08301612415565b84612452565b01356001600160801b03811681036102905761265991612556565b565b634e487b7160e01b600052600060045260246000fd5b6001600160a01b03806126838361210e565b1683526126926020830161210e565b16602083015260408101359060ff821680920361029057604083019190915260c0906001600160401b03806126c960608401612122565b166060850152806126dc60808401612122565b1660808501526126ee60a08301612122565b1660a084015201356001600160801b03811691908290036102905760c00152565b6001600160401b0391821681529116602082015260400190565b6001600160681b0391821681529116602082015260400190565b805482101561275f576000526003602060002091020190600090565b634e487b7160e01b600052603260045260246000fd5b9160009160018060a01b038094168352600193602085815261279c600a604087200161239f565b805195805b8781106127ba576040516367fa94e760e01b8152600490fd5b82518110156127ea5784848260051b850101515116858716146127de5788016127a1565b96505050505050915090565b634e487b7160e01b82526032600452602482fdfea26469706673582212205eccb8079963c94e22fd1f7a24f41150ee3776499efdad8d3f5e6e6472c30a4e64736f6c634300080f0033
Deployed Bytecode
0x608080604052600436101561001357600080fd5b60003560e01c908163058e415514612070575080630c340a2414612047578063240dd96d14611fb8578063294be43314611ee757806335e67c1014611e55578063395c0fda14611e155780633dd4036514611d865780634a900c5a14611ce65780634c96a38914611a2857806354fd4d5014611a0a5780635bfb83731461197d5780635c9ae499146118ee5780635e8255641461185f57806374b20ab8146117d057806377a7dafd146116ed578063786f0ac41461165e5780637d5e1840146115be5780638145ae7d1461152a578063886fe70b146114e55780638d2ed08d146114565780639340d433146113c95780639a01fe821461132b5780639a0fd80814611255578063a2ced7fd1461117f578063b2f5ee19146110df578063b73585f114611016578063b8cc9ce614610fa2578063c1252f90146107c7578063c44b11f71461059d578063c4d66de81461052c578063d89e834f1461048c578063e1a533ed146103fa578063e8623ec514610357578063ea31a447146102955763ecb9a875146101a057600080fd5b34610290576060366003190112610290576001600160a01b036004358181169081810361029057602435908382169384830361029057604435916001600160401b039182841684036102905760025416330361027f5782600261026461022a7f4bce180f5fbcc3f04e85605e3179ceaa66041248373ced1a406d4c44d91e37979761026b95612775565b948860005260016020528261024687600a604060002001612743565b50015460401c1694886000526001602052600a604060002001612743565b5001612452565b61027a6040519283928361270f565b0390a3005b6040516282b42960e81b8152600490fd5b600080fd5b3461029057610100366003190112610290576004356001600160a01b03818116918290036102905760e03660231901126102905760025416330361027f576000818152600160205260409020600a018054600160401b811015610341576103078161030d936001602494018155612743565b90612579565b7f1f7dcc7122c2fe2d685db789d8cde941d28c9d5bf456dcd260705c8d4aef4ef860e060405161033e816024612671565ba2005b634e487b7160e01b600052604160045260246000fd5b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f576000838152600160205260409081902060060180547fec47838861ac4faa72ef1cf4d982f923880203912cd0c53d6fea2e611562f82c94921c909116906103e6908390612452565b6103f56040519283928361270f565b0390a2005b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f5760008281526001602052604080822060030180546001600160a01b0319811685179091559051919491939116907f1e3daca7fe0d6c7ab58271d196454f1d9e867a09de95666bcad4ab688e750f1a8585a4f35b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160681b039060243590828216908183036102905760025416330361027f576000848152600160205260409081902060080180546001600160681b031981169093179055517f635524bd339ec1b914f9b13607c72592cfa9538a3c56170a59094dde834bb41d93909283926103f5921683612729565b34610290576020366003190112610290576004356001600160a01b038116908190036102905760005461058c57801561057a57600280546001600160a01b0319169190911790556001600055005b60405163e6c4247b60e01b8152600490fd5b60405162dc149f60e41b8152600490fd5b34610290576020366003190112610290576004356001600160a01b03811681036102905760606102806040516105d56102a082612311565b60008152600060208201526000604082015260008382015260006080820152600060a0820152600060c0820152600060e08201526000610100820152600061012082015260006101408201526000610160820152600061018082015260006101a082015260006101c082015260006101e08201526000610200820152600061022082015260006102408201526000610260820152015260018060a01b031660005260016020526107c360406000206107a9600a604051926106986102a085612311565b80546001600160a01b0390811685526001820154811660208601526002820154811660408087019190915260038301548216606087015260048301549182166080808801919091526001600160401b0360a093841c811693880193909352600584015480841660c0808a019190915281841c851660e08a015281831c85166101008a015290811c61012089015260068501548085166101408a015280841c85166101608a015280831c85166101808a0152901c6101a088015260078401548084166101c08901529182901c83166101e08801521c1661020085015260088101546001600160681b0380821661022087015260689190911c81166102408601526009820154166102608501520161239f565b6102808201526040519182916020835260208301906121ad565b0390f35b346102905760031960403682011261029057600435906001600160a01b0382168203610290576001600160401b0360243511610290576102a09060243536030112610290576002546001600160a01b0316330361027f5760018060a01b03811660005260016020526040600020610849600a604051926106986102a085612311565b61028082015260408101516001600160a01b03168015159081610f50575b50610f3e576001600160a01b03828116600090815260016020526040902090610894600460243501612401565b82546001600160a01b03191691161781556001600160a01b036108ba6024803501612401565b600183018054919092166001600160a01b0319909116179055600281016001600160a01b036108ed604460243501612401565b82546001600160a01b0319169116179055600381016001600160a01b03610918602435606401612401565b82546001600160a01b031916911617905561096b600482016001600160a01b03610946602435608401612401565b82546001600160a01b031916911617815561096560243560a401612415565b90612429565b6001600160401b0361098160243560c401612415565b1660018060401b03196005830154161760058201556109b06109a760e460243501612415565b60058301612452565b6109cb6109c261010460243501612415565b6005830161247b565b6109e66109dd61012460243501612415565b600583016124a4565b6001600160401b036109fd60243561014401612415565b1660018060401b0319600683015416176006820155610a2d610a2461016460243501612415565b60068301612452565b610a48610a3f61018460243501612415565b6006830161247b565b610a63610a5a6101a460243501612415565b600683016124a4565b6001600160401b03610a7a6024356101c401612415565b1660018060401b0319600783015416176007820155610aaa610aa16101e460243501612415565b60078301612452565b610ac5610abc61020460243501612415565b6007830161247b565b6001600160681b03610adc602435610224016124c7565b1660018060681b0319600883015416176008820155610b0c610b03610244602435016124c7565b600883016124db565b6001600160681b03610b23602435610264016124c7565b16600982019060018060681b0319825416179055602219602435360301610284602435013512156102905760243561028481013501906001600160401b036004830135116102905760e06004830135023603602483011361029057600160401b60048301351161034157600a81018054600484013591829055908111610ee8575b50600a01600090815260208120602483015b60048401358310610ec5578585610bd8604051916040835260408301906121ad565b8181036020830152916001600160a01b03610bf760046024350161210e565b1683526001600160a01b03610c0f602480350161210e565b1660208401526001600160a01b03610c2b60243560440161210e565b1660408401526001600160a01b03610c4760243560640161210e565b1660608401526001600160a01b03610c6360243560840161210e565b1660808401526001600160401b03610c7f60243560a401612122565b1660a08401526001600160401b03610c9b60243560c401612122565b1660c08401526001600160401b03610cb760243560e401612122565b1660e08401526001600160401b03610cd460243561010401612122565b166101008401526001600160401b03610cf260243561012401612122565b166101208401526001600160401b03610d1060243561014401612122565b166101408401526001600160401b03610d2e60243561016401612122565b166101608401526001600160401b03610d4c60243561018401612122565b166101808401526001600160401b03610d6a6024356101a401612122565b166101a08401526001600160401b03610d886024356101c401612122565b166101c08401526001600160401b03610da66024356101e401612122565b166101e08401526001600160401b03610dc460243561020401612122565b166102008401526001600160681b03610de260243561022401612136565b166102208401526001600160681b03610e0060243561024401612136565b166102408401526001600160681b03610e1e60243561026401612136565b166102608401526024356102846024350135016024600482013591019360018060401b0382116102905760e082023603851361029057806102a06102806102c0930152826102a082015201939060005b818110610ea7576001600160a01b0384167f11750c0169cdcebd42703782ec1a557a8ddebc9c3239aaf46662cd6c81cdb90b86880387a2005b90919460e08082610eba6001948a612671565b019601929101610e6e565b6001600360e083610eda600495600088612579565b019301930192919050610bb6565b610ef3906003612504565b610f0260048401356003612504565b90600a830160005260206000209182015b8183018110610f23575050610ba4565b80600060039255600060018201556000600282015501610f13565b604051630735e0fd60e51b8152600490fd5b90506001600160a01b03610f68602435604401612401565b1614801590610f78575b83610867565b506101c08101516001600160401b0390811690610f9a6024356101c401612415565b161415610f72565b34610290576020366003190112610290576001600160a01b0360043581811690819003610290576002549182169081330361027f576001600160a01b0319909216821760025560405160009290917f6fadb1c244276388aee22be93b919985a18748c021e5d48553957a48101a25608484a3f35b34610290576060366003190112610290576001600160a01b036004358181169081810361029057602435908382169384830361029057604435916001600160401b039182841684036102905760025416330361027f578260016110d86110a07f14bba7d3df0797b2f5143e4f2087f29fcd3ee3ec3197d38a7f77f85dc0d0ec639761026b95612775565b948860005282602052826110bb87600a604060002001612743565b50015460a81c16948860005282602052600a604060002001612743565b500161252d565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b039060243590828216908183036102905760025416330361027f576000848152600160205260409081902060060180546001600160401b031981169093179055517fe5d8ea5f9f9bc1e3132e593561d5b440062de5e0d5585a7046c87ca172a60d4693909283926103f592168361270f565b34610290576060366003190112610290576001600160a01b036004358181169081810361029057602435908382169384830361029057604435906001600160801b038216908183036102905760025416330361027f576112486112057f561b42b6b7ded5005c55634f0a6bd24d306cb04b04533bab7e1a644b6724548695604095612775565b9286600052600160205260026112418161122587600a8a60002001612743565b50015460801c95896000526001602052600a8860002001612743565b5001612556565b82519182526020820152a3005b3461029057610100366003190112610290576001600160a01b03600435818116918282036102905760e0366023190112610290578060025416330361027f576024359081168103610290576112ce6101c0917ff0d2e933bc5a83ab653c27f5ae312ee5f4a394a45c34bb90e8c790bf0ed3834193612775565b83600052600160205261131060246103076112f96112f385600a604060002001612743565b50612334565b93876000526001602052600a604060002001612743565b61131d604051809261214a565b61033e60e082016024612671565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160681b03906024359082821682036102905760025416330361027f57600083815260016020526040902060080180547f2cc4a6aedb45911a1034b2320f16567fa4e2eca3f1f5d3b46804f6bc42b7c3f29360689190911c16906113ba9083906124db565b6103f560405192839283612729565b34610290576040366003190112610290576004356001600160a01b038181169182900361029057602435906001600160401b03821682036102905760025416330361027f57600082815260016020526040902060060180547f864cdb8aef050e3718f73f8f3512418f04745083156b40523b128e79b411fc2d929160c09190911c906103e69083906124a4565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f57600083815260016020526040902060070180547fcd38d79accad9a0b2cec7a7f94a4ceb7d9b0df5f35bdcb6ee4212b695fad0aa19360809190911c16906103e690839061247b565b34610290576040366003190112610290576001600160a01b0360043581811681036102905760243591821682036102905760209161152291612775565b604051908152f35b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f57600082815260016020819052604080832090910180546001600160a01b0319811685179091559051919491939116907fb60cc4e8fd32e3f131099a821d4716afdb1e906f90421b5edb21070d209d0ee28585a4f35b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160681b039060243590828216908183036102905760025416330361027f576000848152600160205260409081902060090180546001600160681b031981169093179055517f0fcb429b7790258a8e50ab0f30505a67d74d6571119febb9690e6264594e2e2993909283926103f5921683612729565b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f5760008281526001602052604080822080546001600160a01b0319811685179091559051919491939116907f54b27c9d187943783592d79e0380d54f9a545d098bd921e5919d4b3305bd603f8585a4f35b34610290576060366003190112610290576004356001600160a01b038082169081830361029057602435908082169384830361029057604435916001600160401b0391828416918285036102905760025416330361027f576117ac6117757fbdfea73f1d581ded04f608d47cd124146963b03795e30c9f9e16d57bb1fed65296600293612775565b938760005260016020528261179186600a604060002001612743565b5001541693876000526001602052600a604060002001612743565b500180546001600160401b031916909117905560405191829161027a91908361270f565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f57600083815260016020526040902060060180547f7e237d05d262a573a6b2d126c2065264a3bcabb68e67a1d5a1e88b1dbef6666d9360809190911c16906103e690839061247b565b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f5760008281526003602052604080822080546001600160a01b0319811685179091559051919491939116907fcc826d20934cb90e9329d09ff55b4e43831c5bb3a3305fb536842ad49041e7d58585a4f35b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f576000838152600160205260409081902060050180547f9fd77f9236bc26e7c30eaa679ccff4200f9a813e5950b2904c29f11d0b5f2a5e94921c909116906103e6908390612452565b34610290576040366003190112610290576004356001600160a01b038181169182900361029057602435906001600160401b03821682036102905760025416330361027f57600082815260016020526040902060050180547fe4e8221220a251ab6772c13e04f6c54532602ec260a26f48ff23fa8b11f41be7929160c09190911c906103e69083906124a4565b34610290576000366003190112610290576020600054604051908152f35b34610290576020366003190112610290576004356001600160a01b0381168103610290576001600160a01b0381811660009081526003602081815260408084205460018084528286208351632d52643960e01b8152600480820187905282548a166024830152928201548916604482015260028201548916606482015295810154881660848701529081015480881660a487015260a01c6001600160401b0390811660c4870152600582015480821660e488015280851c8216610104880152608081811c831661012489015260c091821c61014489015260068401548084166101648a015280871c84166101848a015280821c84166101a48a015290911c6101c488015260078301548083166101e48901529485901c82166102048801529390931c90921661022485015260088201546001600160681b0380821661024487015260689190911c81166102648601526009830154166102848501526102a06102a4850152600a90910180546102c48501819052908552918420929594169285926102e484019290915b818110611c6657505050918160008160209503925af18015611c5a57600090611c15575b60405160209350916001600160a01b03918216918291167f3da528dfe78562a1f409134989443b5f21ee92023a64b90dedeb2002415189b6600085a38152f35b50906020813d602011611c52575b81611c3060209383612311565b810103126102905751906001600160a01b038216820361029057602091611bd5565b3d9150611c23565b6040513d6000823e3d90fd5b82546001600160a01b039081168552600180850154918216602087015260a082811c60ff1660408089019190915260a89390931c6001600160401b03908116606089015260028701548082166080808b01919091529481901c9091169188019190915290911c60c086015288955060e09094019360039093019201611bb1565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b039060243590828216908183036102905760025416330361027f576000848152600160205260409081902060050180546001600160401b031981169093179055517fc936b3eb07b584b686d11042214266fed11036dbc226159d67b3cfaa4ce26f7893909283926103f592168361270f565b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f57600083815260016020526040902060050180547f56027dd4756fabe0c40c7de2c732b95d170796feaf975883a17a087b3718e6b99360809190911c16906103e690839061247b565b34610290576020366003190112610290576004356001600160a01b0381811691829003610290576020916000526003825260406000205416604051908152f35b34610290576040366003190112610290576001600160a01b036004358181169081900361029057602435828116809103610290578260025416330361027f5760008281526001602052604080822060040180546001600160a01b0319811685179091559051919491939116907fc86eba353c79b422cdb4d71fcc7db3615603457a42c0559fcf1b31dfd66920b38585a4f35b34610290576060366003190112610290576001600160a01b0360043581811690818103610290576024358381169384820361029057604435818116809103610290578160025416330361027f576001611f99611f666040957f1736faf0e37344d44b8757867808a35e1d4961804de8c3dec2896bf1c1d6fc5197612775565b93876000528260205282611f8086600a8960002001612743565b50015416938760005282602052600a8660002001612743565b500180546001600160a01b0319168217905582519182526020820152a3005b34610290576040366003190112610290576004356001600160a01b0381811691829003610290576001600160401b03906024359082821682036102905760025416330361027f576000838152600160205260409081902060070180547faf80475c4b413d347b2ac9b71b6c734ba09a6f4771aba12edc65346cffe273f594921c909116906103e6908390612452565b34610290576000366003190112610290576002546040516001600160a01b039091168152602090f35b34610290576040366003190112610290576004356001600160a01b038181169182900361029057602435906001600160401b039081831683036102905760025416330361210057600083815260016020526040902060040180547f35ebb489f572b08259fa0a007e62d8390043159fcf4a6c9a517dd1eb4dc77dfc939260a09190911c16906103e6908390612429565b6282b42960e81b8452600484fd5b35906001600160a01b038216820361029057565b35906001600160401b038216820361029057565b35906001600160681b038216820361029057565b60c09060018060a01b03808251168452602082015116602084015260ff604082015116604084015260018060401b0380606083015116606085015280608083015116608085015260a08201511660a08401528160018060801b0391015116910152565b906102a0908181019060018060a01b038085511682526102c0602092828493848901511684830152806040890151166040830152806060890151166060830152608088015116608082015260018060401b03958660a08901511660a08301528660c08901511660c083015260e09680888a0151168884015261010081818b0151169084015261012081818b0151169084015261014081818b0151169084015261016081818b0151169084015261018081818b015116908401526101a081818b015116908401526101c081818b015116908401526101e081818b0151169084015261020090818a0151169083015260018060681b0361022081818b0151169084015261024081818b0151169084015261026090818a0151169083015261028080980151978201528651809552019401926000905b8382106122ef57505050505090565b90919293948382826123046001948a5161214a565b01960194939201906122e0565b601f909101601f19168101906001600160401b0382119082101761034157604052565b9060405161234360e082612311565b60c08193600260018060a01b03918281541685526001810154928316602086015260ff8360a01c16604086015260018060401b03809360a81c16606086015201549080821660808501528160401c1660a084015260801c910152565b80549091906001600160401b038111610341576040519260206123c7818460051b0186612311565b82855260009182528082208186015b8484106123e4575050505050565b6003836001926123f385612334565b8152019201930192906123d6565b356001600160a01b03811681036102905790565b356001600160401b03811681036102905790565b8054600160a01b600160e01b03191660a09290921b600160a01b600160e01b0316919091179055565b8054600160401b600160801b03191660409290921b600160401b600160801b0316919091179055565b8054600160801b600160c01b03191660809290921b600160801b600160c01b0316919091179055565b80546001600160c01b031660c09290921b6001600160c01b031916919091179055565b356001600160681b03811681036102905790565b8054600160681b600160d01b03191660689290921b600160681b600160d01b0316919091179055565b8060001904821181151516612517570290565b634e487b7160e01b600052601160045260246000fd5b8054600160a81b600160e81b03191660a89290921b600160a81b600160e81b0316919091179055565b80546001600160801b031660809290921b6001600160801b031916919091179055565b9061265b576001600160a01b038061259084612401565b169160018060a01b0319928382541617815560018101916125b360208601612401565b169182815494851617815560408501359060ff821682036102905760c0946002946126029360ff60a01b9060a01b169160018060a81b031916171781556125fc60608701612415565b9061252d565b01916001600160401b0361261860808301612415565b84546001600160401b031916911617835561263e61263860a08301612415565b84612452565b01356001600160801b03811681036102905761265991612556565b565b634e487b7160e01b600052600060045260246000fd5b6001600160a01b03806126838361210e565b1683526126926020830161210e565b16602083015260408101359060ff821680920361029057604083019190915260c0906001600160401b03806126c960608401612122565b166060850152806126dc60808401612122565b1660808501526126ee60a08301612122565b1660a084015201356001600160801b03811691908290036102905760c00152565b6001600160401b0391821681529116602082015260400190565b6001600160681b0391821681529116602082015260400190565b805482101561275f576000526003602060002091020190600090565b634e487b7160e01b600052603260045260246000fd5b9160009160018060a01b038094168352600193602085815261279c600a604087200161239f565b805195805b8781106127ba576040516367fa94e760e01b8152600490fd5b82518110156127ea5784848260051b850101515116858716146127de5788016127a1565b96505050505050915090565b634e487b7160e01b82526032600452602482fdfea26469706673582212205eccb8079963c94e22fd1f7a24f41150ee3776499efdad8d3f5e6e6472c30a4e64736f6c634300080f0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MNT
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.