Source Code
Overview
MON Balance
MON Value
$0.00Latest 10 from a total of 10 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Remove Asset | 40850015 | 46 days ago | IN | 0 MON | 0.01938408 | ||||
| Set Guarded Pric... | 37832760 | 60 days ago | IN | 0 MON | 0.01483127 | ||||
| Add Asset | 37832749 | 60 days ago | IN | 0 MON | 0.01542437 | ||||
| Add Asset | 37832691 | 60 days ago | IN | 0 MON | 0.02409745 | ||||
| Set Guarded Pric... | 37832606 | 60 days ago | IN | 0 MON | 0.02305566 | ||||
| Add Asset | 37832595 | 60 days ago | IN | 0 MON | 0.01839103 | ||||
| Set Guarded Pric... | 37832463 | 60 days ago | IN | 0 MON | 0.07858785 | ||||
| Add Asset | 37832451 | 60 days ago | IN | 0 MON | 0.0221574 | ||||
| Set Guarded Pric... | 37832405 | 60 days ago | IN | 0 MON | 0.02103027 | ||||
| Add Asset | 37832395 | 60 days ago | IN | 0 MON | 0.02191473 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ChainlinkAdaptor
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity)
/**
*Submitted for verification at monadscan.com on 2025-11-25
*/
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.28;
// contracts/libraries/ConstantsLib.sol
/// @dev Scalar for math. `WAD` * `WAD`.
uint256 constant WAD_SQUARED = 1e36;
/// @dev Scalar for math. `WAD` * `WAD` / `BPS`.
/// 1e18 * 1e18 / 1e4
uint256 constant WAD_SQUARED_BPS_OFFSET = 1e32;
/// @dev Scalar for math. Increased precision when WAD is insufficient
/// but WAD_SQUARED runs the risk of overflow.
uint256 constant RAY = 1e27;
/// @dev Scalar for math. `WAD` * `BPS`.
uint256 constant WAD_BPS = 1e22;
/// @dev Scalar for math. Base precision matching ether.
uint256 constant WAD = 1e18;
/// @dev Scalar for math. Represents basis points typically used in TradFi.
uint256 constant BPS = 1e4;
/// @dev Return value indicating no price returned at all.
uint256 constant BAD_SOURCE = 2;
/// @dev Return value indicating price divergence or a missing price feed.
uint256 constant CAUTION = 1;
/// @dev Return value indicating no price error.
uint256 constant NO_ERROR = 0;
/// @dev Extra time added to top end Oracle feed heartbeat incase of
/// transaction congestion delaying an update.
uint256 constant HEARTBEAT_GRACE_PERIOD = 120;
/// @dev Unix time has 31,536,000 seconds per year.
/// All my homies hate leap seconds and leap years.
uint256 constant SECONDS_PER_YEAR = 31_536_000;
// contracts/libraries/external/FixedPointMathLib.sol
/// @notice Arithmetic library with operations for fixed-point numbers.
/// @dev Reduced function scope from full FixedPointMathLib library to only what is needed for Curvance.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
library FixedPointMathLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.
error MulDivFailed();
/// @dev The full precision multiply-divide operation failed, either due
/// to the result being larger than 256 bits, or a division by a zero.
error FullMulDivFailed();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* GENERAL NUMBER UTILITIES */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Calculates `floor(x * y / d)` with full precision.
/// Throws if result overflows a uint256 or when `d` is zero.
/// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv
function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
/// @solidity memory-safe-assembly
assembly {
for {} 1 {} {
// 512-bit multiply `[p1 p0] = x * y`.
// Compute the product mod `2**256` and mod `2**256 - 1`
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that `product = p1 * 2**256 + p0`.
// Least significant 256 bits of the product.
result := mul(x, y) // Temporarily use `result` as `p0` to save gas.
let mm := mulmod(x, y, not(0))
// Most significant 256 bits of the product.
let p1 := sub(mm, add(result, lt(mm, result)))
// Handle non-overflow cases, 256 by 256 division.
if iszero(p1) {
if iszero(d) {
mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
revert(0x1c, 0x04)
}
result := div(result, d)
break
}
// Make sure the result is less than `2**256`. Also prevents `d == 0`.
if iszero(gt(d, p1)) {
mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
revert(0x1c, 0x04)
}
/*------------------- 512 by 256 division --------------------*/
// Make division exact by subtracting the remainder from `[p1 p0]`.
// Compute remainder using mulmod.
let r := mulmod(x, y, d)
// `t` is the least significant bit of `d`.
// Always greater or equal to 1.
let t := and(d, sub(0, d))
// Divide `d` by `t`, which is a power of two.
d := div(d, t)
// Invert `d mod 2**256`
// Now that `d` is an odd number, it has an inverse
// modulo `2**256` such that `d * inv = 1 mod 2**256`.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, `d * inv = 1 mod 2**4`.
let inv := xor(2, mul(3, d))
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64
inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128
result :=
mul(
// Divide [p1 p0] by the factors of two.
// Shift in bits from `p1` into `p0`. For this we need
// to flip `t` such that it is `2**256 / t`.
or(
mul(sub(p1, gt(r, result)), add(div(sub(0, t), t), 1)),
div(sub(result, r), t)
),
// inverse mod 2**256
mul(inv, sub(2, mul(d, inv)))
)
break
}
}
}
/// @dev Calculates `floor(x * y / d)` with full precision, rounded up.
/// Throws if result overflows a uint256 or when `d` is zero.
/// Credit to Uniswap-v3-core under MIT license:
/// https://github.com/Uniswap/v3-core/blob/contracts/libraries/FullMath.sol
function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {
result = fullMulDiv(x, y, d);
/// @solidity memory-safe-assembly
assembly {
if mulmod(x, y, d) {
result := add(result, 1)
if iszero(result) {
mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Returns `floor(x * y / d)`.
/// Reverts if `x * y` overflows, or `d` is zero.
function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
mstore(0x00, 0xad251c27) // `MulDivFailed()`.
revert(0x1c, 0x04)
}
z := div(mul(x, y), d)
}
}
/// @dev Returns `ceil(x * y / d)`.
/// Reverts if `x * y` overflows, or `d` is zero.
function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))
if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {
mstore(0x00, 0xad251c27) // `MulDivFailed()`.
revert(0x1c, 0x04)
}
z := add(iszero(iszero(mod(mul(x, y), d))), div(mul(x, y), d))
}
}
/// @dev Returns the square root of `x`.
function sqrt(uint256 x) internal pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
// `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`.
z := 181 // The "correct" value is 1, but this saves a multiplication later.
// This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
// start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.
// Let `y = x / 2**r`. We check `y >= 2**(k + 8)`
// but shift right by `k` bits to ensure that if `x >= 256`, then `y >= 256`.
let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x))
r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x))))
r := or(r, shl(5, lt(0xffffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffffff, shr(r, x))))
z := shl(shr(1, r), z)
// Goal was to get `z*z*y` within a small factor of `x`. More iterations could
// get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`.
// We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small.
// That's not possible if `x < 256` but we can just verify those cases exhaustively.
// Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`.
// Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`.
// Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps.
// For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)`
// is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`,
// with largest error when `s = 1` and when `s = 256` or `1/256`.
// Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`.
// Then we can estimate `sqrt(y)` using
// `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`.
// There is no overflow risk here since `y < 2**136` after the first branch above.
z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181.
// Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
// If `x+1` is a perfect square, the Babylonian method cycles between
// `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor.
// See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
z := sub(z, lt(div(x, z), z))
}
}
}
// contracts/interfaces/ICentralRegistry.sol
/// TYPES ///
/// @notice Configuration data for a separately supported blockchain.
/// @param isSupported Whether the chain is supported or not.
/// @param messagingChainId Messaging Chain ID where this address authorized.
/// @param domain Domain for the chain.
/// @param messagingHub Messaging Hub address on the chain.
/// @param votingHub Voting Hub address on the chain.
/// @param cveAddress CVE address on the chain.
/// @param feeTokenAddress Fee token address on the chain.
/// @param crosschainRelayer Crosschain relayer address on the chain.
struct ChainConfig {
bool isSupported;
uint16 messagingChainId;
uint32 domain;
address messagingHub;
address votingHub;
address cveAddress;
address feeTokenAddress;
address crosschainRelayer;
}
interface ICentralRegistry {
/// @notice The length of one protocol epoch, in seconds.
function EPOCH_DURATION() external view returns (uint256);
/// @notice Sequencer uptime oracle on this chain (for L2s).
function SEQUENCER_ORACLE() external view returns (address);
/// @notice Returns Genesis Epoch Timestamp of Curvance.
function genesisEpoch() external view returns (uint256);
/// @notice Returns Protocol DAO address.
function daoAddress() external view returns (address);
/// @notice Returns Protocol Emergency Council address.
function emergencyCouncil() external view returns (address);
/// @notice Indicates if address has DAO permissions or not.
function hasDaoPermissions(
address addressToCheck
) external view returns (bool);
/// @notice Indicates if address has elevated DAO permissions or not.
function hasElevatedPermissions(
address addressToCheck
) external view returns (bool);
/// @notice Indicates if address has lock creation permissions or not.
function hasLockingPermissions(
address addressToCheck
) external view returns (bool);
/// @notice Indicates if address has auction permissions or not.
function hasAuctionPermissions(
address addressToCheck
) external view returns (bool);
/// @notice Indicates if address has market permissions or not.
function hasMarketPermissions(
address addressToCheck
) external view returns (bool);
/// @notice Indicates if address has harvest permissions or not.
function hasHarvestPermissions(
address addressToCheck
) external view returns (bool);
/// @notice Returns Reward Manager address.
function rewardManager() external view returns (address);
/// @notice Returns Gauge Manager address.
function gaugeManager() external view returns (address);
/// @notice Returns CVE address.
function cve() external view returns (address);
/// @notice Returns veCVE address.
function veCVE() external view returns (address);
/// @notice Returns Voting Hub address.
function votingHub() external view returns (address);
/// @notice Returns Messaging Hub address.
function messagingHub() external view returns (address);
/// @notice Returns Oracle Manager address.
function oracleManager() external view returns (address);
/// @notice Returns Fee Manager address.
function feeManager() external view returns (address);
/// @notice Returns Fee Token address.
function feeToken() external view returns (address);
/// @notice Returns Crosschain Core contract address.
function crosschainCore() external view returns (address);
/// @notice Returns Crosschain Relayer contract address.
function crosschainRelayer() external view returns (address);
/// @notice Returns Token Messenger contract address.
function tokenMessager() external view returns (address);
/// @notice Returns Messenger Transmitter contract address.
function messageTransmitter() external view returns (address);
/// @notice Returns domain value.
function domain() external view returns (uint32);
/// @notice Returns protocol gas fee on harvest, in `BPS`.
function protocolCompoundFee() external view returns (uint256);
/// @notice Returns protocol yield fee on strategy harvest, in `BPS`.
function protocolYieldFee() external view returns (uint256);
/// @notice Returns protocol yield + gas fee on strategy harvest,
/// in `BPS`.
function protocolHarvestFee() external view returns (uint256);
/// @notice Returns protocol fee on leverage actions, in `BPS`.
function protocolLeverageFee() external view returns (uint256);
/// @notice Returns default fee on interest generated from active loans,
/// in `BPS`.
function defaultProtocolInterestFee() external view returns (uint256);
/// @notice Returns earlyUnlockPenaltyMultiplier value, in `BPS`.
function earlyUnlockPenaltyMultiplier() external view returns (uint256);
/// @notice Returns voteBoostMultiplier value, in `BPS`.
function voteBoostMultiplier() external view returns (uint256);
/// @notice Returns lockBoostMultiplier value, in `BPS`.
function lockBoostMultiplier() external view returns (uint256);
/// @notice Returns swap slippage limit, in `BPS`.
function slippageLimit() external view returns (uint256);
/// @notice Returns an array of Chain IDs recorded in the Crosschain
/// Protocol's Chain ID format.
function foreignChainIds() external view returns (uint256[] memory);
/// @notice Returns an array of Curvance markets on this chain.
function marketManagers() external view returns (address[] memory);
/// @notice Increments a caller's approval index.
/// @dev By incrementing their approval index, a user's delegates will all
/// have their delegation authority revoked across all Curvance
/// contracts.
/// Emits an {ApprovalIndexIncremented} event.
function incrementApprovalIndex() external;
/// @notice Returns `user`'s approval index.
/// @param user The user to check approval index for.
function userApprovalIndex(address user) external view returns (uint256);
/// @notice Returns whether a user has delegation disabled.
/// @param user The user to check delegation status for.
function checkNewDelegationDisabled(
address user
) external view returns (bool);
/// @notice Returns whether a particular GETH chainId is supported.
/// ChainId => messagingHub address, 2 = supported; 1 = unsupported.
function chainConfig(
uint256 chainId
) external view returns (ChainConfig memory);
/// @notice Returns the GETH chainId corresponding chainId corresponding
/// to Crosschain Messaging Protocol's `chainId`.
/// @param chainId The Crosschain Messaging Protocol's chainId.
/// @return The GETH chainId corresponding chainId corresponding to
/// Crosschain Messaging Protocol's `chainId`.
function messagingToGETHChainId(
uint16 chainId
) external view returns (uint256);
/// @notice Returns the Crosschain Messaging Protocol's ChainId
/// corresponding to the GETH `chainId`.
/// @param chainId The GETH chainId.
/// @return The Crosschain Messaging Protocol's ChainId
/// corresponding to the GETH `chainId`.
function GETHToMessagingChainId(
uint256 chainId
) external view returns (uint256);
/// @notice Indicates if an address is a market manager or not.
function isMarketManager(
address addressToCheck
) external view returns (bool);
/// @notice Maps an intent target address to the contract that will
/// inspect provided external calldata.
function externalCalldataChecker(
address addressToCheck
) external view returns (address);
/// @notice Maps a Multicall target address to the contract that will
/// inspect provided multicall calldata.
function multicallChecker(
address addressToCheck
) external view returns (address);
/// @notice Indicates the amount of token rewards allocated on this chain,
/// for an epoch.
function emissionsAllocatedByEpoch(
uint256 epoch
) external view returns (uint256);
/// @notice Indicates the amount of token rewards allocated across all
/// chains, for an era. An era is a particular period in time in
/// which rewards are constant, before a halvening event moves the
/// protocol to a new era.
function targetEmissionAllocationByEra(
uint256 era
) external view returns (uint256);
/// @notice Unlocks a market to process auction-based liquidations.
/// @param marketToUnlock The address of the market manager to unlock
/// auction-based liquidations with a specific
/// liquidation bonus.
function unlockAuctionForMarket(address marketToUnlock) external;
/// @notice Checks if a market is unlocked for auction operations.
/// @return Whether the caller is an unlocked market, approved for
/// auction-based liquidations.
function isMarketUnlocked() external view returns (bool);
/// @notice Sets the amount of token rewards allocated on this chain,
/// for an epoch.
/// @dev Only callable by the Voting Hub.
/// @param epoch The epoch having its token emission values set.
/// @param emissionsAllocated The amount of token rewards allocated on
/// this chain, for an epoch.
function setEmissionsAllocatedByEpoch(
uint256 epoch,
uint256 emissionsAllocated
) external;
/// @notice Checks whether `user` has transferability enabled or disabled
/// for their tokens.
/// @dev This is inherited from ActionRegistry portion of centralRegistry.
/// @param user The address to check whether transferability is enabled or
/// disabled for.
/// @return result Indicates whether `user` has transferability disabled
/// or not, true = disabled, false = not disabled.
function checkTransfersDisabled(
address user
) external view returns (bool result);
}
// contracts/interfaces/external/chainlink/IChainlink.sol
interface IChainlink {
/// @notice Returns the number of decimals the aggregator responds with.
function decimals() external view returns (uint8);
/// @notice Returns the latest oracle data from the aggregator.
/// @return roundId The round ID from the aggregator for which the data
/// was retrieved.
/// answer The price returned by the aggregator.
/// startedAt The timestamp the current round was started.
/// updatedAt The timestamp the current round last was updated.
/// answeredInRound The round ID of the round in which `answer`
/// was computed.
function latestRoundData() external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
/// @notice Returns the latest roundID the aggregator responds with.
function latestRound() external view returns (uint256);
function getRoundData(uint80 _roundId) external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
// contracts/interfaces/IDynamicIRM.sol
interface IDynamicIRM {
/// @notice Returns the interval at which interest rates are adjusted.
/// @notice The interval at which interest rates are adjusted,
/// in seconds.
function ADJUSTMENT_RATE() external view returns (uint256);
/// @notice The borrowable token linked to this interest rate model
/// contract.
function linkedToken() external view returns (address);
/// @notice Calculates the current borrow rate, per second.
/// @dev This function's intention is for frontend data querying and
/// should not be used for onchain execution.
/// @param assetsHeld The amount of underlying assets held in the pool.
/// @param debt The amount of outstanding debt in the pool.
/// @return result The borrow interest rate percentage, per second,
/// in `WAD`.
function borrowRate(
uint256 assetsHeld,
uint256 debt
) external view returns (uint256 result);
/// @notice Calculates the current borrow rate per second,
/// with updated vertex multiplier applied.
/// @param assetsHeld The amount of underlying assets held in the pool.
/// @param debt The amount of outstanding debt in the pool.
/// @return result The borrow rate percentage per second, in `WAD`.
function predictedBorrowRate(
uint256 assetsHeld,
uint256 debt
) external view returns (uint256 result);
/// @notice Calculates the current supply rate, per second.
/// @dev This function's intention is for frontend data querying and
/// should not be used for onchain execution.
/// @param assetsHeld The amount of underlying assets held in the pool.
/// @param debt The amount of outstanding debt in the pool.
/// @param interestFee The current interest rate protocol fee
/// for the market token.
/// @return result The supply interest rate percentage, per second,
/// in `WAD`.
function supplyRate(
uint256 assetsHeld,
uint256 debt,
uint256 interestFee
) external view returns (uint256 result);
/// @notice Calculates the interest rate paid per second by borrowers,
/// in percentage paid, per second, in `WAD`, and updates
/// `vertexMultiplier` if necessary.
/// @param assetsHeld The amount of underlying assets held in the pool.
/// @param debt The amount of outstanding debt in the pool.
/// @return ratePerSecond The interest rate paid per second by borrowers,
/// in percentage paid, per second, in `WAD`.
/// @return adjustmentRate The period of time at which interest rates are
/// adjusted, in seconds.
function adjustedBorrowRate(
uint256 assetsHeld,
uint256 debt
) external returns (uint256 ratePerSecond, uint256 adjustmentRate);
/// @notice Calculates the borrow utilization rate of the market.
/// @param assetsHeld The amount of underlying assets held in the pool.
/// @param outstandingDebt The amount of outstanding debt in the pool.
/// @return The utilization rate between [0, WAD].
function utilizationRate(
uint256 assetsHeld,
uint256 outstandingDebt
) external view returns (uint256);
}
// contracts/interfaces/IERC165.sol
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(
bytes4 interfaceId
) external view returns (bool);
}
// contracts/interfaces/IERC20.sol
// @dev Interface of the ERC20 standard
interface IERC20 {
// @dev Returns the name of the token.
function name() external view returns (string memory);
// @dev Returns the symbol of the token.
function symbol() external view returns (string memory);
// @dev Returns the decimals of the token.
function decimals() external view returns (uint8);
// @dev Emitted when `value` tokens are moved from one account (`from`) to
// another (`to`).
// Note that `value` may be zero.
event Transfer(address indexed from, address indexed to, uint256 value);
// @dev Emitted when the allowance of a `spender` for an `owner` is set by
// a call to {approve}. `value` is the new allowance.
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
// @dev Returns the amount of tokens in existence.
function totalSupply() external view returns (uint256);
// @dev Returns the amount of tokens owned by `account`.
function balanceOf(address account) external view returns (uint256);
// @dev Moves `amount` tokens from the caller's account to `to`.
// Returns a boolean value indicating whether the operation succeeded.
// Emits a {Transfer} event.
function transfer(address to, uint256 amount) external returns (bool);
// @dev Moves `amount` tokens from `from` to `to` using the
// allowance mechanism. `amount` is then deducted from the caller's
// allowance.
// Returns a boolean value indicating whether the operation succeeded.
// Emits a {Transfer} event.
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
// @dev Returns the remaining number of tokens that `spender` will be
// allowed to spend on behalf of `owner` through {transferFrom}. This
// is zero by default.
function allowance(
address owner,
address spender
) external view returns (uint256);
// @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
// Returns a boolean value indicating whether the operation succeeded.
// IMPORTANT: Beware that changing an allowance with this method brings the risk
// that someone may use both the old and the new allowance by unfortunate
// transaction ordering. One possible solution to mitigate this race
// condition is to first reduce the spender's allowance to 0 and set the
// desired value afterwards:
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
// Emits an {Approval} event.
function approve(address spender, uint256 amount) external returns (bool);
}
// contracts/interfaces/IMarketManager.sol
interface IMarketManager {
/// TYPES ///
/// @notice Data structure passed communicating the intended liquidation
/// scenario to review based on current liquidity levels.
/// @param collateralToken The token which was used as collateral
/// by `account` and may be seized.
/// @param debtToken The token to potentially repay which has
/// outstanding debt by `account`.
/// @param numAccounts The number of accounts to be, potentially,
/// liquidated.
/// @param liquidateExact Whether the liquidator desires a specific
/// liquidation amount.
/// @param liquidatedShares Empty variable slot to store how much
/// `collateralToken` will be seized as
/// part of a particular liquidation.
/// @param debtRepaid Empty variable slot to store how much
/// `debtToken` will be repaid as part of a
/// particular liquidation.
/// @param badDebt Empty variable slot to store how much bad debt will
/// be realized by lenders as part of a particular
/// liquidation.
struct LiqAction {
address collateralToken;
address debtToken;
uint256 numAccounts;
bool liquidateExact;
uint256 liquidatedShares;
uint256 debtRepaid;
uint256 badDebt;
}
/// @notice Data structure returned communicating outcome of a liquidity
/// scenario review based on current liquidity levels.
/// @param liquidatedShares An array containing the collateral amounts to
/// liquidate from accounts, in shares.
/// @param debtRepaid The total amount of debt to repay from accounts,
/// in assets.
/// @param badDebtRealized The total amount of debt to realize as losses
/// for lenders, in assets.
struct LiqResult {
uint256[] liquidatedShares;
uint256 debtRepaid;
uint256 badDebtRealized;
}
/// @notice Returns whether minting, collateralization, borrowing of
/// `cToken` is paused.
/// @param cToken The address of the Curvance token to return
/// action statuses of.
/// @return bool Whether minting `cToken` is paused or not.
/// @return bool Whether collateralization `cToken` is paused or not.
/// @return bool Whether borrowing `cToken` is paused or not.
function actionsPaused(
address cToken
) external view returns (bool, bool, bool);
/// @notice Returns the current collateralization configuration
/// of `cToken`.
/// @param cToken The address of the Curvance token to return
/// collateralization configuration of.
/// @return The ratio at which this token can be borrowed against
/// when collateralized.
/// @return The collateral requirement where dipping below this
/// will cause a soft liquidation.
/// @return The collateral requirement where dipping below
/// this will cause a hard liquidation.
function collConfig(address cToken) external view returns (
uint256, uint256, uint256
);
/// @notice Returns the current liquidation configuration
/// of `cToken`.
/// @param cToken The address of the Curvance token to return
/// liquidation configuration of.
/// @return The base ratio at which this token will be
/// compensated on soft liquidation.
/// @return The liquidation incentive curve length between soft
/// liquidation to hard liquidation, in `WAD`. e.g. 5% base
/// incentive with 8% curve length results in 13% liquidation
/// incentive on hard liquidation.
/// @return The minimum possible liquidation incentive for during an
/// auction, in `WAD`.
/// @return The maximum possible liquidation incentive for during an
/// auction, in `WAD`.
/// @return Maximum % that a liquidator can repay when soft
/// liquidating an account, in `WAD`.
/// @return Curve length between soft liquidation and hard liquidation,
/// should be equal to 100% - `closeFactorBase`, in `WAD`.
/// @return The minimum possible close factor for during an auction,
/// in `WAD`.
/// @return The maximum possible close factor for during an auction,
/// in `WAD`.
function liquidationConfig(address cToken) external view returns (
uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256
);
/// @notice Enables an auction-based liquidation, potentially with a dynamic
/// close factor and liquidation penalty values in transient storage.
/// @dev Transient storage enforces any liquidator outside auction-based
/// liquidations uses the default risk parameters.
/// @param cToken The Curvance token to configure liquidations for during
/// an auction-based liquidation.
/// @param incentive The auction liquidation incentive value, in `BPS`.
/// @param closeFactor The auction close factor value, in `BPS`.
function setTransientLiquidationConfig(
address cToken,
uint256 incentive,
uint256 closeFactor
) external;
/// @notice Called from the AuctionManager as a post hook after liquidations
/// are tried to enable all collateral to be liquidated outside
/// an Auction tx.
/// @notice Resets the liquidation risk parameters in transient storage to
/// zero.
/// @dev This is redundant since the transient values will be reset after
/// the liquidation transaction, but can be useful during meta calls
/// with multiple liquidations during a single transaction.
function resetTransientLiquidationConfig() external;
/// @notice Checks if the account should be allowed to mint tokens
/// in the given market.
/// @param cToken The token to verify mints against.
function canMint(address cToken) external;
/// @notice Checks if the account should be allowed to collateralize
/// their shares of the given market.
/// Prunes unused positions in `account` data.
/// @dev May emit a {PositionUpdated} event.
/// @param cToken The token to verify collateralization of.
/// @param account The account which would collateralize the asset.
/// @param newNetCollateral The amount of shares that would be
/// collateralized in total if allowed.
function canCollateralize(
address cToken,
address account,
uint256 newNetCollateral
) external;
/// @notice Checks if the account should be allowed to redeem tokens
/// in the given market, and then redeems.
/// @dev This can only be called by the cToken itself.
/// @param cToken The token to verify the redemption against.
/// @param shares The number of cToken shares to redeem for the
/// underlying asset in the market.
/// @param account The account which would redeem `shares`.
/// @param balanceOf The current cToken share balance of `account`.
/// @param collateralPosted The current cToken shares posted as
/// collateral by `account`.
/// @param forceRedeemCollateral Whether the collateral should be always
/// reduced.
function canRedeemWithCollateralRemoval(
address cToken,
uint256 shares,
address account,
uint256 balanceOf,
uint256 collateralPosted,
bool forceRedeemCollateral
) external returns (uint256);
/// @notice Checks if the account should be allowed to borrow
/// the underlying asset of the given market.
/// Prunes unused positions in `account` data.
/// @dev May emit a {PositionUpdated} event.
/// @param cToken The token to verify borrowability of.
/// @param assets The amount of underlying assets `account` would borrow.
/// @param account The account which would borrow the asset.
/// @param newNetDebt The amount of assets that would be
/// outstanding debt in total if allowed.
function canBorrow(
address cToken,
uint256 assets,
address account,
uint256 newNetDebt
) external;
/// @notice Checks if the account should be allowed to borrow
/// the underlying asset of the given market,
/// and notifies the market of the borrow.
/// @dev This can only be called by the market itself.
/// @param cToken The market to verify the borrow against.
/// @param assets The amount of underlying assets `account` would borrow.
/// @param account The account which would borrow the asset.
/// @param newNetDebt The amount of assets that would be
/// outstanding debt in total if allowed.
function canBorrowWithNotify(
address cToken,
uint256 assets,
address account,
uint256 newNetDebt
) external;
/// @notice Checks if the account should be allowed to repay a borrow
/// in the given market, may clean up positions.
/// @param cToken The Curvance token to verify the repayment of.
/// @param newNetDebt The new debt amount owed by `account` after
/// repayment.
/// @param debtAsset The debt asset being repaid to `cToken`.
/// @param decimals The decimals that `debtToken` is measured in.
/// @param account The account who will have their loan repaid.
function canRepayWithReview(
address cToken,
uint256 newNetDebt,
address debtAsset,
uint256 decimals,
address account
) external;
/// @notice Checks if the liquidation should be allowed to occur,
/// and returns how many collateralized shares should be seized
/// on liquidation.
/// @param debtAmounts The amounts of outstanding debt the liquidator
/// wishes to repay, in underlying assets, empty if
/// intention is to liquidate maximum amount possible
/// for each account.
/// @param liquidator The address of the account trying to liquidate
/// `accounts`.
/// @param accounts The addresses of the accounts to be liquidated.
/// @param action A LiqAction struct containing:
/// collateralToken The token which is used as collateral
/// by `account` and may be seized.
/// debtToken The token to potentially repay which has
/// outstanding debt by `account`.
/// numAccounts The number of accounts to be, potentially,
/// liquidated.
/// liquidateExact Whether the liquidator desires a
/// specific liquidation amount.
/// collateralLiquidated Empty variable slot to store how
/// much `collateralToken` will be
/// seized as part of a particular
/// liquidation.
/// debtRepaid Empty variable slot to store how much
/// `debtToken` will be repaid as part of a
/// particular liquidation.
/// badDebt Empty variable slot to store how much bad debt
/// will be realized as part of a particular
/// liquidation.
/// @return result A LiqResult struct containing:
/// liquidatedShares An array containing the collateral
/// amounts to liquidate from
/// `accounts`.
/// debtRepaid The total amount of debt to repay from
/// `accounts`.
/// badDebtRealized The total amount of debt to realize as
/// losses for lenders inside this market.
/// @return An array containing the debt amounts to repay from
/// `accounts`, in assets.
function canLiquidate(
uint256[] memory debtAmounts,
address liquidator,
address[] calldata accounts,
IMarketManager.LiqAction memory action
) external returns (LiqResult memory, uint256[] memory);
/// @notice Checks if the seizing of `collateralToken` by repayment of
/// `debtToken` should be allowed.
/// @param collateralToken The Curvance token which was used as collateral
/// and will be seized.
/// @param debtToken The Curvance token which has outstanding debt to and
/// would be repaid during `collateralToken` seizure.
function canSeize(address collateralToken, address debtToken) external;
/// @notice Checks if the account should be allowed to transfer collateral
/// tokens in the given market.
/// @param cToken The Curvance token to verify the transfer of.
/// @param shares The amount of `cToken` to transfer.
/// @param account The account which will transfer `shares`.
/// @param balanceOf The current balance that `account` has of `cToken`
/// shares.
/// @param collateralPosted The amount of `cToken` shares posted as
/// collateral by `account`.
/// @param isCollateral Boolean indicating whether the token is currently
/// being used as collateral.
function canTransfer(
address cToken,
uint256 shares,
address account,
uint256 balanceOf,
uint256 collateralPosted,
bool isCollateral
) external returns (uint256);
/// @notice Updates `account` cooldownTimestamp to the current block
/// timestamp.
/// @dev The caller must be a listed cToken in the `markets` mapping.
/// @param cToken The address of the token that the account is borrowing.
/// @param account The address of the account that has just borrowed.
function notifyBorrow(address cToken, address account) external;
/// @notice A list of all tokens inside this market for
/// offchain querying.
function queryTokensListed() external view returns (address[] memory);
/// @notice Returns whether `cToken` is listed in the lending market.
/// @param cToken market token address.
function isListed(address cToken) external view returns (bool);
/// @notice The total amount of `cToken` that can be posted as collateral,
/// in shares.
function collateralCaps(address cToken) external view returns (uint256);
/// @notice The total amount of `cToken` underlying that can be borrowed,
/// in assets.
function debtCaps(address cToken) external view returns (uint256);
/// @notice Returns whether `addressToCheck` is an approved position
/// manager or not.
/// @param addressToCheck Address to check for position management
/// authority.
function isPositionManager(
address addressToCheck
) external view returns (bool);
/// @notice Returns the assets an account has entered.
/// @param account The address of the account to pull assets for.
/// @return A dynamic list with the assets `account` has entered.
function assetsOf(
address account
) external view returns (address[] memory);
/// @notice Determine `account`'s current status between collateral,
/// debt, and additional liquidity.
/// @param account The account to determine liquidity for.
/// @return The current total collateral amount of `account`.
/// @return The maximum debt amount of `account` can take out with
/// their current collateral.
/// @return The current total borrow amount of `account`.
function statusOf(
address account
) external returns (uint256, uint256, uint256);
}
// contracts/interfaces/IMulticallChecker.sol
interface IMulticallChecker {
function checkCalldata(
address caller,
address target,
bytes memory data
) external;
}
// contracts/interfaces/IOracleAdaptor.sol
interface IOracleAdaptor {
/// TYPES ///
/// @notice Return data from pricing an asset.
/// @param price The price of the asset.
/// @param inUsd Boolean indicating whether `price` is denominated
/// in USD (true) or native token (false).
/// @param hadError Boolean indicating whether the asset was priced
/// without running into any issues or not.
struct PricingResult {
uint256 price;
bool inUSD;
bool hadError;
}
/// @notice Guard logic when pricing `asset` configured to prevent oracle
/// mispricing either by mistake or malicious PriceGuard when
/// pricing `asset` denominated either USD or native tokens.
/// @param timestampStart When `increasePerYear` should start increasing
/// `basePrice` raising the maximum price returned
/// when pricing `asset`.
/// @param ips The magnitude that `basePrice` should increase overtime
/// from `timestampStart`, in `WAD`, per second.
/// @param basePrice The base price that should be the maximum price
/// returned when pricing `asset`.
/// @param minPrice The minimum price that should be allowed to be
/// returned when pricing `asset`.
struct PriceGuard {
uint40 timestampStart;
uint40 ips;
uint88 basePrice;
uint88 minPrice;
}
/// @notice Called by OracleManager to price an asset.
/// @param asset The address of the asset for which the price is needed.
/// @param inUSD A boolean to determine if the price should be returned in
/// USD or not.
/// @param getLower A boolean to determine if lower of two oracle prices
/// should be retrieved.
/// @return result Return data for a priced asset containing:
/// price The price of the asset.
/// inUSD Boolean indicating whether `price` is denominated
/// in USD (true) or native token (false).
/// hadError Boolean indicating whether the asset was priced
/// without running into any issues or not.
function getPrice(
address asset,
bool inUSD,
bool getLower
) external view returns (PricingResult memory);
/// @notice Whether an asset is supported by the Oracle Adaptor or not.
/// @dev Asset => Supported by adaptor.
function isSupportedAsset(address asset) external view returns (bool);
/// @notice Token price guard configuration for pricing an asset.
/// @dev Token address => inUSD => Price Guard configuration.
function getPriceGuard(
address asset,
bool inUSD
) external view returns (PriceGuard memory);
/// @notice Returns the adaptor's type.
/// @dev Used by frontends to determine how to properly interact
/// with a supported asset.
function adaptorType() external view returns (uint256);
}
// contracts/libraries/LowLevelCallsHelper.sol
library LowLevelCallsHelper {
/// ERRORS ///
error LowLevelCallsHelper__InsufficientBalance();
error LowLevelCallsHelper__CallFailed();
/// INTERNAL FUNCTIONS ///
/// @notice Executes a low level .call() and validates that execution
/// was safely performed.
/// @dev Bubbles up errors and reverts if anything along the execution
/// path failed or was a red flag.
/// @param target The target contract address to execute .call() at.
/// @param data The bytecode data to attach to the .call() execution
/// including the function signature hash and function call
/// parameters.
function _call(
address target,
bytes memory data
) internal returns (bytes memory) {
(bool success, bytes memory returnData) = target.call{value: 0}(data);
return _verifyResult(target, success, returnData);
}
/// @notice Executes a low level .call(), with attached native token
/// and validates that execution was safely performed.
/// @dev Bubbles up errors and reverts if anything along the execution
/// path failed or was a red flag.
/// @param target The target contract address to execute .call() at.
/// @param data The bytecode data to attach to the .call() execution
/// including the function signature hash and function call
/// parameters.
/// @param value The amount of native token to attach to the low level
/// call.
function _callWithNative(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
if (address(this).balance < value) {
revert LowLevelCallsHelper__InsufficientBalance();
}
(bool success, bytes memory returnData) = target.call{
value: value
}(data);
return _verifyResult(target, success, returnData);
}
/// @notice Executes a low level .delegatecall() and validates that
/// execution was safely performed.
/// @dev Bubbles up errors and reverts if anything along the execution
/// path failed or was a red flag.
/// @param target The target contract address to execute .delegatecall()
/// at.
/// @param data The bytecode data to attach to the .call() execution
/// including the function signature hash and function call
/// parameters.
function _delegateCall(
address target,
bytes memory data
) internal returns (bytes memory) {
(bool success, bytes memory returnData) = target.delegatecall(data);
return _verifyResult(target, success, returnData);
}
/// @dev Validates whether the low level call or delegate call was
/// successful and reverts in cases of bubbled up revert messages
/// or if `target` was not actually a contract.
function _verifyResult(
address target,
bool success,
bytes memory returnData
) internal view returns (bytes memory) {
_propagateError(success, returnData);
// If the call was successful but there was no return data we need
// to make sure a contract was actually called as expected.
if (returnData.length == 0 && target.code.length == 0) {
revert LowLevelCallsHelper__CallFailed();
}
return returnData;
}
/// @dev Propagates an error message, if necessary.
/// @param success If transaction was successful.
/// @param resultData The transaction result data.
function _propagateError(
bool success,
bytes memory resultData
) internal pure {
if (!success) {
if (resultData.length == 0) {
revert LowLevelCallsHelper__CallFailed();
}
// Bubble up error if there was one given.
assembly {
revert(add(32, resultData), mload(resultData))
}
}
}
}
// contracts/libraries/external/SafeTransferLib.sol
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
/// - For ERC20s, this implementation won't check that a token has code,
/// responsibility is delegated to the caller.
library SafeTransferLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ETH transfer has failed.
error ETHTransferFailed();
/// @dev The ERC20 `transferFrom` has failed.
error TransferFromFailed();
/// @dev The ERC20 `transfer` has failed.
error TransferFailed();
/// @dev The ERC20 `approve` has failed.
error ApproveFailed();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;
/// @dev Suggested gas stipend for contract receiving ETH to perform a few
/// storage reads and writes, but low enough to prevent griefing.
uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ETH OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
//
// The regular variants:
// - Forwards all remaining gas to the target.
// - Reverts if the target reverts.
// - Reverts if the current contract has insufficient balance.
//
// The force variants:
// - Forwards with an optional gas stipend
// (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
// - If the target reverts, or if the gas stipend is exhausted,
// creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
// Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
// - Reverts if the current contract has insufficient balance.
//
// The try variants:
// - Forwards with a mandatory gas stipend.
// - Instead of reverting, returns whether the transfer succeeded.
/// @dev Sends `amount` (in wei) ETH to `to`.
function safeTransferETH(address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Sends all the ETH in the current contract to `to`.
function safeTransferAllETH(address to) internal {
/// @solidity memory-safe-assembly
assembly {
// Transfer all the ETH and check if it succeeded or not.
if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
/// @solidity memory-safe-assembly
assembly {
if lt(selfbalance(), amount) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
}
}
}
/// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
/// @solidity memory-safe-assembly
assembly {
if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
}
}
}
/// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
function forceSafeTransferETH(address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
if lt(selfbalance(), amount) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
}
}
}
/// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
function forceSafeTransferAllETH(address to) internal {
/// @solidity memory-safe-assembly
assembly {
// forgefmt: disable-next-item
if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, to) // Store the address in scratch space.
mstore8(0x0b, 0x73) // Opcode `PUSH20`.
mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
}
}
}
/// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
internal
returns (bool success)
{
/// @solidity memory-safe-assembly
assembly {
success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)
}
}
/// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
function trySafeTransferAllETH(address to, uint256 gasStipend)
internal
returns (bool success)
{
/// @solidity memory-safe-assembly
assembly {
success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC20 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
/// Reverts upon failure.
///
/// The `from` account must have at least `amount` approved for
/// the current contract to manage.
function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, amount) // Store the `amount` argument.
mstore(0x40, to) // Store the `to` argument.
mstore(0x2c, shl(96, from)) // Store the `from` argument.
mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
)
) {
mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Sends all of ERC20 `token` from `from` to `to`.
/// Reverts upon failure.
///
/// The `from` account must have their entire balance approved for
/// the current contract to manage.
function safeTransferAllFrom(address token, address from, address to)
internal
returns (uint256 amount)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x40, to) // Store the `to` argument.
mstore(0x2c, shl(96, from)) // Store the `from` argument.
mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
// Read the balance, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x1f), // At least 32 bytes returned.
staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
)
) {
mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
revert(0x1c, 0x04)
}
mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
)
) {
mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot to zero.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
/// Reverts upon failure.
function safeTransfer(address token, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
revert(0x1c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sends all of ERC20 `token` from the current contract to `to`.
/// Reverts upon failure.
function safeTransferAll(address token, address to) internal returns (uint256 amount) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
mstore(0x20, address()) // Store the address of the current contract.
// Read the balance, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x1f), // At least 32 bytes returned.
staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
)
) {
mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
revert(0x1c, 0x04)
}
mstore(0x14, to) // Store the `to` argument.
amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
// Perform the transfer, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
revert(0x1c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
/// Reverts upon failure.
function safeApprove(address token, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
// Perform the approval, reverting upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
revert(0x1c, 0x04)
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
/// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
/// then retries the approval again (some tokens, e.g. USDT, requires this).
/// Reverts upon failure.
function safeApproveWithRetry(address token, address to, uint256 amount) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, to) // Store the `to` argument.
mstore(0x34, amount) // Store the `amount` argument.
mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
// Perform the approval, retrying upon failure.
if iszero(
and( // The arguments of `and` are evaluated from right to left.
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x34, 0) // Store 0 for the `amount`.
mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.
mstore(0x34, amount) // Store back the original `amount`.
// Retry the approval, reverting upon failure.
if iszero(
and(
or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.
call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
)
) {
mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
revert(0x1c, 0x04)
}
}
mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
}
}
/// @dev Returns the amount of ERC20 `token` owned by `account`.
/// Returns zero if the `token` does not exist.
function balanceOf(address token, address account) internal view returns (uint256 amount) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x14, account) // Store the `account` argument.
mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
amount :=
mul(
mload(0x20),
and( // The arguments of `and` are evaluated from right to left.
gt(returndatasize(), 0x1f), // At least 32 bytes returned.
staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
)
)
}
}
}
// contracts/libraries/external/ERC165Checker.sol
// @author Modified from OpenZeppelin Contracts (utils/introspection/ERC165Checker.sol)
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/
library ERC165Checker {
// As per the EIP-165 spec, no interface should ever match 0xffffffff
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
/**
* @dev Returns true if `account` supports the {IERC165} interface.
*/
function supportsERC165(address account) internal view returns (bool) {
// Any contract that implements ERC165 must explicitly indicate support of
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
return
supportsERC165InterfaceUnchecked(
account,
type(IERC165).interfaceId
) &&
!supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/
function supportsInterface(
address account,
bytes4 interfaceId
) internal view returns (bool) {
// query support of both ERC165 as per the spec and support of _interfaceId
return
supportsERC165(account) &&
supportsERC165InterfaceUnchecked(account, interfaceId);
}
/**
* @notice Query if a contract implements an interface, does not check ERC165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
*
* Some precompiled contracts will falsely indicate support for a given interface, so caution
* should be exercised when using this function.
*
* Interface identification is specified in ERC-165.
*/
function supportsERC165InterfaceUnchecked(
address account,
bytes4 interfaceId
) internal view returns (bool) {
// prepare call
bytes memory encodedParams = abi.encodeCall(
IERC165.supportsInterface,
(interfaceId)
);
// perform static call
bool success;
uint256 returnSize;
uint256 returnValue;
assembly {
success := staticcall(
30000,
account,
add(encodedParams, 0x20),
mload(encodedParams),
0x00,
0x20
)
returnSize := returndatasize()
returnValue := mload(0x00)
}
return success && returnSize >= 0x20 && returnValue > 0;
}
}
// contracts/libraries/CentralRegistryLib.sol
/// @title Curvance Central Registry Validation Library
/// @notice For validating that Central Registry is configured properly
/// on launch.
library CentralRegistryLib {
/// ERRORS ///
error CentralRegistryLib__InvalidCentralRegistry();
/// INTERNAL FUNCTIONS ///
/// @notice Validates that `cr` is the Protocol Central Registry.
/// @param cr The proposed Protocol Central Registry.
function _isCentralRegistry(ICentralRegistry cr) internal view {
if (
!ERC165Checker.supportsInterface(
address(cr),
type(ICentralRegistry).interfaceId
)
) {
revert CentralRegistryLib__InvalidCentralRegistry();
}
}
}
// contracts/libraries/Multicall.sol
/// @title Curvance Multicall helper.
/// @notice Multicall implementation to support pull based oracles and
/// other chained actions within Curvance.
abstract contract Multicall {
/// TYPES ///
/// @notice Struct containing information on the desired
/// multicall action to execute.
/// @param target The address of the target contract to execute the call at.
/// @param isPriceUpdate Boolean indicating if the call is a price update.
/// @param data The data to attach to the call.
struct MulticallAction {
address target;
bool isPriceUpdate;
bytes data;
}
/// ERRORS ///
error Multicall__InvalidTarget();
error Multicall__UnknownCalldata();
/// EXTERNAL FUNCTIONS ///
/// @notice Executes multiple calls in a single transaction.
/// This can be used to update oracle prices before
/// a liquidity dependent action.
function multicall(
MulticallAction[] calldata calls
) external returns (bytes[] memory results) {
ICentralRegistry cr = _getCentralRegistry();
uint256 numCalls = calls.length;
results = new bytes[](numCalls);
MulticallAction memory cachedCall;
for (uint256 i; i < numCalls; ++i) {
cachedCall = calls[i];
if (cachedCall.isPriceUpdate) {
// CASE: We need to update a pull based price oracle and we
// need a direct call to the target address.
address checker = cr.multicallChecker(cachedCall.target);
// Validate we know how to verify this calldata.
if (checker == address(0)) {
revert Multicall__UnknownCalldata();
}
IMulticallChecker(checker).checkCalldata(
msg.sender,
cachedCall.target,
cachedCall.data
);
results[i] = LowLevelCallsHelper.
_call(cachedCall.target, cachedCall.data);
continue;
}
// CASE: Not a price update and we need delegate the call to the
// current address.
if (address(this) != cachedCall.target) {
revert Multicall__InvalidTarget();
}
results[i] = LowLevelCallsHelper.
_delegateCall(address(this), cachedCall.data);
}
}
/// @notice Returns the Protocol Central Registry contract in interface
/// form.
/// @dev MUST be overridden in every multicallable contract's
/// implementation.
function _getCentralRegistry()
internal
view
virtual
returns (ICentralRegistry);
}
// contracts/libraries/CommonLib.sol
/// @title Curvance Common Library
/// @notice A utility library for common functions used throughout the
/// Curvance Protocol.
library CommonLib {
/// @notice Returns whether `tokenA` matches `tokenB` or not.
/// @param tokenA The first token address to compare.
/// @param tokenB The second token address to compare.
/// @return Whether `tokenA` matches `tokenB` or not.
function _isMatchingToken(
address tokenA,
address tokenB
) internal pure returns (bool) {
if (tokenA == tokenB) {
return true;
}
if (_isNative(tokenA) && _isNative(tokenB)) {
return true;
}
return false;
}
/// @notice Returns whether `token` is referring to network gas token
/// or not.
/// @param token The address to review.
/// @return result Whether `token` is referring to network gas token or
/// not.
function _isNative(address token) internal pure returns (bool result) {
result = token == address(0) ||
token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
}
/// @notice Returns balance of `token` for this contract.
/// @param token The token address to query balance of.
/// @return b The balance of `token` inside address(this).
function _balanceOf(address token) internal view returns (uint256 b) {
b = _isNative(token) ? address(this).balance :
IERC20(token).balanceOf(address(this));
}
/// @notice Returns the Oracle Manager in interface form from `cr`.
/// @param cr The address of the Protocol Central Registry.
/// @return oracleManager The Oracle Manager in interface form.
function _oracleManager(
ICentralRegistry cr
) internal view returns (IOracleManager oracleManager) {
oracleManager = IOracleManager(cr.oracleManager());
}
}
// contracts/interfaces/IBorrowableCToken.sol
interface IBorrowableCToken {
/// ICToken GENERIC FUNCTIONS ///
/// @notice Starts a cToken market, executed via marketManager.
/// @dev This initial mint is a failsafe against rounding exploits,
/// although, we protect against them in many ways,
/// better safe than sorry.
/// @param by The account initializing deposits.
function initializeDeposits(address by) external returns (bool);
/// @notice Returns the decimals of the cToken.
/// @dev We pull directly from underlying incase its a proxy contract,
/// and changes decimals on us.
/// @return The number of decimals for this cToken,
/// matching the underlying token.
function decimals() external view returns (uint8);
/// @notice Returns whether the underlying token can be borrowed.
/// @dev true = Borrowable; false = Not Borrowable.
/// @return Whether this token is borrowable or not.
function isBorrowable() external view returns (bool);
/// @notice The token balance of an account.
/// @dev Account address => account token balance.
/// @param account The address of the account to query token balance for.
function balanceOf(address account) external view returns (uint256);
/// @notice Returns the address of the underlying asset.
/// @return The address of the underlying asset.
function asset() external view returns (address);
/// @notice Returns the current vesting yield information.
/// @return vestingRate % per second in `asset()`.
/// @return vestingEnd When the current vesting period ends and interest
/// rates paid will update.
/// @return lastVestingClaim Last time pending vested yield was claimed.
/// @return debtIndex The current market debt index.
function getYieldInformation() external view returns (
uint256 vestingRate,
uint256 vestingEnd,
uint256 lastVestingClaim,
uint256 debtIndex
);
/// @notice Get a snapshot of `account` data in this Curvance token.
/// @dev Used by marketManager to more efficiently perform
/// liquidity checks.
/// NOTE: Does not accrue pending interest as part of the call.
/// @param account The address of the account to snapshot.
/// @return The account snapshot of `account`.
function getSnapshot(
address account
) external view returns (AccountSnapshot memory);
/// @notice Total number of cTokens in circulation.
function totalSupply() external view returns (uint256);
/// @notice Returns the total amount of assets held by the market.
/// @return The total amount of assets held by the market.
function totalAssets() external view returns (uint256);
/// @notice Address of the Market Manager linked to this contract.
function marketManager() external view returns (IMarketManager);
/// @notice Returns the amount of assets that would be exchanged
/// by the vault for `shares` provided.
/// @param shares The number of shares to theoretically use
/// for conversion to assets.
/// @return The number of assets a user would receive for converting
/// `shares`.
function convertToAssets(uint256 shares) external view returns (uint256);
/// @notice Returns share -> asset exchange rate, in `WAD`.
/// @dev Oracle Manager calculates cToken value from this exchange rate.
function exchangeRate() external view returns (uint256);
/// @notice Executes multiple calls in a single transaction.
/// This can be used to update oracle prices before
/// a liquidity dependent action.
function multicall(
Multicall.MulticallAction[] memory calls
) external returns (bytes[] memory results);
/// @notice Caller deposits `assets` into the market and `receiver`
/// receives shares.
/// @param assets The amount of the underlying assets to deposit.
/// @param receiver The account that should receive the shares.
/// @return shares The amount of shares received by `receiver`.
function deposit(
uint256 assets,
address receiver
) external returns (uint256 shares);
/// @notice Caller deposits `assets` into the market, `receiver` receives
/// shares, and collateralization of `assets` is enabled.
/// @dev The caller must be depositing for themselves, or be managing
/// their position through a Position Manager contract.
/// If the caller is not approved to collateralize the function will
/// simply deposit assets on behalf of `receiver`.
/// @param assets The amount of the underlying assets to deposit.
/// @param receiver The account that should receive the shares.
/// @return shares The amount of shares received by `receiver`.
function depositAsCollateral(
uint256 assets,
address receiver
) external returns (uint256 shares);
/// @notice Caller deposits `assets` into the market, `receiver` receives
/// shares, and collateralization of `assets` is enabled.
/// @dev Requires that `receiver` approves the caller prior to
/// collateralize on their behalf.
/// NOTE: Be careful who you approve here!
/// They can delay redemption of assets through repeated
/// collateralization preventing withdrawal.
/// If the caller is not approved to collateralize the function will
/// simply deposit assets on behalf of `receiver`.
/// @param assets The amount of the underlying assets to deposit.
/// @param receiver The account that should receive the shares.
/// @return shares The amount of shares received by `receiver`.
function depositAsCollateralFor(
uint256 assets,
address receiver
) external returns (uint256 shares);
/// @notice Withdraws assets, quoted in `shares` from the market,
/// and burns `owner` shares.
/// @dev Does not force collateral to be withdrawn.
/// @param shares The amount of shares to be redeemed.
/// @param receiver The account that should receive the assets.
/// @param owner The account that will burn their shares to withdraw
/// assets.
/// @return assets The amount of assets redeemed by `owner`.
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
/// @notice Withdraws assets, quoted in `shares` from the market,
/// and burns `owner` shares, sending assets to `receiver`.
/// @dev Does not force collateral to be withdrawn.
/// @param shares The amount of shares to redeemed.
/// @param receiver The account that should receive the assets.
/// @param owner The account that will burn their shares to withdraw
/// assets.
/// @return assets The amount of assets redeemed by `owner` and sent to
/// `receiver`.
function redeemFor(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
/// @notice Caller withdraws assets from the market and burns their
/// shares, on behalf of `owner`.
/// @dev Forces collateral to be withdrawn from `owner` collateralPosted.
/// @param shares The amount of shares to redeemed.
/// @param receiver The account that should receive the assets.
/// @param owner The account that will burn their shares to withdraw
/// assets.
/// @return assets The amount of assets redeemed by `owner` and sent to
/// `receiver`.
function redeemCollateralFor(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
/// @notice Used by a Position Manager contract to redeem assets from
/// collateralized shares by `account` to perform a complex
/// action.
/// @param assets The amount of the underlying assets to redeem.
/// @param owner The owner address of assets to redeem.
/// @param action Instructions for a deleverage action containing:
/// cToken Address of the cToken that will be redeemed from
/// and assets swapped into `borrowableCToken` asset.
/// collateralAssets The amount of `cToken` that will be
/// deleveraged, in assets.
/// borrowableCToken Address of the borrowableCToken that
/// will have its debt paid.
/// repayAssets The amount of `borrowableCToken` asset that
/// will be repaid to lenders.
/// swapActions Swap actions instructions converting
/// collateral asset into debt asset to
/// facilitate deleveraging.
/// auxData Optional auxiliary data for execution of a
/// deleverage action.
function withdrawByPositionManager(
uint256 assets,
address owner,
IPositionManager.DeleverageAction memory action
) external;
/// @notice Amount of tokens that has been posted as collateral,
/// in shares.
function marketCollateralPosted() external view returns (uint256);
/// @notice Shares of this token that an account has posted as collateral.
/// @param account The address of the account to check collateral posted
/// of.
function collateralPosted(address account) external view returns (uint256);
/// @notice Transfers tokens from `account` to `liquidator`.
/// @dev Will fail unless called by a cToken during the process
/// of liquidation.
/// @param shares An array containing the number of cToken shares
/// to seize.
/// @param liquidator The account receiving seized cTokens.
/// @param accounts An array containing the accounts having
/// collateral seized.
function seize(
uint256[] calldata shares,
address liquidator,
address[] calldata accounts
) external;
/// @notice Allows users to simulate the effects of their deposit at
/// the current block.
/// @param assets The number of assets to preview a deposit call.
/// @return The shares received for depositing `assets`.
function previewDeposit(uint256 assets) external view returns (uint256);
/// IBorrowableCToken SPECIFIC FUNCTIONS ///
/// @notice Address of the current Dynamic IRM.
function IRM() external view returns (IDynamicIRM);
/// @notice Fee that goes to protocol for interested generated for
/// lenders, in `WAD`.
function interestFee() external view returns (uint256);
/// @notice Can accrue interest yield, configure next interest accrual
/// period, and updates vesting data, if needed.
/// @dev May emit a {RatesAdjusted} event.
function accrueIfNeeded() external;
/// @notice The amount of tokens that has been borrowed as debt,
/// in assets.
function marketOutstandingDebt() external view returns (uint256);
/// @notice Returns the current debt balance for `account`.
/// @dev Note: Pending interest is not applied in this calculation.
/// @param account The address whose debt balance should be calculated.
/// @return result The current outstanding debt balance of `account`.
function debtBalance(
address account
) external view returns (uint256 result);
/// @notice Updates pending interest and returns the current outstanding
/// debt owed by `account`.
/// @param account The address whose debt balance should be calculated.
/// @return result The current outstanding debt of `account`, with pending
/// interest applied.
function debtBalanceUpdated(
address account
) external returns (uint256 result);
/// @notice Updates pending interest and returns the up-to-date exchange
/// rate from the underlying to the BorrowableCToken.
/// @return result The share -> asset exchange rate, in `WAD`.
function exchangeRateUpdated() external returns (uint256);
/// @notice Used by a delegated user to borrow underlying tokens
/// from lenders, based on collateral posted inside this market
/// by `account`.
/// @dev Updates pending interest before executing the borrow.
/// NOTE: Be careful who you approve here!
/// Not only can they take borrowed funds, but, they can delay
/// repayment through repeated borrows preventing withdrawal.
/// @param assets The amount of the underlying asset to borrow.
/// @param receiver The account who will receive the borrowed assets.
/// @param owner The account who will have their assets borrowed
/// against.
function borrowFor(
uint256 assets,
address receiver,
address owner
) external;
/// @notice Used by a Position Manager contract to borrow assets from
/// lenders, based on collateralized shares by `account` to
/// perform a complex action.
/// @param assets The amount of the underlying assets to borrow.
/// @param owner The account address to borrow on behalf of.
/// @param action Instructions for a leverage action containing:
/// borrowableCToken Address of the borrowableCToken that
/// will be borrowed from and assets
/// swapped into `cToken` asset.
/// borrowAssets The amount borrowed from
/// `borrowableCToken`, in assets.
/// cToken Curvance token assets that borrowed funds will be
/// swapped into.
/// swapAction Swap action instructions converting debt
/// asset into collateral asset to facilitate
/// leveraging.
/// auxData Optional auxiliary data for execution of a
/// leverage action.
function borrowForPositionManager(
uint256 assets,
address owner,
IPositionManager.LeverageAction memory action
) external;
/// @notice Repays underlying tokens to lenders, on behalf of `account`,
/// freeing up their collateral posted inside this market.
/// @dev Updates pending interest before executing the repay.
/// @param assets The amount to repay, or 0 for the full outstanding
/// amount.
/// @param owner The account address to repay on behalf of.
function repayFor(uint256 assets, address owner) external;
/// @notice Gets balance of this contract, in terms of the underlying.
/// @dev This excludes changes in underlying token balance by the
/// current transaction, if any.
/// @return The quantity of underlying tokens held by the market.
function assetsHeld() external view returns (uint256);
}
// contracts/interfaces/ICToken.sol
struct AccountSnapshot {
address asset;
address underlying;
uint8 decimals;
bool isCollateral;
uint256 collateralPosted;
uint256 debtBalance;
}
interface ICToken {
/// @notice Starts a cToken market, executed via marketManager.
/// @dev This initial mint is a failsafe against rounding exploits,
/// although, we protect against them in many ways,
/// better safe than sorry.
/// @param by The account initializing deposits.
function initializeDeposits(address by) external returns (bool);
/// @notice Returns the decimals of the cToken.
/// @dev We pull directly from underlying incase its a proxy contract,
/// and changes decimals on us.
/// @return The number of decimals for this cToken,
/// matching the underlying token.
function decimals() external view returns (uint8);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
/// @notice Returns whether the underlying token can be borrowed.
/// @dev true = Borrowable; false = Not Borrowable.
/// @return Whether this token is borrowable or not.
function isBorrowable() external view returns (bool);
/// @notice The token balance of an account.
/// @dev Account address => account token balance.
/// @param account The address of the account to query token balance for.
function balanceOf(address account) external view returns (uint256);
/// @notice Returns the address of the underlying asset.
/// @return The address of the underlying asset.
function asset() external view returns (address);
/// @notice Updates pending assets and returns a snapshot of the cToken
/// and `account` data.
/// @dev Used by marketManager to more efficiently perform
/// liquidity checks.
/// @return result The snapshot of the cToken and `account` data.
function getSnapshotUpdated(
address account
) external returns (AccountSnapshot memory result);
/// @notice Get a snapshot of `account` data in this Curvance token.
/// @dev NOTE: Does not accrue pending assets as part of the call.
/// @param account The address of the account to snapshot.
/// @return The account snapshot of `account`.
function getSnapshot(
address account
) external view returns (AccountSnapshot memory);
/// @notice Total number of cTokens in circulation.
function totalSupply() external view returns (uint256);
/// @notice Returns the total amount of assets held by the market.
/// @return The total amount of assets held by the market.
function totalAssets() external view returns (uint256);
/// @notice Address of the Market Manager linked to this contract.
function marketManager() external view returns (IMarketManager);
/// @notice Returns the amount of assets that would be exchanged
/// by the vault for `shares` provided.
/// @param shares The number of shares to theoretically use
/// for conversion to assets.
/// @return The number of assets a user would receive for converting
/// `shares`.
function convertToAssets(uint256 shares) external view returns (uint256);
/// @notice Updates pending assets and returns the up-to-date exchange
/// rate from the underlying to the BorrowableCToken.
/// @dev Oracle Manager calculates cToken value from this exchange rate.
/// @return The share -> asset exchange rate, in `WAD`.
function exchangeRateUpdated() external returns (uint256) ;
/// @notice Returns the up-to-date exchange rate from the underlying to
/// the BorrowableCToken.
/// @dev Oracle Manager calculates cToken value from this exchange rate.
/// @return The share -> asset exchange rate, in `WAD`.
function exchangeRate() external view returns (uint256);
/// @notice Executes multiple calls in a single transaction.
/// This can be used to update oracle prices before
/// a liquidity dependent action.
function multicall(
Multicall.MulticallAction[] memory calls
) external returns (bytes[] memory results);
/// @notice Caller deposits `assets` into the market and `receiver`
/// receives shares.
/// @param assets The amount of the underlying assets to deposit.
/// @param receiver The account that should receive the shares.
/// @return shares The amount of shares received by `receiver`.
function deposit(
uint256 assets,
address receiver
) external returns (uint256 shares);
/// @notice Caller deposits `assets` into the market, `receiver` receives
/// shares, and collateralization of `assets` is enabled.
/// @dev The caller must be depositing for themselves, or be managing
/// their position through a Position Manager contract.
/// @param assets The amount of the underlying assets to deposit.
/// @param receiver The account that should receive the shares.
/// @return shares The amount of shares received by `receiver`.
function depositAsCollateral(
uint256 assets,
address receiver
) external returns (uint256 shares);
/// @notice Caller deposits `assets` into the market, `receiver` receives
/// shares, and collateralization of `assets` is enabled.
/// @dev Requires that `receiver` approves the caller prior to
/// collateralize on their behalf.
/// NOTE: Be careful who you approve here!
/// They can delay redemption of assets through repeated
/// collateralization preventing withdrawal.
/// @param assets The amount of the underlying assets to deposit.
/// @param receiver The account that should receive the shares.
/// @return shares The amount of shares received by `receiver`.
function depositAsCollateralFor(
uint256 assets,
address receiver
) external returns (uint256 shares);
/// @notice Withdraws assets, quoted in `shares` from the market,
/// and burns `owner` shares.
/// @dev Does not force collateral to be withdrawn.
/// @param shares The amount of shares to be redeemed.
/// @param receiver The account that should receive the assets.
/// @param owner The account that will burn their shares to withdraw
/// assets.
/// @return assets The amount of assets redeemed by `owner`.
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
/// @notice Withdraws assets, quoted in `shares` from the market,
/// and burns `owner` shares, sending assets to `receiver`.
/// @dev Does not force collateral to be withdrawn.
/// @param shares The amount of shares to redeemed.
/// @param receiver The account that should receive the assets.
/// @param owner The account that will burn their shares to withdraw
/// assets.
/// @return assets The amount of assets redeemed by `owner` and sent to
/// `receiver`.
function redeemFor(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
/// @notice Caller withdraws assets from the market and burns their
/// shares, on behalf of `owner`.
/// @dev Forces collateral to be withdrawn from `owner` collateralPosted.
/// @param shares The amount of shares to redeemed.
/// @param receiver The account that should receive the assets.
/// @param owner The account that will burn their shares to withdraw
/// assets.
/// @return assets The amount of assets redeemed by `owner` and sent to
/// `receiver`.
function redeemCollateralFor(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
/// @notice Used by a Position Manager contract to redeem assets from
/// collateralized shares by `account` to perform a complex
/// action.
/// @param assets The amount of the underlying assets to redeem.
/// @param owner The owner address of assets to redeem.
/// @param action Instructions for a deleverage action containing:
/// cToken Address of the cToken that will be redeemed from
/// and assets swapped into `borrowableCToken` asset.
/// collateralAssets The amount of `cToken` that will be
/// deleveraged, in assets.
/// borrowableCToken Address of the borrowableCToken that
/// will have its debt paid.
/// repayAssets The amount of `borrowableCToken` asset that
/// will be repaid to lenders.
/// swapActions Swap actions instructions converting
/// collateral asset into debt asset to
/// facilitate deleveraging.
/// auxData Optional auxiliary data for execution of a
/// deleverage action.
function withdrawByPositionManager(
uint256 assets,
address owner,
IPositionManager.DeleverageAction memory action
) external;
/// @notice Amount of tokens that has been posted as collateral,
/// in shares.
function marketCollateralPosted() external view returns (uint256);
/// @notice Shares of this token that an account has posted as collateral.
/// @param account The address of the account to check collateral posted
/// of.
function collateralPosted(address account) external view returns (uint256);
/// @notice Transfers tokens from `account` to `liquidator`.
/// @dev Will fail unless called by a cToken during the process
/// of liquidation.
/// @param shares An array containing the number of cToken shares
/// to seize.
/// @param liquidator The account receiving seized cTokens.
/// @param accounts An array containing the accounts having
/// collateral seized.
function seize(
uint256[] calldata shares,
address liquidator,
address[] calldata accounts
) external;
/// @notice Allows users to simulate the effects of their deposit at
/// the current block.
/// @param assets The number of assets to preview a deposit call.
/// @return The shares received for depositing `assets`.
function previewDeposit(uint256 assets) external view returns (uint256);
}
// contracts/interfaces/IExternalCalldataChecker.sol
interface IExternalCalldataChecker {
/// @notice Inspects calldata for compliance with other swap instruction
/// parameters.
/// @dev Used on swap to inspect and validate calldata safety.
/// @param swapAction Swap action instructions including both direct
/// parameters and decodeable calldata.
/// @param expectedRecipient Address who will receive proceeds of
/// `swapAction`.
function checkCalldata(
SwapperLib.Swap memory swapAction,
address expectedRecipient
) external;
}
// contracts/interfaces/IOracleManager.sol
interface IOracleManager {
/// @notice Retrieves the price of a specified asset from either single
/// or dual oracles.
/// @dev If the asset has one oracle, it fetches the price from a single feed.
/// If it has two or more oracles, it fetches the price from both feeds.
/// @param asset The address of the asset to retrieve the price for.
/// @param inUSD Whether the price should be returned in USD or ETH.
/// @param getLower Whether the lower or higher price should be returned
/// if two feeds are available.
/// @return price The current price of `asset`.
/// @return errorCode An error code related to fetching the price:
/// '0' indicates no error fetching price.
/// '1' indicates that price should be taken with
/// caution.
/// '2' indicates a complete failure in receiving
/// a price.
function getPrice(
address asset,
bool inUSD,
bool getLower
) external view returns (uint256 price, uint256 errorCode);
/// @notice Retrieves the prices of a collateral token and debt token
/// underlyings.
/// @param collateralToken The cToken currently collateralized to price.
/// @param debtToken The cToken borrowed from to price.
/// @param errorCodeBreakpoint The error code that will cause liquidity
/// operations to revert.
/// @return collateralUnderlyingPrice The current price of
/// `collateralToken` underlying.
/// @return debtUnderlyingPrice The current price of `debtToken`
/// underlying.
function getPriceIsolatedPair(
address collateralToken,
address debtToken,
uint256 errorCodeBreakpoint
) external returns (uint256, uint256);
/// @notice Retrieves the prices and account data of multiple assets
/// inside a Curvance Market.
/// @param account The account to retrieve data for.
/// @param assets An array of asset addresses to retrieve the prices for.
/// @param errorCodeBreakpoint The error code that will cause liquidity
/// operations to revert.
/// @return AccountSnapshot[] Contains `assets` data for `account`
/// @return uint256[] Contains prices for `assets`.
/// @return uint256 The number of assets `account` is in.
function getPricesForMarket(
address account,
address[] calldata assets,
uint256 errorCodeBreakpoint
)
external
returns (AccountSnapshot[] memory, uint256[] memory, uint256);
/// @notice Potentially removes the dependency on pricing from `adaptor`
/// for `asset`, triggered by an adaptor's notification of a price
/// feed's removal.
/// @notice Removes a pricing adaptor for `asset` triggered by an
/// adaptor's notification of a price feed's removal.
/// @dev Requires that the adaptor is currently being used for pricing
/// for `asset`.
/// NOTE: This intentionally does not modify asset deviation values
/// because they simply wont be used if there are less than two
/// pricing adaptors in use, so no reason to delete data as
/// when a second pricing adaptor is configured the deviation
/// has the opportunity be to reconfigured anyway.
/// @param asset The address of the asset to potentially remove the
/// pricing adaptor dependency from depending on current
/// `asset` configuration.
function notifyFeedRemoval(address asset) external;
/// @notice Returns the adaptors used for pricing `asset`.
/// @param asset The address of the asset to get pricing adaptors for.
/// @return The current adaptor(s) used for pricing `asset`.
function getPricingAdaptors(
address asset
) external view returns(address[] memory);
/// @notice Address => Adaptor approval status.
/// @param adaptor The address of the adaptor to check.
/// @return True if the adaptor is supported, false otherwise.
function isApprovedAdaptor(address adaptor) external view returns (bool);
/// @notice Whether a token is recognized as a Curvance token or not,
/// if it is, will return its underlying asset address instead
/// of address (0).
/// @return The cToken's underlying asset, or address(0) if not a cToken.
function cTokens(address cToken) external view returns (address);
/// @notice Checks if a given asset is supported by the Oracle Manager.
/// @dev An asset is considered supported if it has one
/// or more associated price feeds.
/// @param asset The address of the asset to check.
/// @return True if the asset is supported, false otherwise.
function isSupportedAsset(address asset) external view returns (bool);
/// @notice Check whether L2 sequencer is valid or down.
/// @return True if sequencer is valid.
function isSequencerValid() external view returns (bool);
}
// contracts/interfaces/IPositionManager.sol
interface IPositionManager {
/// TYPES ///
/// @notice Instructions for a leverage action.
/// @param borrowableCToken Address of the borrowableCToken that will be
/// borrowed from and assets swapped into `cToken`
/// asset.
/// @param borrowAssets The amount borrowed from `borrowableCToken`,
/// in assets.
/// @param cToken Curvance token assets that borrowed funds will be
/// swapped into.
/// @param expectedShares The expected shares received from depositing
/// into `cToken` with swapped `borrowAssets`.
/// @param swapAction Swap action instructions converting debt asset into
/// collateral asset to facilitate leveraging.
/// @param auxData Optional auxiliary data for execution of a leverage
/// action.
struct LeverageAction {
IBorrowableCToken borrowableCToken;
uint256 borrowAssets;
ICToken cToken;
uint256 expectedShares;
SwapperLib.Swap swapAction;
bytes auxData;
}
/// @notice Instructions for a deleverage action.
/// @param cToken Address of the cToken that will be redeemed from and
/// assets swapped into `borrowableCToken` asset.
/// @param collateralAssets The amount of `cToken` that will be
/// deleveraged, in assets.
/// @param borrowableCToken Address of the borrowableCToken that will
/// have its debt paid.
/// @param repayAssets The amount of `borrowableCToken` asset that will
/// be repaid to lenders.
/// @param swapActions Swap actions instructions converting collateral
/// asset into debt asset to facilitate deleveraging.
/// @param auxData Optional auxiliary data for execution of a deleverage
/// action.
struct DeleverageAction {
ICToken cToken;
uint256 collateralAssets;
IBorrowableCToken borrowableCToken;
uint256 repayAssets;
SwapperLib.Swap[] swapActions;
bytes auxData;
}
/// @notice Callback function to execute post borrow of
/// `borrowableCToken`'s asset and swap it to deposit
/// new collateralized shares for `owner`.
/// @dev Measures slippage after this callback validating that `owner`
/// is still within acceptable liquidity requirements.
/// @param borrowableCToken The borrowableCToken borrowed from.
/// @param borrowAssets The amount of `borrowableCToken`'s asset borrowed.
/// @param owner The account borrowing that will be swapped into
/// collateral assets deposited into Curvance.
/// @param action Instructions for a leverage action containing:
/// borrowableCToken Address of the borrowableCToken that
/// will be borrowed from and assets
/// swapped into `cToken` asset.
/// borrowAssets The amount borrowed from
/// `borrowableCToken`, in assets.
/// cToken Curvance token assets that borrowed funds will be
/// swapped into.
/// swapAction Swap action instructions converting debt
/// asset into collateral asset to facilitate
/// leveraging.
/// auxData Optional auxiliary data for execution of a
/// leverage action.
function onBorrow(
address borrowableCToken,
uint256 borrowAssets,
address owner,
LeverageAction memory action
) external;
/// @notice Callback function to execute post redemption of `cToken`'s
/// asset and swap it to repay outstanding debt for `owner`.
/// @dev Measures slippage after this callback validating that `owner`
/// is still within acceptable liquidity requirements.
/// @param cToken The Curvance token redeemed for its underlying.
/// @param collateralAssets The amount of `cToken` underlying redeemed.
/// @param owner The account redeeming collateral that will be used to
/// repay their active debt.
/// @param action Instructions for a deleverage action containing:
/// cToken Address of the cToken that will be redeemed from
/// and assets swapped into `borrowableCToken` asset.
/// collateralAssets The amount of `cToken` that will be
/// deleveraged, in assets.
/// borrowableCToken Address of the borrowableCToken that
/// will have its debt paid.
/// repayAssets The amount of `borrowableCToken` asset that
/// will be repaid to lenders.
/// swapAction Swap actions instructions converting
/// collateral asset into debt asset to
/// facilitate deleveraging.
/// auxData Optional auxiliary data for execution of a
/// deleverage action.
function onRedeem(
address cToken,
uint256 collateralAssets,
address owner,
DeleverageAction memory action
) external;
}
// contracts/libraries/SwapperLib.sol
/// @title Curvance Swapper Library.
/// @notice Helper Library for performing composable swaps with varying
/// degrees of slippage tolerance. "Unsafe" swaps perform a standard
/// slippage check whereas "safe" swaps not only check for standard
/// slippage but also check against the Oracle Manager's prices as
/// well.
/// NOTE: This library does not intend to provide support for fee on
/// transfer tokens though support may be built in the future.
library SwapperLib {
/// TYPES ///
/// @notice Instructions to execute a swap, selling `inputToken` for
/// `outputToken`.
/// @param inputToken Address of input token to swap from.
/// @param inputAmount The amount of `inputToken` to swap.
/// @param outputToken Address of token to swap into.
/// @param target Address of the swapper, usually an aggregator.
/// @param slippage The amount of value-loss acceptable from swapping
/// between tokens.
/// @param call Swap instruction calldata.
struct Swap {
address inputToken;
uint256 inputAmount;
address outputToken;
address target;
uint256 slippage;
bytes call;
}
/// @notice Address identifying a chain's native token.
address public constant native =
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// ERRORS ///
error SwapperLib__UnknownCalldata();
error SwapperLib__TokenPrice(address inputToken);
error SwapperLib__Slippage(uint256 slippage);
error SwapperLib__SameTokens();
/// INTERNAL FUNCTIONS ///
/// @notice Swaps `action.inputToken` into a `action.outputToken`
/// without an extra slippage check.
/// @param cr The address of the Protocol Central Registry to pull
/// addresses from.
/// @param action Instructions for a swap action containing:
/// inputToken Address of input token to swap from.
/// inputAmount The amount of `inputToken` to swap.
/// outputToken Address of token to swap into.
/// target Address of the swapper, usually an aggregator.
/// slippage The amount of value-loss acceptable from
/// swapping between tokens.
/// call Swap instruction calldata.
/// @return outAmount The output amount received from swapping.
function _swapUnsafe(
ICentralRegistry cr,
Swap memory action
) internal returns (uint256 outAmount) {
address outputToken = action.outputToken;
address inputToken = action.inputToken;
// Do not use this library if the tokens are the same.
if (CommonLib._isMatchingToken(inputToken, outputToken)) {
revert SwapperLib__SameTokens();
}
address callDataChecker = cr.externalCalldataChecker(action.target);
// Validate we know how to verify this calldata.
if (callDataChecker == address(0)) {
revert SwapperLib__UnknownCalldata();
}
// Verify calldata integrity.
IExternalCalldataChecker(callDataChecker)
.checkCalldata(action, address(this));
// Approve `action.inputToken` to target contract, if necessary.
_approveIfNeeded(inputToken, action.target, action.inputAmount);
// Cache output token from struct for easier querying.
uint256 balanceBefore = CommonLib._balanceOf(outputToken);
uint256 callValue = CommonLib._isNative(inputToken) ?
action.inputAmount : 0;
// Execute the swap.
LowLevelCallsHelper._callWithNative(
action.target,
action.call,
callValue
);
// Remove any excess approval.
_removeApprovalIfNeeded(inputToken, action.target);
outAmount = CommonLib._balanceOf(outputToken) - balanceBefore;
}
/// @notice Swaps `action.inputToken` into a `action.outputToken`
/// with an extra slippage check.
/// @param cr The address of the Protocol Central Registry to pull
/// addresses from.
/// @param action Instructions for a swap action containing:
/// inputToken Address of input token to swap from.
/// inputAmount The amount of `inputToken` to swap.
/// outputToken Address of token to swap into.
/// target Address of the swapper, usually an
/// aggregator.
/// slippage The amount of value-loss acceptable from
/// swapping between tokens.
/// call Swap instruction calldata.
/// @return outAmount The output amount received from swapping.
function _swapSafe(
ICentralRegistry cr,
Swap memory action
) internal returns (uint256 outAmount) {
if (action.slippage >= WAD) {
revert SwapperLib__Slippage(action.slippage);
}
outAmount = _swapUnsafe(cr, action);
IOracleManager om = CommonLib._oracleManager(cr);
uint256 valueIn = _getValue(om, action.inputToken, action.inputAmount);
uint256 valueOut = _getValue(om, action.outputToken, outAmount);
// Check if swap received positive slippage.
if (valueOut > valueIn) {
return outAmount;
}
// Calculate % slippage from executed swap.
uint256 slippage = FixedPointMathLib.mulDivUp(
valueIn - valueOut,
WAD,
valueIn
);
if (slippage > action.slippage) {
revert SwapperLib__Slippage(slippage);
}
}
/// @notice Get the value of a token amount.
/// @notice Approves `token` spending allowance, if needed.
/// @param om The Oracle Manager address to call for pricing `token`.
/// @param token The token address to get the value of.
/// @param amount The amount of `token` to get the value of.
function _getValue(
IOracleManager om,
address token,
uint256 amount
) internal view returns (uint256 result) {
// If token is native, normalize to address(0) so it is compatible
// with the Oracle Manager.
if (token == address(0)) {
token = native;
}
(uint256 price, uint256 errorCode) = om.getPrice(token, true, true);
if (errorCode != NO_ERROR) {
revert SwapperLib__TokenPrice(token);
}
// Return price in WAD form.
result = FixedPointMathLib.mulDiv(
price,
amount,
10 ** (CommonLib._isNative(token) ? 18 : IERC20(token).decimals())
);
}
/// @notice Approves `token` spending allowance, if needed.
/// @param token The token address to approve.
/// @param spender The spender address.
/// @param amount The approval amount.
function _approveIfNeeded(
address token,
address spender,
uint256 amount
) internal {
if (!CommonLib._isNative(token)) {
SafeTransferLib.safeApprove(token, spender, amount);
}
}
/// @notice Removes `token` spending allowance, if needed.
/// @param token The token address to remove approval.
/// @param spender The spender address.
function _removeApprovalIfNeeded(address token, address spender) internal {
if (!CommonLib._isNative(token)) {
if (IERC20(token).allowance(address(this), spender) > 0) {
SafeTransferLib.safeApprove(token, spender, 0);
}
}
}
}
// contracts/oracles/adaptors/BaseOracleAdaptor.sol
abstract contract BaseOracleAdaptor is IOracleAdaptor {
/// CONSTANTS ///
/// @notice Curvance DAO hub.
ICentralRegistry public immutable centralRegistry;
/// @notice The minimum amount of time allowed between `timestampStart`
/// and `block.timestamp` on `setGuardedPriceConfig` call.
uint256 internal constant _MINIMUM_TIMESTAMP_BUFFER = 7 days;
/// @notice The oracle adaptor type, calculated via keccak256 of the
/// oracle adaptor's name.
uint256 internal immutable _adaptorType;
/// STORAGE ///
/// @notice Whether an asset is supported by the Oracle Adaptor or not.
/// @dev Asset => Supported by Adaptor.
mapping(address => bool) public isSupportedAsset;
/// @notice Token price guard configuration for pricing an asset.
/// @dev Token address => inUSD => Price Guard configuration.
mapping(address => mapping(bool => PriceGuard)) public priceGuards;
/// EVENTS ///
event AssetRemoved(address asset);
event PriceGuardUpdated(PriceGuard pg);
/// ERRORS ///
error BaseOracleAdaptor__Unauthorized();
error BaseOracleAdaptor__InvalidConfig();
error BaseOracleAdaptor__InvalidTimestamp();
error BaseOracleAdaptor__MinPriceAboveCurrentPrice();
error BaseOracleAdaptor__BasePriceBelowCurrentPrice();
error BaseOracleAdaptor__AssetIsNotSupported();
/// CONSTRUCTOR ///
/// @param cr The address of the Protocol Central Registry.
constructor(ICentralRegistry cr, string memory adaptorName) {
CentralRegistryLib._isCentralRegistry(cr);
centralRegistry = cr;
if (bytes(adaptorName).length == 0) {
revert BaseOracleAdaptor__InvalidConfig();
}
_adaptorType = uint256(keccak256(abi.encode(adaptorName)));
}
/// EXTERNAL FUNCTIONS ///
/// @notice Retrieves the price of `asset`, in `inUSD` price form.
/// @param asset The address of the asset to retrieve a price for.
/// @param inUSD Specifies whether the price format should be in USD (true)
/// or a chain's native token (false).
/// @return result Return data for a priced asset containing:
/// price The price of the asset.
/// inUSD Boolean indicating whether `price` is denominated
/// in USD (true) or native token (false).
/// hadError Boolean indicating whether the asset was priced
/// without running into any issues or not.
function getPrice(
address asset,
bool inUSD,
bool /* getLower */
) external view virtual override returns (PricingResult memory result) {
_checkSupportedAsset(asset);
result = _getPrice(asset, inUSD);
}
/// @notice Returns PriceGuard data for pricing `asset` denominated either
/// USD or native tokens depending on `inUSD`.
/// @param asset The address of the asset to retrieve any PriceGuard data on.
/// @param inUSD Specifies whether the PriceGuard returned should be in
/// USD (true) or a chain's native token (false).
/// @return result The price guard currently applied to `asset` when
/// denominated in `inUSD`.
function getPriceGuard(
address asset,
bool inUSD
) external view returns (PriceGuard memory result) {
result = priceGuards[asset][inUSD];
}
/// @notice Sets a PriceGuard when pricing `asset` denominated either USD
/// or native tokens depending on `inUSD`.
/// @param asset The address of the asset to set a PriceGuard data on.
/// @param inUSD Specifies whether the PriceGuard should be in
/// USD (true) or a chain's native token (false).
/// @param timestampStart When `ips` should start increasing `basePrice`
/// raising the maximum price returned when pricing
/// `asset`.
/// @param ips The magnitude that `basePrice` should increase overtime
/// overtime from `timestampStart`, in `WAD`, in seconds.
/// @param basePrice The base price that should be the maximum price
/// returned when pricing `asset`.
/// @param minPrice The minimum price that should be allowed to be
/// returned when pricing `asset`.
function setGuardedPriceConfig(
address asset,
bool inUSD,
uint256 timestampStart,
uint256 ips,
uint256 basePrice,
uint256 minPrice
) external {
_checkMarketPermissions();
// Validate timestamp configuration depending on whether dynamic scaling is
// enabled. If ips == 0, timestampStart must be exactly 0
// (unused in static mode).
// Otherwise, enforce it is not in the future or too "now".
if (ips == 0) {
if (timestampStart != 0) {
revert BaseOracleAdaptor__InvalidTimestamp();
}
} else {
if (
timestampStart > block.timestamp ||
block.timestamp - timestampStart < _MINIMUM_TIMESTAMP_BUFFER ||
timestampStart == 0
) {
revert BaseOracleAdaptor__InvalidTimestamp();
}
}
// Validate that growth rate will fit in 40 bit slot allocated.
if (ips > type(uint40).max) {
revert BaseOracleAdaptor__InvalidConfig();
}
// Validate basePrice is not 0 and that base price will fit in the
// 88 bit slot allocated.
if (basePrice == 0 || basePrice > type(uint88).max) {
revert BaseOracleAdaptor__InvalidConfig();
}
// Validate that min and max price logic are not inverted, we can then
// skip the storage slot check since basePrice > minPrice.
if (minPrice > basePrice) {
revert BaseOracleAdaptor__InvalidConfig();
}
// Validate the higher feed did not return an error.
PricingResult memory result = this.getPrice(asset, inUSD, false);
if (result.hadError) {
revert BaseOracleAdaptor__InvalidConfig();
}
// Validate the lower feed did not return an error.
result = this.getPrice(asset, inUSD, true);
if (result.hadError) {
revert BaseOracleAdaptor__InvalidConfig();
}
// Having a minimum price above the current price does not make sense,
// implying that asset price behaves differently than our PriceGuard
// assumes.
// This will simply return `minPrice` if ips == 0 so can use internal
// function to handle both cases.
uint256 guardedMinPrice =
_guardedPrice(block.timestamp - timestampStart, ips, minPrice);
if (guardedMinPrice > result.price) {
revert BaseOracleAdaptor__MinPriceAboveCurrentPrice();
}
PriceGuard storage pg = priceGuards[asset][inUSD];
// New `timestampStart` needs to start after the current one.
if (pg.timestampStart > timestampStart && timestampStart > 0) {
revert BaseOracleAdaptor__InvalidTimestamp();
}
pg.timestampStart = uint40(timestampStart);
pg.ips = uint40(ips);
pg.basePrice = uint88(basePrice);
pg.minPrice = uint88(minPrice);
emit PriceGuardUpdated(pg);
}
/// @notice Disables any PriceGuard active when pricing `asset`
/// denominated either USD or native tokens depending on `inUSD`.
/// @param asset The address of the asset to disable any PriceGuard data on.
/// @param inUSD Specifies whether the PriceGuard disabled should be in
/// USD (true) or a chain's native token (false).
function disableGuardedPriceConfig(address asset, bool inUSD) external {
_checkMarketPermissions();
_disableGuardedPriceConfig(asset, inUSD);
}
/// @notice Removes a supported asset from the adaptor, and any price
/// guard configured.
/// @dev Calls back into Oracle Manager to notify it of its removal.
/// Requires that `asset` is currently supported.
/// @param asset The address of the supported asset to remove from
/// the adaptor.
function removeAsset(address asset) external {
_checkElevatedPermissions();
_checkSupportedAsset(asset);
// Notify the adaptor to stop supporting the asset.
delete isSupportedAsset[asset];
_wipeAssetConfigs(asset);
_disableGuardedPriceConfig(asset, true);
_disableGuardedPriceConfig(asset, false);
// Notify the Oracle Manager that we are going to stop supporting
// the asset.
CommonLib._oracleManager(centralRegistry).notifyFeedRemoval(asset);
emit AssetRemoved(asset);
}
/// @notice Returns the adaptor's type.
/// @dev Used by frontends to determine how to properly interact
/// with a supported asset.
/// @return result The adaptor's type.
function adaptorType() external view returns (uint256 result) {
result = _adaptorType;
}
/// INTERNAL FUNCTIONS ///
/// @notice Validates the feed data based on various constraints.
/// @dev Checks if the value is within a specific range
/// and if the data is not outdated.
/// @param value The value that is retrieved from the feed data.
/// @param timestamp The time at which the value was last updated.
/// @param heartbeat The maximum allowed time difference between
/// current time and 'timestamp'.
/// @return A boolean indicating whether the feed data had an error
/// (true = error, false = no error).
function _verifyData(
uint256 value,
uint256 timestamp,
uint256 heartbeat
) internal view virtual returns (bool) {
// Validate `value` is not at or below 0.
if (value <= 0) {
return true;
}
// Validate the price returned is not stale.
if (block.timestamp - timestamp > heartbeat) {
return true;
}
return false;
}
/// @notice Helper function for adjusting received price into WAD form
/// received from various oracle adaptors.
/// @param price The price to adjust.
/// @param decimals The decimal precision `price` is reported in.
/// @return Returns the potentially adjusted price in 1e18 (WAD) scale.
function _adjustPrice(
address asset,
bool inUSD,
uint256 price,
uint256 decimals
) internal view returns (uint256) {
// Normalize price to 18 decimals (WAD).
if (decimals != 18) {
price = FixedPointMathLib.fullMulDiv(price, WAD, 10 ** decimals);
}
// Adjust price based on any present price guards.
PriceGuard memory pg = priceGuards[asset][inUSD];
// Case where there is no base price at all, this indicates PriceGuard
// is disabled, so can return price as is.
if (pg.basePrice == 0) {
return price;
}
// Case where there is no realtime price increase so the PriceGuard
// has static minimum/maximum guarded prices.
if (pg.ips == 0) {
// If the price of the token drops below the minimum we return 0
// to immediately bubble up a pricing error.
if (price < pg.minPrice) {
return 0;
}
return price > pg.basePrice ? pg.basePrice : price;
}
// Case with dynamic minimum/maximum guarded prices.
// Calculate how much to shift up minimum and maximum values from
// scaling guarded prices.
uint256 timePassed = block.timestamp - pg.timestampStart;
uint256 min = _guardedPrice(timePassed, pg.ips, pg.minPrice);
// If the price of the token drops below the minimum we return 0 to
// immediately bubble up a pricing error.
if (price < min) {
return 0;
}
uint256 max = _guardedPrice(timePassed, pg.ips, pg.basePrice);
return price > max ? max : price;
}
/// @notice Calculated the guarded price value to compare an oracle feeds
/// calculated price against.
/// @notice timePassed The time passed since dynamic price increase
/// started.
/// @notice ips The increase per second relative applied to `price`,
/// in `WAD`.
/// @notice price The starting price to calculate the guarded price from,
/// increased by `ips` overtime.
function _guardedPrice(
uint256 timePassed,
uint256 ips,
uint256 price
) internal pure returns (uint256 r) {
r = FixedPointMathLib.fullMulDiv(price, ((timePassed * ips) + WAD), WAD);
}
/// @notice Disables any PriceGuard active when pricing `asset`
/// denominated either USD or native tokens depending on `inUSD`.
/// @param asset The address of the asset to disable any PriceGuard data on.
/// @param inUSD Specifies whether the PriceGuard disabled should be in
/// USD (true) or a chain's native token (false).
function _disableGuardedPriceConfig(address asset, bool inUSD) internal {
delete priceGuards[asset][inUSD];
}
/// @notice Checks whether `asset` is supported by the adaptor or not.
function _checkSupportedAsset(address asset) internal view {
// Validate we support pricing `asset`.
if (!isSupportedAsset[asset]) {
revert BaseOracleAdaptor__AssetIsNotSupported();
}
}
/// @notice Checks whether `asset` is the zero address which is blocked.
function _checkNotZeroAddress(address asset) internal pure {
if (asset == address(0)) {
revert BaseOracleAdaptor__InvalidConfig();
}
}
/// @notice Checks whether the caller has sufficient permissioning.
function _checkElevatedPermissions() internal view {
if (!centralRegistry.hasElevatedPermissions(msg.sender)) {
revert BaseOracleAdaptor__Unauthorized();
}
}
/// @notice Checks whether the caller has sufficient permissioning.
function _checkMarketPermissions() internal view {
if (!centralRegistry.hasMarketPermissions(msg.sender)) {
revert BaseOracleAdaptor__Unauthorized();
}
}
/// INTERNAL FUNCTIONS TO OVERRIDE ///
/// @notice Retrieves the price of a given asset in `inUSD` price form.
/// @param asset The address of the asset for which the price is needed.
/// @param inUSD Whether `asset` should be priced in USD or native tokens.
/// @return result Return data for a priced asset containing:
/// price The price of the asset.
/// inUSD Boolean indicating whether `price` is denominated
/// in USD (true) or native token (false).
/// hadError Boolean indicating whether the asset was priced
/// without running into any issues or not.
function _getPrice(
address asset,
bool inUSD
) internal view virtual returns (PricingResult memory result);
/// @notice Wipes asset pricing configurations from this adaptor.
function _wipeAssetConfigs(address /*asset*/ ) internal virtual;
}
// contracts/oracles/adaptors/chainlink/ChainlinkAdaptor.sol
contract ChainlinkAdaptor is BaseOracleAdaptor {
/// TYPES ///
/// @notice Stores configuration data for Chainlink price sources.
/// @param isConfigured Whether the asset is configured or not.
/// false = unconfigured; true = configured.
/// @param aggregatorProxy Chainlink aggregator proxy to use for
/// pricing `asset`.
/// @param decimals Returns the number of decimals the proxy denominates
/// asset prices in.
/// @param heartbeat The max amount of time allowed between price updates.
/// 0 defaults to using `DEFAULT_HEARTBEAT`.
struct AssetConfig {
bool isConfigured;
IChainlink aggregatorProxy;
uint8 decimals;
uint24 heartbeat;
}
/// CONSTANTS ///
/// @notice If zero is specified for a Chainlink asset heartbeat,
/// this value is used instead.
/// @dev 1 days = 24 hours = 1,440 minutes = 86,400 seconds.
uint256 public constant DEFAULT_HEARTBEAT =
1 days + HEARTBEAT_GRACE_PERIOD;
/// STORAGE ///
/// @notice Price feed configuration data for an asset.
/// @dev Token address => inUSD => Price feed configuration for `asset`.
mapping(address => mapping(bool => AssetConfig)) public assetConfig;
/// EVENTS ///
event AssetAdded(address asset, AssetConfig config, bool isUpdate);
/// ERRORS ///
error ChainlinkAdaptor__InvalidHeartbeat();
/// CONSTRUCTOR ///
/// @param cr The address of the Protocol Central Registry.
constructor(ICentralRegistry cr) BaseOracleAdaptor(cr, "ChainlinkAdaptor") {}
/// EXTERNAL FUNCTIONS ///
/// @notice Adds pricing support for `asset` via a new Chainlink feed.
/// @dev Should be called before `OracleManager:addAssetPricingAdaptor`
/// is called.
/// @param asset The address of the token to add pricing support for.
/// @param inUSD Whether the price feed is in USD (inUSD = true)
/// or native token (inUSD = false).
/// @param aggregatorProxy Chainlink aggregator proxy to use for
/// pricing `asset`.
/// @param heartbeat Chainlink heartbeat to use when validating prices
/// for `asset`. 0 = `DEFAULT_HEARTBEAT`.
function addAsset(
address asset,
bool inUSD,
address aggregatorProxy,
uint256 heartbeat
) external {
_checkElevatedPermissions();
_checkNotZeroAddress(asset);
// If we are not using the default heartbeat directly, apply
// `HEARTBEAT_GRACE_PERIOD` to `heartbeat` to make sure it,
// was not missed.
if (heartbeat != 0) {
heartbeat = heartbeat + HEARTBEAT_GRACE_PERIOD;
}
// Validate the feed heartbeat is not too long.
if (heartbeat > DEFAULT_HEARTBEAT) {
revert ChainlinkAdaptor__InvalidHeartbeat();
}
AssetConfig storage config = assetConfig[asset][inUSD];
// Update `config` and make sure `isSupportedAsset` returns true
// for `asset`.
config.aggregatorProxy = IChainlink(aggregatorProxy);
config.decimals = IChainlink(aggregatorProxy).decimals();
config.heartbeat = uint24(heartbeat != 0 ? heartbeat : DEFAULT_HEARTBEAT);
config.isConfigured = true;
// Check whether this is new or updated support for `asset`.
bool isUpdate;
if (isSupportedAsset[asset]) {
isUpdate = true;
}
isSupportedAsset[asset] = true;
emit AssetAdded(asset, config, isUpdate);
}
/// INTERNAL FUNCTIONS ///
/// @notice Retrieves the price of a given asset in `inUSD` price form.
/// @dev Calls latestRoundData() from Chainlink to get the latest data
/// for pricing and staleness.
/// @param asset The address of the asset for which the price is needed.
/// @param inUSD Whether `asset` should be priced in USD or native tokens.
/// @return result Return data for a priced asset containing:
/// price The price of the asset.
/// inUSD Boolean indicating whether `price` is denominated
/// in USD (true) or native token (false).
/// hadError Boolean indicating whether the asset was priced
/// without running into any issues or not.
function _getPrice(
address asset,
bool inUSD
) internal view override returns (PricingResult memory result) {
// Parse data from the format you want if its configured, otherwise
// price in the other format and manually convert in Oracle Manager.
if (!assetConfig[asset][inUSD].isConfigured) {
inUSD = !inUSD;
}
AssetConfig memory c = assetConfig[asset][inUSD];
result.inUSD = inUSD;
(, int256 price,, uint256 updatedAt, ) = IChainlink(c.aggregatorProxy)
.latestRoundData();
// If we got a price of 0 or less, bubble up an error immediately.
if (price <= 0) {
result.hadError = true;
return result;
}
// Adjust price pulled, if necessary.
uint256 adjustedPrice =
_adjustPrice(asset, inUSD, uint256(price), c.decimals);
result.hadError = _verifyData(adjustedPrice, updatedAt, c.heartbeat);
result.price = adjustedPrice;
}
/// @notice Wipes `asset` pricing configurations from this adaptor.
/// @param asset The address of the asset to wipe pricing support of.
function _wipeAssetConfigs(address asset) internal override {
delete assetConfig[asset][true];
delete assetConfig[asset][false];
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ICentralRegistry","name":"cr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BaseOracleAdaptor__AssetIsNotSupported","type":"error"},{"inputs":[],"name":"BaseOracleAdaptor__BasePriceBelowCurrentPrice","type":"error"},{"inputs":[],"name":"BaseOracleAdaptor__InvalidConfig","type":"error"},{"inputs":[],"name":"BaseOracleAdaptor__InvalidTimestamp","type":"error"},{"inputs":[],"name":"BaseOracleAdaptor__MinPriceAboveCurrentPrice","type":"error"},{"inputs":[],"name":"BaseOracleAdaptor__Unauthorized","type":"error"},{"inputs":[],"name":"CentralRegistryLib__InvalidCentralRegistry","type":"error"},{"inputs":[],"name":"ChainlinkAdaptor__InvalidHeartbeat","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"components":[{"internalType":"bool","name":"isConfigured","type":"bool"},{"internalType":"contract IChainlink","name":"aggregatorProxy","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint24","name":"heartbeat","type":"uint24"}],"indexed":false,"internalType":"struct ChainlinkAdaptor.AssetConfig","name":"config","type":"tuple"},{"indexed":false,"internalType":"bool","name":"isUpdate","type":"bool"}],"name":"AssetAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"asset","type":"address"}],"name":"AssetRemoved","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint40","name":"timestampStart","type":"uint40"},{"internalType":"uint40","name":"ips","type":"uint40"},{"internalType":"uint88","name":"basePrice","type":"uint88"},{"internalType":"uint88","name":"minPrice","type":"uint88"}],"indexed":false,"internalType":"struct IOracleAdaptor.PriceGuard","name":"pg","type":"tuple"}],"name":"PriceGuardUpdated","type":"event"},{"inputs":[],"name":"DEFAULT_HEARTBEAT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adaptorType","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"bool","name":"inUSD","type":"bool"},{"internalType":"address","name":"aggregatorProxy","type":"address"},{"internalType":"uint256","name":"heartbeat","type":"uint256"}],"name":"addAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bool","name":"","type":"bool"}],"name":"assetConfig","outputs":[{"internalType":"bool","name":"isConfigured","type":"bool"},{"internalType":"contract IChainlink","name":"aggregatorProxy","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint24","name":"heartbeat","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"centralRegistry","outputs":[{"internalType":"contract ICentralRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"bool","name":"inUSD","type":"bool"}],"name":"disableGuardedPriceConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"bool","name":"inUSD","type":"bool"},{"internalType":"bool","name":"","type":"bool"}],"name":"getPrice","outputs":[{"components":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"inUSD","type":"bool"},{"internalType":"bool","name":"hadError","type":"bool"}],"internalType":"struct IOracleAdaptor.PricingResult","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"bool","name":"inUSD","type":"bool"}],"name":"getPriceGuard","outputs":[{"components":[{"internalType":"uint40","name":"timestampStart","type":"uint40"},{"internalType":"uint40","name":"ips","type":"uint40"},{"internalType":"uint88","name":"basePrice","type":"uint88"},{"internalType":"uint88","name":"minPrice","type":"uint88"}],"internalType":"struct IOracleAdaptor.PriceGuard","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isSupportedAsset","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bool","name":"","type":"bool"}],"name":"priceGuards","outputs":[{"internalType":"uint40","name":"timestampStart","type":"uint40"},{"internalType":"uint40","name":"ips","type":"uint40"},{"internalType":"uint88","name":"basePrice","type":"uint88"},{"internalType":"uint88","name":"minPrice","type":"uint88"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"removeAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"bool","name":"inUSD","type":"bool"},{"internalType":"uint256","name":"timestampStart","type":"uint256"},{"internalType":"uint256","name":"ips","type":"uint256"},{"internalType":"uint256","name":"basePrice","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"}],"name":"setGuardedPriceConfig","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60c060405234801561000f575f5ffd5b5060405161179f38038061179f83398101604081905261002e916101cf565b60408051808201909152601081526f21b430b4b73634b735a0b230b83a37b960811b60208201528190610060826100c3565b6001600160a01b03821660805280515f0361008e5760405163bdb91f6b60e01b815260040160405180910390fd5b8060405160200161009f91906101f5565b60408051601f19818403018152919052805160209091012060a0525061022a915050565b6100d4816399011ef160e01b6100f4565b6100f1576040516369b5e45b60e11b815260040160405180910390fd5b50565b5f6100fe83610116565b801561010f575061010f8383610149565b9392505050565b5f610128826301ffc9a760e01b610149565b80156101435750610141826001600160e01b0319610149565b155b92915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f5190508280156101b9575060208210155b80156101c457505f81115b979650505050505050565b5f602082840312156101df575f5ffd5b81516001600160a01b038116811461010f575f5ffd5b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b60805160a05161153f6102605f395f6101d101525f81816101fa015281816104a201528181610b5c0152610c2b015261153f5ff3fe608060405234801561000f575f5ffd5b50600436106100b1575f3560e01c8063752f4c6d1161006e578063752f4c6d146101cf5780638f73dcfa146101f55780639be918e614610234578063cece0b2e14610266578063e93068b9146102f7578063eb93ae66146103ef575f5ffd5b806308453cf8146100b557806328a2fda8146100d057806338ac94a71461015b5780634a5e42b1146101705780635ae69163146101835780635f5f92c5146101bc575b5f5ffd5b6100bd610402565b6040519081526020015b60405180910390f35b6101246100de366004611156565b600260209081525f928352604080842090915290825290205460ff8082169161010081046001600160a01b031691600160a81b82041690600160b01b900462ffffff1684565b6040805194151585526001600160a01b03909316602085015260ff9091169183019190915262ffffff1660608201526080016100c7565b61016e610169366004611156565b610413565b005b61016e61017e36600461118d565b610429565b6101966101913660046111a8565b61055e565b6040805182518152602080840151151590820152918101511515908201526060016100c7565b61016e6101ca3660046111f0565b610595565b7f00000000000000000000000000000000000000000000000000000000000000006100bd565b61021c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100c7565b61025661024236600461118d565b5f6020819052908152604090205460ff1681565b60405190151581526020016100c7565b6102bf610274366004611156565b600160209081525f928352604080842090915290825290205464ffffffffff80821691600160281b8104909116906001600160581b03600160501b8204811691600160a81b90041684565b6040805164ffffffffff95861681529490931660208501526001600160581b03918216928401929092521660608201526080016100c7565b610398610305366004611156565b60408051608080820183525f808352602080840182905283850182905260609384018290526001600160a01b0396909616815260018652838120941515815293855292829020825193840183525464ffffffffff8082168552600160281b820416948401949094526001600160581b03600160501b8504811692840192909252600160a81b909304169181019190915290565b6040516100c791905f60808201905064ffffffffff835116825264ffffffffff60208401511660208301526001600160581b0360408401511660408301526001600160581b03606084015116606083015292915050565b61016e6103fd366004611245565b610921565b6104106078620151806112a7565b81565b61041b610b47565b6104258282610bed565b5050565b610431610c16565b61043a81610c62565b6001600160a01b0381165f90815260208181526040808320805460ff19169055600282528083206001845290915280822080546001600160c81b0319908116909155828052912080549091169055610493816001610bed565b61049d815f610bed565b6104c67f0000000000000000000000000000000000000000000000000000000000000000610c9d565b604051631c79049560e21b81526001600160a01b03838116600483015291909116906371e41254906024015f604051808303815f87803b158015610508575f5ffd5b505af115801561051a573d5f5f3e3d5ffd5b50506040516001600160a01b03841681527f37803e2125c48ee96c38ddf04e826daf335b0e1603579040fd275aba6d06b6fc9250602001905060405180910390a150565b604080516060810182525f808252602082018190529181019190915261058384610c62565b61058d8484610d04565b949350505050565b61059d610b47565b825f036105c85783156105c35760405163cf8731d360e01b815260040160405180910390fd5b610608565b428411806105e1575062093a806105df85426112ba565b105b806105ea575083155b156106085760405163cf8731d360e01b815260040160405180910390fd5b64ffffffffff83111561062e5760405163bdb91f6b60e01b815260040160405180910390fd5b81158061064157506001600160581b0382115b1561065f5760405163bdb91f6b60e01b815260040160405180910390fd5b818111156106805760405163bdb91f6b60e01b815260040160405180910390fd5b604051635ae6916360e01b81526001600160a01b038716600482015285151560248201525f60448201819052903090635ae6916390606401606060405180830381865afa1580156106d3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f791906112cd565b905080604001511561071c5760405163bdb91f6b60e01b815260040160405180910390fd5b604051635ae6916360e01b81526001600160a01b03881660048201528615156024820152600160448201523090635ae6916390606401606060405180830381865afa15801561076d573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061079191906112cd565b90508060400151156107b65760405163bdb91f6b60e01b815260040160405180910390fd5b5f6107cb6107c487426112ba565b8685610e74565b82519091508111156107f057604051638072783f60e01b815260040160405180910390fd5b6001600160a01b0388165f9081526001602090815260408083208a151584529091529020805464ffffffffff168710801561082a57505f87115b156108485760405163cf8731d360e01b815260040160405180910390fd5b80546001600160581b03858116600160a81b026001600160a81b03918816600160501b029190911669ffffffffffffffffffff64ffffffffff8a8116600160281b0269ffffffffffffffffffff19909516908c16179390931792909216919091171781556040517f62e8c7a0261a219d2ffa5939dce28f886b863e3e7ecede4a76a8a0c9934d70009061090e90835464ffffffffff8082168352602882901c166020830152605081901c6001600160581b0316604083015260a81c606082015260800190565b60405180910390a1505050505050505050565b610929610c16565b61093284610ea4565b8015610946576109436078826112a7565b90505b6109546078620151806112a7565b81111561097457604051638647953560e01b815260040160405180910390fd5b6001600160a01b038481165f90815260026020908152604080832087151584528252918290208054610100600160a81b031916610100948716948502178155825163313ce56760e01b8152925190939263313ce5679260048083019391928290030181865afa1580156109e9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0d9190611342565b815460ff91909116600160a81b0260ff60a81b199091161781555f829003610a4257610a3d6078620151806112a7565b610a44565b815b815460ff1962ffffff92909216600160b01b029190911660ff62ffffff60b01b01199091161760011781556001600160a01b0385165f9081526020819052604081205460ff1615610a93575060015b6001600160a01b0386165f9081526020819052604090819020805460ff19166001179055517f48ad0e65be417216028cec51e9f08373e4c9a87ab4a61ca2fc6c439dd7ce7c0690610b37908890859085906001600160a01b039384168152915460ff80821615156020850152600882901c909416604084015260a881901c909316606083015260b09290921c62ffffff16608082015290151560a082015260c00190565b60405180910390a1505050505050565b604051630225e24360e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630225e243906024015b602060405180830381865afa158015610baa573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bce9190611362565b610beb57604051637dab3b4d60e11b815260040160405180910390fd5b565b6001600160a01b039091165f908152600160209081526040808320931515835292905290812055565b60405163de0c7a7160e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063de0c7a7190602401610b8f565b6001600160a01b0381165f9081526020819052604090205460ff16610c9a57604051636e74c1f360e01b815260040160405180910390fd5b50565b5f816001600160a01b031663565d878c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cda573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfe919061137d565b92915050565b604080516060810182525f80825260208083018290528284018290526001600160a01b03861682526002815283822085151583529052919091205460ff16610d4a579015905b6001600160a01b038381165f9081526002602090815260408083208615158085529083528184208251608081018452905460ff8082161515835261010082048816838701908152600160a81b830490911683860152600160b01b90910462ffffff1660608301529387019190915291518151633fabe5a360e21b815291519294849391169163feaf968c9160048083019260a09291908290030181865afa158015610df7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1b91906113b6565b509350509250505f8213610e385750506001604083015250610cfe565b5f610e4c878785876040015160ff16610ecb565b9050610e628183866060015162ffffff16611066565b15156040860152845250505092915050565b5f61058d82670de0b6b3a7640000610e8c8688611404565b610e9691906112a7565b670de0b6b3a7640000611099565b6001600160a01b038116610c9a5760405163bdb91f6b60e01b815260040160405180910390fd5b5f81601214610ef457610ef183670de0b6b3a7640000610eec85600a6114fe565b611099565b92505b6001600160a01b0385165f908152600160209081526040808320871515845282528083208151608081018352905464ffffffffff8082168352600160281b820416938201939093526001600160581b03600160501b84048116928201839052600160a81b9093049092166060830152909103610f73578391505061058d565b806020015164ffffffffff165f03610fd45780606001516001600160581b0316841015610fa3575f91505061058d565b80604001516001600160581b03168411610fbd5783610fcc565b80604001516001600160581b03165b91505061058d565b80515f90610fe99064ffffffffff16426112ba565b90505f61100f82846020015164ffffffffff1685606001516001600160581b0316610e74565b905080861015611024575f935050505061058d565b5f61104883856020015164ffffffffff1686604001516001600160581b0316610e74565b90508087116110575786611059565b805b9998505050505050505050565b5f5f841161107657506001611092565b8161108184426112ba565b111561108f57506001611092565b505f5b9392505050565b8282025f1983850981811082019003806110c857826110bf5763ae47f7025f526004601cfd5b50819004611092565b8083116110dc5763ae47f7025f526004601cfd5b828486095f84810385169485900494848311909303908390038390046001010292030417600260038302811880840282030280840282030280840282030280840282030280840282030280840290910302029392505050565b6001600160a01b0381168114610c9a575f5ffd5b8015158114610c9a575f5ffd5b5f5f60408385031215611167575f5ffd5b823561117281611135565b9150602083013561118281611149565b809150509250929050565b5f6020828403121561119d575f5ffd5b813561109281611135565b5f5f5f606084860312156111ba575f5ffd5b83356111c581611135565b925060208401356111d581611149565b915060408401356111e581611149565b809150509250925092565b5f5f5f5f5f5f60c08789031215611205575f5ffd5b863561121081611135565b9550602087013561122081611149565b95989597505050506040840135936060810135936080820135935060a0909101359150565b5f5f5f5f60808587031215611258575f5ffd5b843561126381611135565b9350602085013561127381611149565b9250604085013561128381611135565b9396929550929360600135925050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610cfe57610cfe611293565b81810381811115610cfe57610cfe611293565b5f60608284031280156112de575f5ffd5b506040516060810167ffffffffffffffff8111828210171561130e57634e487b7160e01b5f52604160045260245ffd5b60405282518152602083015161132381611149565b6020820152604083015161133681611149565b60408201529392505050565b5f60208284031215611352575f5ffd5b815160ff81168114611092575f5ffd5b5f60208284031215611372575f5ffd5b815161109281611149565b5f6020828403121561138d575f5ffd5b815161109281611135565b805169ffffffffffffffffffff811681146113b1575f5ffd5b919050565b5f5f5f5f5f60a086880312156113ca575f5ffd5b6113d386611398565b602087015160408801516060890151929750909550935091506113f860808701611398565b90509295509295909350565b8082028115828204841417610cfe57610cfe611293565b6001815b60018411156114565780850481111561143a5761143a611293565b600184161561144857908102905b60019390931c92800261141f565b935093915050565b5f8261146c57506001610cfe565b8161147857505f610cfe565b816001811461148e5760028114611498576114b4565b6001915050610cfe565b60ff8411156114a9576114a9611293565b50506001821b610cfe565b5060208310610133831016604e8410600b84101617156114d7575081810a610cfe565b6114e35f19848461141b565b805f19048211156114f6576114f6611293565b029392505050565b5f611092838361145e56fea26469706673582212200fb534bf7ea45618da3dd7c4b9832c59941c571ba8bcc22ba91ba38deb92917464736f6c634300081c00330000000000000000000000001310f352f1389969ece6741671c4b919523912ff
Deployed Bytecode
0x608060405234801561000f575f5ffd5b50600436106100b1575f3560e01c8063752f4c6d1161006e578063752f4c6d146101cf5780638f73dcfa146101f55780639be918e614610234578063cece0b2e14610266578063e93068b9146102f7578063eb93ae66146103ef575f5ffd5b806308453cf8146100b557806328a2fda8146100d057806338ac94a71461015b5780634a5e42b1146101705780635ae69163146101835780635f5f92c5146101bc575b5f5ffd5b6100bd610402565b6040519081526020015b60405180910390f35b6101246100de366004611156565b600260209081525f928352604080842090915290825290205460ff8082169161010081046001600160a01b031691600160a81b82041690600160b01b900462ffffff1684565b6040805194151585526001600160a01b03909316602085015260ff9091169183019190915262ffffff1660608201526080016100c7565b61016e610169366004611156565b610413565b005b61016e61017e36600461118d565b610429565b6101966101913660046111a8565b61055e565b6040805182518152602080840151151590820152918101511515908201526060016100c7565b61016e6101ca3660046111f0565b610595565b7f092b02dfba1fcb65e6c6feeef53a74d18f2d420417578f606e7fb3089b6fad806100bd565b61021c7f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff81565b6040516001600160a01b0390911681526020016100c7565b61025661024236600461118d565b5f6020819052908152604090205460ff1681565b60405190151581526020016100c7565b6102bf610274366004611156565b600160209081525f928352604080842090915290825290205464ffffffffff80821691600160281b8104909116906001600160581b03600160501b8204811691600160a81b90041684565b6040805164ffffffffff95861681529490931660208501526001600160581b03918216928401929092521660608201526080016100c7565b610398610305366004611156565b60408051608080820183525f808352602080840182905283850182905260609384018290526001600160a01b0396909616815260018652838120941515815293855292829020825193840183525464ffffffffff8082168552600160281b820416948401949094526001600160581b03600160501b8504811692840192909252600160a81b909304169181019190915290565b6040516100c791905f60808201905064ffffffffff835116825264ffffffffff60208401511660208301526001600160581b0360408401511660408301526001600160581b03606084015116606083015292915050565b61016e6103fd366004611245565b610921565b6104106078620151806112a7565b81565b61041b610b47565b6104258282610bed565b5050565b610431610c16565b61043a81610c62565b6001600160a01b0381165f90815260208181526040808320805460ff19169055600282528083206001845290915280822080546001600160c81b0319908116909155828052912080549091169055610493816001610bed565b61049d815f610bed565b6104c67f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff610c9d565b604051631c79049560e21b81526001600160a01b03838116600483015291909116906371e41254906024015f604051808303815f87803b158015610508575f5ffd5b505af115801561051a573d5f5f3e3d5ffd5b50506040516001600160a01b03841681527f37803e2125c48ee96c38ddf04e826daf335b0e1603579040fd275aba6d06b6fc9250602001905060405180910390a150565b604080516060810182525f808252602082018190529181019190915261058384610c62565b61058d8484610d04565b949350505050565b61059d610b47565b825f036105c85783156105c35760405163cf8731d360e01b815260040160405180910390fd5b610608565b428411806105e1575062093a806105df85426112ba565b105b806105ea575083155b156106085760405163cf8731d360e01b815260040160405180910390fd5b64ffffffffff83111561062e5760405163bdb91f6b60e01b815260040160405180910390fd5b81158061064157506001600160581b0382115b1561065f5760405163bdb91f6b60e01b815260040160405180910390fd5b818111156106805760405163bdb91f6b60e01b815260040160405180910390fd5b604051635ae6916360e01b81526001600160a01b038716600482015285151560248201525f60448201819052903090635ae6916390606401606060405180830381865afa1580156106d3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f791906112cd565b905080604001511561071c5760405163bdb91f6b60e01b815260040160405180910390fd5b604051635ae6916360e01b81526001600160a01b03881660048201528615156024820152600160448201523090635ae6916390606401606060405180830381865afa15801561076d573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061079191906112cd565b90508060400151156107b65760405163bdb91f6b60e01b815260040160405180910390fd5b5f6107cb6107c487426112ba565b8685610e74565b82519091508111156107f057604051638072783f60e01b815260040160405180910390fd5b6001600160a01b0388165f9081526001602090815260408083208a151584529091529020805464ffffffffff168710801561082a57505f87115b156108485760405163cf8731d360e01b815260040160405180910390fd5b80546001600160581b03858116600160a81b026001600160a81b03918816600160501b029190911669ffffffffffffffffffff64ffffffffff8a8116600160281b0269ffffffffffffffffffff19909516908c16179390931792909216919091171781556040517f62e8c7a0261a219d2ffa5939dce28f886b863e3e7ecede4a76a8a0c9934d70009061090e90835464ffffffffff8082168352602882901c166020830152605081901c6001600160581b0316604083015260a81c606082015260800190565b60405180910390a1505050505050505050565b610929610c16565b61093284610ea4565b8015610946576109436078826112a7565b90505b6109546078620151806112a7565b81111561097457604051638647953560e01b815260040160405180910390fd5b6001600160a01b038481165f90815260026020908152604080832087151584528252918290208054610100600160a81b031916610100948716948502178155825163313ce56760e01b8152925190939263313ce5679260048083019391928290030181865afa1580156109e9573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0d9190611342565b815460ff91909116600160a81b0260ff60a81b199091161781555f829003610a4257610a3d6078620151806112a7565b610a44565b815b815460ff1962ffffff92909216600160b01b029190911660ff62ffffff60b01b01199091161760011781556001600160a01b0385165f9081526020819052604081205460ff1615610a93575060015b6001600160a01b0386165f9081526020819052604090819020805460ff19166001179055517f48ad0e65be417216028cec51e9f08373e4c9a87ab4a61ca2fc6c439dd7ce7c0690610b37908890859085906001600160a01b039384168152915460ff80821615156020850152600882901c909416604084015260a881901c909316606083015260b09290921c62ffffff16608082015290151560a082015260c00190565b60405180910390a1505050505050565b604051630225e24360e01b81523360048201527f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff6001600160a01b031690630225e243906024015b602060405180830381865afa158015610baa573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bce9190611362565b610beb57604051637dab3b4d60e11b815260040160405180910390fd5b565b6001600160a01b039091165f908152600160209081526040808320931515835292905290812055565b60405163de0c7a7160e01b81523360048201527f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff6001600160a01b03169063de0c7a7190602401610b8f565b6001600160a01b0381165f9081526020819052604090205460ff16610c9a57604051636e74c1f360e01b815260040160405180910390fd5b50565b5f816001600160a01b031663565d878c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cda573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cfe919061137d565b92915050565b604080516060810182525f80825260208083018290528284018290526001600160a01b03861682526002815283822085151583529052919091205460ff16610d4a579015905b6001600160a01b038381165f9081526002602090815260408083208615158085529083528184208251608081018452905460ff8082161515835261010082048816838701908152600160a81b830490911683860152600160b01b90910462ffffff1660608301529387019190915291518151633fabe5a360e21b815291519294849391169163feaf968c9160048083019260a09291908290030181865afa158015610df7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1b91906113b6565b509350509250505f8213610e385750506001604083015250610cfe565b5f610e4c878785876040015160ff16610ecb565b9050610e628183866060015162ffffff16611066565b15156040860152845250505092915050565b5f61058d82670de0b6b3a7640000610e8c8688611404565b610e9691906112a7565b670de0b6b3a7640000611099565b6001600160a01b038116610c9a5760405163bdb91f6b60e01b815260040160405180910390fd5b5f81601214610ef457610ef183670de0b6b3a7640000610eec85600a6114fe565b611099565b92505b6001600160a01b0385165f908152600160209081526040808320871515845282528083208151608081018352905464ffffffffff8082168352600160281b820416938201939093526001600160581b03600160501b84048116928201839052600160a81b9093049092166060830152909103610f73578391505061058d565b806020015164ffffffffff165f03610fd45780606001516001600160581b0316841015610fa3575f91505061058d565b80604001516001600160581b03168411610fbd5783610fcc565b80604001516001600160581b03165b91505061058d565b80515f90610fe99064ffffffffff16426112ba565b90505f61100f82846020015164ffffffffff1685606001516001600160581b0316610e74565b905080861015611024575f935050505061058d565b5f61104883856020015164ffffffffff1686604001516001600160581b0316610e74565b90508087116110575786611059565b805b9998505050505050505050565b5f5f841161107657506001611092565b8161108184426112ba565b111561108f57506001611092565b505f5b9392505050565b8282025f1983850981811082019003806110c857826110bf5763ae47f7025f526004601cfd5b50819004611092565b8083116110dc5763ae47f7025f526004601cfd5b828486095f84810385169485900494848311909303908390038390046001010292030417600260038302811880840282030280840282030280840282030280840282030280840282030280840290910302029392505050565b6001600160a01b0381168114610c9a575f5ffd5b8015158114610c9a575f5ffd5b5f5f60408385031215611167575f5ffd5b823561117281611135565b9150602083013561118281611149565b809150509250929050565b5f6020828403121561119d575f5ffd5b813561109281611135565b5f5f5f606084860312156111ba575f5ffd5b83356111c581611135565b925060208401356111d581611149565b915060408401356111e581611149565b809150509250925092565b5f5f5f5f5f5f60c08789031215611205575f5ffd5b863561121081611135565b9550602087013561122081611149565b95989597505050506040840135936060810135936080820135935060a0909101359150565b5f5f5f5f60808587031215611258575f5ffd5b843561126381611135565b9350602085013561127381611149565b9250604085013561128381611135565b9396929550929360600135925050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610cfe57610cfe611293565b81810381811115610cfe57610cfe611293565b5f60608284031280156112de575f5ffd5b506040516060810167ffffffffffffffff8111828210171561130e57634e487b7160e01b5f52604160045260245ffd5b60405282518152602083015161132381611149565b6020820152604083015161133681611149565b60408201529392505050565b5f60208284031215611352575f5ffd5b815160ff81168114611092575f5ffd5b5f60208284031215611372575f5ffd5b815161109281611149565b5f6020828403121561138d575f5ffd5b815161109281611135565b805169ffffffffffffffffffff811681146113b1575f5ffd5b919050565b5f5f5f5f5f60a086880312156113ca575f5ffd5b6113d386611398565b602087015160408801516060890151929750909550935091506113f860808701611398565b90509295509295909350565b8082028115828204841417610cfe57610cfe611293565b6001815b60018411156114565780850481111561143a5761143a611293565b600184161561144857908102905b60019390931c92800261141f565b935093915050565b5f8261146c57506001610cfe565b8161147857505f610cfe565b816001811461148e5760028114611498576114b4565b6001915050610cfe565b60ff8411156114a9576114a9611293565b50506001821b610cfe565b5060208310610133831016604e8410600b84101617156114d7575081810a610cfe565b6114e35f19848461141b565b805f19048211156114f6576114f6611293565b029392505050565b5f611092838361145e56fea26469706673582212200fb534bf7ea45618da3dd7c4b9832c59941c571ba8bcc22ba91ba38deb92917464736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001310f352f1389969ece6741671c4b919523912ff
-----Decoded View---------------
Arg [0] : cr (address): 0x1310f352f1389969Ece6741671c4B919523912fF
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000001310f352f1389969ece6741671c4b919523912ff
Deployed Bytecode Sourcemap
145976:5934:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;147010:84;;;:::i;:::-;;;160:25:1;;;148:2;133:18;147010:84:0;;;;;;;;147265:67;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;147265:67:0;;-1:-1:-1;;;147265:67:0;;;;-1:-1:-1;;;147265:67:0;;;;;;;;;;1104:14:1;;1097:22;1079:41;;-1:-1:-1;;;;;1156:32:1;;;1151:2;1136:18;;1129:60;1237:4;1225:17;;;1205:18;;;1198:45;;;;1291:8;1279:21;1274:2;1259:18;;1252:49;1066:3;1051:19;147265:67:0;842:465:1;138010:166:0;;;;;;:::i;:::-;;:::i;:::-;;138535:591;;;;;;:::i;:::-;;:::i;132601:258::-;;;;;;:::i;:::-;;:::i;:::-;;;;2310:13:1;;2292:32;;2394:4;2382:17;;;2376:24;2369:32;2362:40;2340:20;;;2333:70;2461:17;;;2455:24;2448:32;2441:40;2419:20;;;2412:70;2280:2;2265:18;132601:258:0;2086:402:1;134495:3132:0;;;;;;:::i;:::-;;:::i;139331:102::-;139413:12;139331:102;;130122:49;;;;;;;;-1:-1:-1;;;;;3551:32:1;;;3533:51;;3521:2;3506:18;130122:49:0;3363:227:1;130705:48:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;3760:14:1;;3753:22;3735:41;;3723:2;3708:18;130705:48:0;3595:187:1;130898:66:0;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;130898:66:0;;;;;;-1:-1:-1;;;;;;;;130898:66:0;;;;;-1:-1:-1;;;130898:66:0;;;;;;;;;4040:12:1;4028:25;;;4010:44;;4090:25;;;;4085:2;4070:18;;4063:53;-1:-1:-1;;;;;4152:37:1;;;4132:18;;;4125:65;;;;4226:37;4221:2;4206:18;;4199:65;3997:3;3982:19;130898:66:0;3787:483:1;133357:177:0;;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133501:18:0;;;;;;:11;:18;;;;;:25;;;;;;;;;;;;133492:34;;;;;;;;;;;;;;-1:-1:-1;;;133492:34:0;;;;;;;;;;-1:-1:-1;;;;;;;;133492:34:0;;;;;;;;;;;-1:-1:-1;;;133492:34:0;;;;;;;;;;;;133357:177;;;;;;;4421:4:1;4463:3;4452:9;4448:19;4440:27;;4513:12;4504:6;4498:13;4494:32;4483:9;4476:51;4595:12;4587:4;4579:6;4575:17;4569:24;4565:43;4558:4;4547:9;4543:20;4536:73;-1:-1:-1;;;;;4669:4:1;4661:6;4657:17;4651:24;4647:55;4640:4;4629:9;4625:20;4618:85;-1:-1:-1;;;;;4763:4:1;4755:6;4751:17;4745:24;4741:55;4734:4;4723:9;4719:20;4712:85;4275:528;;;;;148359:1361:0;;;;;;:::i;:::-;;:::i;147010:84::-;147063:31;1207:3;147063:6;:31;:::i;:::-;147010:84;:::o;138010:166::-;138092:25;:23;:25::i;:::-;138128:40;138155:5;138162;138128:26;:40::i;:::-;138010:166;;:::o;138535:591::-;138591:27;:25;:27::i;:::-;138629;138650:5;138629:20;:27::i;:::-;-1:-1:-1;;;;;138737:23:0;;:16;:23;;;;;;;;;;;138730:30;;-1:-1:-1;;138730:30:0;;;151832:11;:18;;;;;-1:-1:-1;151832:24:0;;;;;;;;151825:31;;-1:-1:-1;;;;;;151825:31:0;;;;;;151874:25;;;;;151867:32;;;;;;;138806:39;138833:5;138840:4;138806:26;:39::i;:::-;138856:40;138883:5;138890;138856:26;:40::i;:::-;139007:41;139032:15;139007:24;:41::i;:::-;:66;;-1:-1:-1;;;139007:66:0;;-1:-1:-1;;;;;3551:32:1;;;139007:66:0;;;3533:51:1;139007:59:0;;;;;;;3506:18:1;;139007:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;139099:19:0;;-1:-1:-1;;;;;3551:32:1;;3533:51;;139099:19:0;;-1:-1:-1;3521:2:1;3506:18;;-1:-1:-1;139099:19:0;;;;;;;138535:591;:::o;132601:258::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;132781:27:0;132802:5;132781:20;:27::i;:::-;132828:23;132838:5;132845;132828:9;:23::i;:::-;132819:32;132601:258;-1:-1:-1;;;;132601:258:0:o;134495:3132::-;134708:25;:23;:25::i;:::-;135010:3;135017:1;135010:8;135006:446;;135039:19;;135035:104;;135086:37;;-1:-1:-1;;;135086:37:0;;;;;;;;;;;135035:104;135006:446;;;135210:15;135193:14;:32;:113;;;-1:-1:-1;130383:6:0;135246:32;135264:14;135246:15;:32;:::i;:::-;:60;135193:113;:153;;;-1:-1:-1;135327:19:0;;135193:153;135171:270;;;135388:37;;-1:-1:-1;;;135388:37:0;;;;;;;;;;;135171:270;135547:16;135541:22;;135537:96;;;135587:34;;-1:-1:-1;;;135587:34:0;;;;;;;;;;;135537:96;135761:14;;;:46;;-1:-1:-1;;;;;;135779:28:0;;135761:46;135757:120;;;135831:34;;-1:-1:-1;;;135831:34:0;;;;;;;;;;;135757:120;136052:9;136041:8;:20;136037:94;;;136085:34;;-1:-1:-1;;;136085:34:0;;;;;;;;;;;136037:94;136235:34;;-1:-1:-1;;;136235:34:0;;-1:-1:-1;;;;;6268:32:1;;136235:34:0;;;6250:51:1;6344:14;;6337:22;6317:18;;;6310:50;136205:27:0;6376:18:1;;;6369:50;;;136205:27:0;136235:4;;:13;;6223:18:1;;136235:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;136205:64;;136284:6;:15;;;136280:89;;;136323:34;;-1:-1:-1;;;136323:34:0;;;;;;;;;;;136280:89;136449:33;;-1:-1:-1;;;136449:33:0;;-1:-1:-1;;;;;6268:32:1;;136449:33:0;;;6250:51:1;6344:14;;6337:22;6317:18;;;6310:50;136477:4:0;6376:18:1;;;6369:50;136449:4:0;;:13;;6223:18:1;;136449:33:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;136440:42;;136497:6;:15;;;136493:89;;;136536:34;;-1:-1:-1;;;136536:34:0;;;;;;;;;;;136493:89;136895:23;136934:62;136948:32;136966:14;136948:15;:32;:::i;:::-;136982:3;136987:8;136934:13;:62::i;:::-;137031:12;;136895:101;;-1:-1:-1;137013:30:0;;137009:116;;;137067:46;;-1:-1:-1;;;137067:46:0;;;;;;;;;;;137009:116;-1:-1:-1;;;;;137169:18:0;;137145:21;137169:18;;;:11;:18;;;;;;;;:25;;;;;;;;;;137282:17;;;;:34;-1:-1:-1;137282:56:0;;;;;137337:1;137320:14;:18;137282:56;137278:133;;;137362:37;;-1:-1:-1;;;137362:37:0;;;;;;;;;;;137278:133;137423:42;;-1:-1:-1;;;;;137550:30:0;;;-1:-1:-1;;;137550:30:0;-1:-1:-1;;;;;137507:32:0;;;-1:-1:-1;;;137507:32:0;137550:30;;;;;137423:42;137476:20;;;-1:-1:-1;;;137476:20:0;-1:-1:-1;;137476:20:0;;;137423:42;;;137476:20;;;;;137550:30;;;;;;;;;;;137598:21;;;;;;137423:2;7539:13:1;7594:12;7579:28;;;7561:47;;7654:2;7650:18;;;7646:37;7639:4;7624:20;;7617:67;7730:2;7726:18;;;-1:-1:-1;;;;;7722:49:1;7715:4;7700:20;;7693:79;7814:3;7810:19;7803:4;7788:20;;7781:49;7509:3;7494:19;;7320:516;137598:21:0;;;;;;;;134697:2930;;;134495:3132;;;;;;:::o;148359:1361::-;148511:27;:25;:27::i;:::-;148549;148570:5;148549:20;:27::i;:::-;148760:14;;148756:93;;148803:34;1207:3;148803:9;:34;:::i;:::-;148791:46;;148756:93;147063:31;1207:3;147063:6;:31;:::i;:::-;148922:9;:29;148918:105;;;148975:36;;-1:-1:-1;;;148975:36:0;;;;;;;;;;;148918:105;-1:-1:-1;;;;;149064:18:0;;;149035:26;149064:18;;;:11;:18;;;;;;;;:25;;;;;;;;;;;149201:52;;-1:-1:-1;;;;;;149201:52:0;;;;;;;;;;;149282:38;;-1:-1:-1;;;149282:38:0;;;;149064:25;;149201:52;149282:36;;:38;;;;;149064:18;;149282:38;;;;;149201:52;149282:38;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;149264:56;;;;;;;-1:-1:-1;;;149264:56:0;-1:-1:-1;;;;149264:56:0;;;;;;:15;149357:14;;;:46;;147063:31;1207:3;147063:6;:31;:::i;:::-;149357:46;;;149374:9;149357:46;149331:73;;-1:-1:-1;;149331:73:0;;;;;-1:-1:-1;;;149331:73:0;149415:26;;;;-1:-1:-1;;;;;;149415:26:0;;;;-1:-1:-1;149415:26:0;;;-1:-1:-1;;;;;149552:23:0;;149331:16;149552:23;;;;;;;;;;;149415:26;149552:23;149548:71;;;-1:-1:-1;149603:4:0;149548:71;-1:-1:-1;;;;;149631:23:0;;:16;:23;;;;;;;;;;;;:30;;-1:-1:-1;;149631:30:0;149657:4;149631:30;;;149677:35;;;;;149648:5;;149695:6;;149703:8;;-1:-1:-1;;;;;8393:32:1;;;8375:51;;8452:13;;8530:4;8515:20;;;8508:28;8501:36;8496:2;8481:18;;8474:64;8582:1;8578:17;;;8574:43;;;8569:2;8554:18;;8547:71;8662:3;8658:19;;;8654:30;;;8649:2;8634:18;;8627:58;8730:3;8726:19;;;;8747:8;8722:34;8716:3;8701:19;;8694:63;8801:14;;8794:22;8413:3;8773:19;;8766:51;8362:3;8347:19;;8119:704;149677:35:0;;;;;;;;148500:1220;;148359:1361;;;;:::o;144729:189::-;144794:48;;-1:-1:-1;;;144794:48:0;;144831:10;144794:48;;;3533:51:1;144794:15:0;-1:-1:-1;;;;;144794:36:0;;;;3506:18:1;;144794:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;144789:122;;144866:33;;-1:-1:-1;;;144866:33:0;;;;;;;;;;;144789:122;144729:189::o;143681:123::-;-1:-1:-1;;;;;143771:18:0;;;;;;;:11;:18;;;;;;;;:25;;;;;;;;;;;143764:32;143681:123::o;144455:193::-;144522:50;;-1:-1:-1;;;144522:50:0;;144561:10;144522:50;;;3533:51:1;144522:15:0;-1:-1:-1;;;;;144522:38:0;;;;3506:18:1;;144522:50:0;3363:227:1;143888:230:0;-1:-1:-1;;;;;144012:23:0;;:16;:23;;;;;;;;;;;;;144007:104;;144059:40;;-1:-1:-1;;;144059:40:0;;;;;;;;;;;144007:104;143888:230;:::o;83503:183::-;83587:28;83659:2;-1:-1:-1;;;;;83659:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83628:50;83503:183;-1:-1:-1;;83503:183:0:o;150538:1060::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;150841:18:0;;;;:11;:18;;;;;:25;;;;;;;;;;;:38;;;150836:88;;150904:6;;;150836:88;-1:-1:-1;;;;;150959:18:0;;;150936:20;150959:18;;;:11;:18;;;;;;;;:25;;;;;;;;;;;;150936:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;150936:48:0;;;;;;;;;-1:-1:-1;;;150936:48:0;;;;;;;;;150995:12;;;:20;;;;151088:17;;151077:61;;-1:-1:-1;;;151077:61:0;;;;150936:48;;:20;;151077:59;;;;;:61;;;;;;;;;;;;;;:59;:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;151036:102;;;;;;;151240:1;151231:5;:10;151227:93;;-1:-1:-1;;151276:4:0;151258:15;;;:22;-1:-1:-1;151295:13:0;;151227:93;151379:21;151416:54;151429:5;151436;151451;151459:1;:10;;;151416:54;;:12;:54::i;:::-;151379:91;;151501:50;151513:13;151528:9;151539:1;:11;;;151501:50;;:11;:50::i;:::-;151483:68;;:15;;;:68;151562:28;;-1:-1:-1;;;150538:1060:0;;;;:::o;143068:230::-;143196:9;143222:68;143251:5;636:4;143260:16;143273:3;143260:10;:16;:::i;:::-;143259:24;;;;:::i;:::-;636:4;143222:28;:68::i;144204:170::-;-1:-1:-1;;;;;144278:19:0;;144274:93;;144321:34;;-1:-1:-1;;;144321:34:0;;;;;;;;;;;140823:1769;140971:7;141045:8;141057:2;141045:14;141041:111;;141084:56;141113:5;636:4;141125:14;141131:8;141125:2;:14;:::i;:::-;141084:28;:56::i;:::-;141076:64;;141041:111;-1:-1:-1;;;;;141255:18:0;;141232:20;141255:18;;;:11;:18;;;;;;;;:25;;;;;;;;;;141232:48;;;;;;;;;;;;;;;-1:-1:-1;;;141232:48:0;;;;;;;;;;-1:-1:-1;;;;;;;;141232:48:0;;;;;;;;;;-1:-1:-1;;;141232:48:0;;;;;;;;;;;;141437:17;141433:62;;141478:5;141471:12;;;;;141433:62;141643:2;:6;;;:11;;141653:1;141643:11;141639:314;;141819:2;:11;;;-1:-1:-1;;;;;141811:19:0;:5;:19;141807:68;;;141858:1;141851:8;;;;;141807:68;141906:2;:12;;;-1:-1:-1;;;;;141898:20:0;:5;:20;:43;;141936:5;141898:43;;;141921:2;:12;;;-1:-1:-1;;;;;141898:43:0;;141891:50;;;;;141639:314;142179:17;;142140:18;;142161:35;;;;:15;:35;:::i;:::-;142140:56;;142207:11;142221:46;142235:10;142247:2;:6;;;142221:46;;142255:2;:11;;;-1:-1:-1;;;;;142221:46:0;:13;:46::i;:::-;142207:60;;142420:3;142412:5;:11;142408:52;;;142447:1;142440:8;;;;;;;142408:52;142480:11;142494:47;142508:10;142520:2;:6;;;142494:47;;142528:2;:12;;;-1:-1:-1;;;;;142494:47:0;:13;:47::i;:::-;142480:61;;142567:3;142559:5;:11;:25;;142579:5;142559:25;;;142573:3;142559:25;142552:32;140823:1769;-1:-1:-1;;;;;;;;;140823:1769:0:o;140050:442::-;140189:4;140270:1;140261:5;:10;140257:54;;-1:-1:-1;140295:4:0;140288:11;;140257:54;140411:9;140381:27;140399:9;140381:15;:27;:::i;:::-;:39;140377:83;;;-1:-1:-1;140444:4:0;140437:11;;140377:83;-1:-1:-1;140479:5:0;140050:442;;;;;;:::o;3388:3640::-;4011:9;;;-1:-1:-1;;4018:1:0;4015;4097:20;4227:14;;;4215:27;;4207:36;;;4331:285;;4378:1;4368:156;;4421:10;4415:4;4408:24;4496:4;4490;4483:18;4368:156;-1:-1:-1;4556:14:0;;;4592:5;;4331:285;4740:2;4737:1;4734:9;4724:152;;4781:10;4775:4;4768:24;4852:4;4846;4839:18;4724:152;5139:1;5136;5133;5126:15;5290:1;5286:9;;;5279:17;;5383:9;;;;;6724:13;;;6716:22;;;6748:9;;;;6744:17;;;6763:1;6740:25;6712:54;6801:14;;6797:22;6679:167;5764:1;5771;5767:9;;5760:17;;6050:11;;;6043:19;;6034:29;6124:11;;;6117:19;;6108:29;6199:11;;;6192:19;;6183:29;6274:11;;;6267:19;;6258:29;6349:11;;;6342:19;;6333:29;6936:11;;;6929:19;;;6920:29;6433:539;3388:3640;;;;;:::o;196:131:1:-;-1:-1:-1;;;;;271:31:1;;261:42;;251:70;;317:1;314;307:12;332:118;418:5;411:13;404:21;397:5;394:32;384:60;;440:1;437;430:12;455:382;520:6;528;581:2;569:9;560:7;556:23;552:32;549:52;;;597:1;594;587:12;549:52;636:9;623:23;655:31;680:5;655:31;:::i;:::-;705:5;-1:-1:-1;762:2:1;747:18;;734:32;775:30;734:32;775:30;:::i;:::-;824:7;814:17;;;455:382;;;;;:::o;1312:247::-;1371:6;1424:2;1412:9;1403:7;1399:23;1395:32;1392:52;;;1440:1;1437;1430:12;1392:52;1479:9;1466:23;1498:31;1523:5;1498:31;:::i;1564:517::-;1635:6;1643;1651;1704:2;1692:9;1683:7;1679:23;1675:32;1672:52;;;1720:1;1717;1710:12;1672:52;1759:9;1746:23;1778:31;1803:5;1778:31;:::i;:::-;1828:5;-1:-1:-1;1885:2:1;1870:18;;1857:32;1898:30;1857:32;1898:30;:::i;:::-;1947:7;-1:-1:-1;2006:2:1;1991:18;;1978:32;2019:30;1978:32;2019:30;:::i;:::-;2068:7;2058:17;;;1564:517;;;;;:::o;2493:865::-;2594:6;2602;2610;2618;2626;2634;2687:3;2675:9;2666:7;2662:23;2658:33;2655:53;;;2704:1;2701;2694:12;2655:53;2743:9;2730:23;2762:31;2787:5;2762:31;:::i;:::-;2812:5;-1:-1:-1;2869:2:1;2854:18;;2841:32;2882:30;2841:32;2882:30;:::i;:::-;2493:865;;2931:7;;-1:-1:-1;;;;3011:2:1;2996:18;;2983:32;;3114:2;3099:18;;3086:32;;3217:3;3202:19;;3189:33;;-1:-1:-1;3321:3:1;3306:19;;;3293:33;;-1:-1:-1;2493:865:1:o;4808:644::-;4891:6;4899;4907;4915;4968:3;4956:9;4947:7;4943:23;4939:33;4936:53;;;4985:1;4982;4975:12;4936:53;5024:9;5011:23;5043:31;5068:5;5043:31;:::i;:::-;5093:5;-1:-1:-1;5150:2:1;5135:18;;5122:32;5163:30;5122:32;5163:30;:::i;:::-;5212:7;-1:-1:-1;5271:2:1;5256:18;;5243:32;5284:33;5243:32;5284:33;:::i;:::-;4808:644;;;;-1:-1:-1;5336:7:1;;5416:2;5401:18;5388:32;;-1:-1:-1;;4808:644:1:o;5457:127::-;5518:10;5513:3;5509:20;5506:1;5499:31;5549:4;5546:1;5539:15;5573:4;5570:1;5563:15;5589:125;5654:9;;;5675:10;;;5672:36;;;5688:18;;:::i;5927:128::-;5994:9;;;6015:11;;;6012:37;;;6029:18;;:::i;6430:885::-;6530:6;6590:2;6578:9;6569:7;6565:23;6561:32;6605:2;6602:22;;;6620:1;6617;6610:12;6602:22;-1:-1:-1;6669:2:1;6663:9;6711:2;6699:15;;6744:18;6729:34;;6765:22;;;6726:62;6723:185;;;6830:10;6825:3;6821:20;6818:1;6811:31;6865:4;6862:1;6855:15;6893:4;6890:1;6883:15;6723:185;6924:2;6917:22;6980:16;;7005:21;;7071:2;7056:18;;7050:25;7084:30;7050:25;7084:30;:::i;:::-;7142:2;7130:15;;7123:32;7200:2;7185:18;;7179:25;7213:30;7179:25;7213:30;:::i;:::-;7271:2;7259:15;;7252:32;7263:6;6430:885;-1:-1:-1;;;6430:885:1:o;7841:273::-;7909:6;7962:2;7950:9;7941:7;7937:23;7933:32;7930:52;;;7978:1;7975;7968:12;7930:52;8010:9;8004:16;8060:4;8053:5;8049:16;8042:5;8039:27;8029:55;;8080:1;8077;8070:12;8828:245;8895:6;8948:2;8936:9;8927:7;8923:23;8919:32;8916:52;;;8964:1;8961;8954:12;8916:52;8996:9;8990:16;9015:28;9037:5;9015:28;:::i;9078:251::-;9148:6;9201:2;9189:9;9180:7;9176:23;9172:32;9169:52;;;9217:1;9214;9207:12;9169:52;9249:9;9243:16;9268:31;9293:5;9268:31;:::i;9334:179::-;9412:13;;9465:22;9454:34;;9444:45;;9434:73;;9503:1;9500;9493:12;9434:73;9334:179;;;:::o;9518:571::-;9621:6;9629;9637;9645;9653;9706:3;9694:9;9685:7;9681:23;9677:33;9674:53;;;9723:1;9720;9713:12;9674:53;9746:39;9775:9;9746:39;:::i;:::-;9825:2;9810:18;;9804:25;9891:2;9876:18;;9870:25;9985:2;9970:18;;9964:25;9736:49;;-1:-1:-1;9804:25:1;;-1:-1:-1;9870:25:1;-1:-1:-1;9964:25:1;-1:-1:-1;10034:49:1;10078:3;10063:19;;10034:49;:::i;:::-;10024:59;;9518:571;;;;;;;;:::o;10094:168::-;10167:9;;;10198;;10215:15;;;10209:22;;10195:37;10185:71;;10236:18;;:::i;10267:375::-;10355:1;10373:5;10387:249;10408:1;10398:8;10395:15;10387:249;;;10458:4;10453:3;10449:14;10443:4;10440:24;10437:50;;;10467:18;;:::i;:::-;10517:1;10507:8;10503:16;10500:49;;;10531:16;;;;10500:49;10614:1;10610:16;;;;;10570:15;;10387:249;;;10267:375;;;;;;:::o;10647:902::-;10696:5;10726:8;10716:80;;-1:-1:-1;10767:1:1;10781:5;;10716:80;10815:4;10805:76;;-1:-1:-1;10852:1:1;10866:5;;10805:76;10897:4;10915:1;10910:59;;;;10983:1;10978:174;;;;10890:262;;10910:59;10940:1;10931:10;;10954:5;;;10978:174;11015:3;11005:8;11002:17;10999:43;;;11022:18;;:::i;:::-;-1:-1:-1;;11078:1:1;11064:16;;11137:5;;10890:262;;11236:2;11226:8;11223:16;11217:3;11211:4;11208:13;11204:36;11198:2;11188:8;11185:16;11180:2;11174:4;11171:12;11167:35;11164:77;11161:203;;;-1:-1:-1;11273:19:1;;;11349:5;;11161:203;11396:42;-1:-1:-1;;11421:8:1;11415:4;11396:42;:::i;:::-;11474:6;11470:1;11466:6;11462:19;11453:7;11450:32;11447:58;;;11485:18;;:::i;:::-;11523:20;;10647:902;-1:-1:-1;;;10647:902:1:o;11554:131::-;11614:5;11643:36;11670:8;11664:4;11643:36;:::i
Swarm Source
ipfs://0fb534bf7ea45618da3dd7c4b9832c59941c571ba8bcc22ba91ba38deb929174
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in MON
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.