Source Code
Latest 25 from a total of 212 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap And Deposit | 48452628 | 11 days ago | IN | 749.98047252 MON | 0.0455263 | ||||
| Swap And Deposit | 48055405 | 12 days ago | IN | 201,250.1184628 MON | 0.05892285 | ||||
| Swap And Deposit | 47142059 | 17 days ago | IN | 2 MON | 0.06832398 | ||||
| Swap And Deposit | 46387544 | 20 days ago | IN | 1 MON | 0.05010423 | ||||
| Swap And Deposit | 46363964 | 20 days ago | IN | 7,400 MON | 0.0818784 | ||||
| Swap And Deposit | 46110136 | 22 days ago | IN | 3,050 MON | 0.04078222 | ||||
| Swap And Deposit | 45837223 | 23 days ago | IN | 59,000 MON | 0.05883821 | ||||
| Swap And Deposit | 45833698 | 23 days ago | IN | 55,000 MON | 0.05904413 | ||||
| Swap And Deposit | 45245091 | 26 days ago | IN | 267.74435022 MON | 0.07441564 | ||||
| Swap And Deposit | 44557946 | 29 days ago | IN | 1 MON | 0.06291085 | ||||
| Swap And Deposit | 44557645 | 29 days ago | IN | 1 MON | 0.0623117 | ||||
| Swap And Deposit | 44557556 | 29 days ago | IN | 1 MON | 0.06966367 | ||||
| Swap And Deposit | 44317828 | 30 days ago | IN | 20,000 MON | 0.0920745 | ||||
| Swap And Deposit | 43864232 | 32 days ago | IN | 0.2 MON | 0.108199 | ||||
| Swap And Deposit | 43778217 | 32 days ago | IN | 44.53562838 MON | 0.07631681 | ||||
| Swap And Deposit | 43133954 | 35 days ago | IN | 35 MON | 0.08520329 | ||||
| Swap And Deposit | 43057551 | 36 days ago | IN | 5 MON | 0.1002331 | ||||
| Swap And Deposit | 43050489 | 36 days ago | IN | 12.23646073 MON | 0.11670996 | ||||
| Swap And Deposit | 42838514 | 37 days ago | IN | 7 MON | 0.04559236 | ||||
| Swap And Deposit | 42777621 | 37 days ago | IN | 61,000 MON | 0.07392705 | ||||
| Swap And Deposit | 42776067 | 37 days ago | IN | 29,000 MON | 0.08471351 | ||||
| Swap And Deposit | 42613647 | 38 days ago | IN | 100 MON | 0.0577494 | ||||
| Swap And Deposit | 42500870 | 38 days ago | IN | 1,500 MON | 0.08119373 | ||||
| Swap And Deposit | 41500110 | 43 days ago | IN | 2,282.95838064 MON | 0.08879339 | ||||
| Swap And Deposit | 41194755 | 44 days ago | IN | 36.36339199 MON | 0.05352195 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 48452628 | 11 days ago | 749.98047252 MON | ||||
| 48055405 | 12 days ago | 201,250.1184628 MON | ||||
| 47142059 | 17 days ago | 2 MON | ||||
| 46387544 | 20 days ago | 1 MON | ||||
| 46363964 | 20 days ago | 7,400 MON | ||||
| 46110136 | 22 days ago | 3,050 MON | ||||
| 45837223 | 23 days ago | 59,000 MON | ||||
| 45833698 | 23 days ago | 55,000 MON | ||||
| 45245091 | 26 days ago | 267.74435022 MON | ||||
| 44557946 | 29 days ago | 1 MON | ||||
| 44557645 | 29 days ago | 1 MON | ||||
| 44557556 | 29 days ago | 1 MON | ||||
| 44317828 | 30 days ago | 20,000 MON | ||||
| 43864232 | 32 days ago | 0.2 MON | ||||
| 43778217 | 32 days ago | 44.53562838 MON | ||||
| 43133954 | 35 days ago | 35 MON | ||||
| 43057551 | 36 days ago | 5 MON | ||||
| 43050489 | 36 days ago | 12.23646073 MON | ||||
| 42838514 | 37 days ago | 7 MON | ||||
| 42777621 | 37 days ago | 61,000 MON | ||||
| 42776067 | 37 days ago | 29,000 MON | ||||
| 42613647 | 38 days ago | 100 MON | ||||
| 42500870 | 38 days ago | 1,500 MON | ||||
| 41500110 | 43 days ago | 2,282.95838064 MON | ||||
| 41194755 | 44 days ago | 36.36339199 MON |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
NativeVaultZapper
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/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/IPluginDelegable.sol
interface IPluginDelegable {
/// @notice Returns whether a user or contract has the ability to act
/// on behalf of an account.
/// @param user The address to check whether `delegate` has delegation
/// permissions.
/// @param delegate The address that will be approved or restricted
/// from delegated actions on behalf of the caller.
/// @return result Indicates whether `delegate` is an approved delegate or
/// not of `user`, true = disabled, false = not disabled.
function isDelegate(
address user,
address delegate
) external view returns (bool result);
/// @notice Approves or restricts `delegate`'s authority to operate
/// on the caller's behalf.
/// @dev NOTE: Be careful who you approve here!
/// They can delay actions such as asset redemption through repeated
/// denial of service.
/// Emits a {DelegateApproval} event.
/// @param delegate The address that will be approved or restricted
/// from delegated actions on behalf of the caller.
/// @param isApproved Whether `delegate` is being approved or restricted
/// of authority to operate on behalf of caller.
function setDelegateApproval(address delegate, bool isApproved) external;
}
// contracts/interfaces/IWETH.sol
interface IWETH {
function balanceOf(address user) external view returns (uint256);
function deposit() external payable;
function withdraw(uint256 amount) external;
}
// 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/ReentrancyGuardTransient.sol
/// @notice Reentrancy guard mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ReentrancyGuardTransient.sol)
/// @dev Mai: Edited to always use transient storage.
abstract contract ReentrancyGuard {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Unauthorized reentrant call.
error Reentrancy();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Equivalent to: `uint32(bytes4(keccak256("Reentrancy()"))) | 1 << 71`.
/// 9 bytes is large enough to avoid collisions in practice,
/// but not too large to result in excessive bytecode bloat.
uint256 private constant _REENTRANCY_GUARD_SLOT = 0x8000000000ab143c06;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* REENTRANCY GUARD */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Guards a function from reentrancy.
modifier nonReentrant() virtual {
/// @solidity memory-safe-assembly
assembly {
if tload(_REENTRANCY_GUARD_SLOT) {
mstore(0x00, 0xab143c06) // `Reentrancy()`.
revert(0x1c, 0x04)
}
tstore(_REENTRANCY_GUARD_SLOT, address())
}
_;
/// @solidity memory-safe-assembly
assembly {
tstore(_REENTRANCY_GUARD_SLOT, 0)
}
}
/// @dev Guards a view function from read-only reentrancy.
modifier nonReadReentrant() virtual {
/// @solidity memory-safe-assembly
assembly {
if tload(_REENTRANCY_GUARD_SLOT) {
mstore(0x00, 0xab143c06) // `Reentrancy()`.
revert(0x1c, 0x04)
}
}
_;
}
}
// 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/interfaces/IVault.sol
interface IVault {
function deposit(
uint256 assets,
address receiver
) external payable returns (uint256 shares);
function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
function previewDeposit(
uint256 assets
) external returns (uint256 shares);
function previewRedeem(
uint256 shares
) external returns (uint256 assets);
function asset() external view returns (IERC20);
}
// 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/plugins/BaseZapper.sol
/// @title Curvance Base Zapper.
/// @notice Base contract for executing zap related actions.
/// @dev Curvance zapper contracts enshrine actions that
/// usually would require multiple sequential actions to facilitate,
/// specifically swapping, depositing, redemptions, and repayments.
///
/// Curvance token contracts facilitate these operations through our
/// standard contract interfaces and the plugin system.
///
/// Actions that include collateralization require plugin approval to the
/// corresponding zapper contract, to collateralize on behalf of another
/// user via a zapper both the zapper and the caller must have plugin
/// approval from the account being collateralized on behalf of.
///
/// The "base" contract is the basis on which all zapper contracts are
/// built on top of.
///
/// NOTE: Multicalling swapAndDeposit to perform multiple sequential
/// actions or to update oracle prices is blocked for native gas
/// token denominated actions to prevent double spend transaction
/// failures from delegate call.
///
abstract contract BaseZapper is Multicall, ReentrancyGuard {
/// TYPES ///
/// @param cToken The address of the cToken corresponding to the
/// redemption action.
/// @param shares The amount of shares to redeemed.
/// @param forceRedeemCollateral Whether the collateral should be always
/// reduced from caller's collateralized
/// shares.
struct RedeemAction {
address cToken;
uint256 shares;
bool forceRedeemCollateral;
}
/// CONSTANTS ///
/// @notice Curvance DAO hub.
ICentralRegistry public immutable centralRegistry;
/// @notice The address of wrapped native token on this chain.
address public immutable wrappedNative;
/// ERRORS ///
error BaseZapper__Unauthorized();
error BaseZapper__UnderlyingTokenIsNotInputToken();
error BaseZapper__ExecutionError();
error BaseZapper__InsufficientToRepay();
/// CONSTRUCTOR ///
/// @param cr The address of the Protocol Central Registry.
/// @param wNative The address of wrapped native token.
constructor(ICentralRegistry cr, address wNative) {
CentralRegistryLib._isCentralRegistry(cr);
centralRegistry = cr;
wrappedNative = wNative;
}
/// EXTERNAL FUNCTIONS ///
/// @notice Allows contract to receive native tokens.
receive() external payable {}
/// INTERNAL FUNCTIONS ///
/// @notice Routes `asset` token into `cToken`, for `receiver`.
/// @param cToken The Curvance cToken address.
/// @param asset The input token address, should match
/// `cToken`.asset().
/// @param assets The amount of `asset` to deposit into cToken
/// position.
/// @param expectedShares The minimum expected amount of shares received
/// from depositing `assets` of `asset` into
/// `cToken` position.
/// @param collateralizeFor Whether the deposit should be collateralized,
/// requires plugin approval.
/// @param receiver Address that should receive Curvance cTokens.
/// @return shares The output amount of shares received.
function _enterCurvance(
address cToken,
address asset,
uint256 assets,
uint256 expectedShares,
bool collateralizeFor,
address receiver
) internal returns (uint256 shares) {
_checkAddresses(cToken, asset);
// Approve `cToken` to take `asset`.
SwapperLib._approveIfNeeded(asset, cToken, assets);
// The user is trusting this plugin to not use their delegation
// approval for nefarious reasons such as keeping them stuck in
// positions, so lets validate that the receiver is a delegate
// as well.
if (collateralizeFor) {
// Enter Curvance position and collateralize it.
// This requires plugin approval for this zapper, and
// if its a different user calling on behalf of `receiver`
// we make sure that user also has delegation approved.
if (
msg.sender == receiver ||
IPluginDelegable(cToken).isDelegate(receiver, msg.sender)
) {
shares = ICToken(cToken).depositAsCollateralFor(
assets,
receiver
);
} else {
revert BaseZapper__Unauthorized();
}
} else {
// User wants to enter an uncollateralized a position so we dont
// care if they are zapping for themselves or someone else.
shares = ICToken(cToken).deposit(assets, receiver);
}
// Make sure sufficient shares were received from deposit action.
if (shares < expectedShares) {
revert BaseZapper__ExecutionError();
}
// Remove any leftover approval, if any.
SwapperLib._removeApprovalIfNeeded(asset, cToken);
}
/// @notice Exits a Curvance position.
/// @param cToken The address of the cToken to be redeemed from.
/// @param asset The expected asset of `cToken`.
/// @param shares The amount of shares to redeemed.
/// @param expectedAssets The amount of assets expected to be redeemed
/// on exiting Curvance position.
/// @param forceRedeemCollateral Whether the collateral should be always
/// reduced from callers collateralPosted.
/// @param receiver Address that should receive redeemed assets.
function _exitCurvance(
address cToken,
address asset,
uint256 shares,
uint256 expectedAssets,
bool forceRedeemCollateral,
address receiver
) internal {
_checkAddresses(cToken, asset);
uint256 assets;
// Transfer tokens exited to the Zapper.
if (forceRedeemCollateral) {
assets = ICToken(cToken).redeemCollateralFor(
shares,
address(this),
msg.sender
);
} else {
assets = ICToken(cToken).redeemFor(
shares,
address(this),
msg.sender
);
}
// Make sure sufficient assets were received from redemption action.
if (assets < expectedAssets) {
revert BaseZapper__ExecutionError();
}
// Return any excess assets remaining back to the user.
if (assets > expectedAssets) {
_transferToRecipient(asset, receiver, assets - expectedAssets);
}
}
/// @notice Repays Curvance lenders outstanding debt owed on behalf
/// of `receiver`.
/// @param borrowableCToken The Curvance token address to repay
/// outstanding debt to.
/// @param debtAsset The asset token for `borrowableCToken` to repay
/// debt in.
/// @param assetsHeld The amount of `debtAsset` on hand.
/// @param repayAssets The amount of debt to be repaid.
/// @param receiver Address that should have outstanding debt repaid.
/// @return The amount of `debtAsset` that was returned to `receiver`.
function _repayDebt(
address borrowableCToken,
address debtAsset,
uint256 assetsHeld,
uint256 repayAssets,
address receiver
) internal returns (uint256) {
_checkAddresses(borrowableCToken, debtAsset);
if (repayAssets == 0) {
// Accrue any interest owed so repayAssets includes all
// `receiver` debt.
repayAssets = IBorrowableCToken(borrowableCToken)
.debtBalanceUpdated(receiver);
}
// Revert if the swap experienced too much slippage.
if (assetsHeld < repayAssets) {
revert BaseZapper__InsufficientToRepay();
}
// Approve `debtAsset` transfer to cToken contract, if needed.
SwapperLib._approveIfNeeded(debtAsset, borrowableCToken, repayAssets);
// Execute repayment of outstanding debt.
IBorrowableCToken(borrowableCToken).repayFor(repayAssets, receiver);
// Remove any leftover approval, if any.
SwapperLib._removeApprovalIfNeeded(debtAsset, borrowableCToken);
assetsHeld -= repayAssets;
// Transfer any remaining `debtAsset` to caller, we return funds to
// caller instead of `receiver` for teams integrating on top of
// Curvance and may want to keep those funds.
if (assetsHeld > 0) {
_transferToRecipient(debtAsset, msg.sender, assetsHeld);
}
return assetsHeld;
}
/// @notice Prepares for an upcoming swap based on input parameters
/// accounting for both native gas token routing versus
/// erc20s.
/// @param inputToken The token being inputted into the upcoming swap.
/// @param inputAmount The amount of `inputToken` to be swapped.
/// @param depositAsWrappedNative Used when `inputToken` is the native gas
/// token, indicates depositing native token
/// into wrapped version or not.
function _prepareSwap(
address inputToken,
uint256 inputAmount,
bool depositAsWrappedNative
) internal {
if (CommonLib._isNative(inputToken)) {
// Validate `inputAmount` token attached equal to `msg.value`.
if (inputAmount != msg.value) {
revert BaseZapper__ExecutionError();
}
if (depositAsWrappedNative) {
IWETH(wrappedNative).deposit{ value: inputAmount }();
}
return;
}
// For ERC20 input flows, there should be no msg.value.
if (msg.value != 0) {
revert BaseZapper__ExecutionError();
}
SafeTransferLib.safeTransferFrom(
inputToken,
msg.sender,
address(this),
inputAmount
);
}
/// @notice Checks whether address parameters for a particular zapper
/// action on valid.
/// @param cToken The Curvance cToken address.
/// @param asset The input token address, should match `cToken`.asset().
function _checkAddresses(address cToken, address asset) internal view {
// Validate `cToken` is not the zero address.
if (cToken == address(0)) {
revert BaseZapper__ExecutionError();
}
// Validate `cToken` is listed in the Market Manager.
IMarketManager mm = ICToken(cToken).marketManager();
if (
!centralRegistry.isMarketManager(address(mm)) ||
!mm.isListed(cToken)
) {
revert BaseZapper__Unauthorized();
}
// Validate `asset` matches asset of cToken contract.
if (asset != ICToken(cToken).asset()) {
revert BaseZapper__UnderlyingTokenIsNotInputToken();
}
}
/// @notice Helper function for efficiently transferring tokens
/// to desired user.
/// @param token The token to transfer to `receiver`,
/// this can be the network gas token.
/// @param receiver The user receiving `token`.
/// @param amount The amount of `token` to be transferred to `receiver`.
function _transferToRecipient(
address token,
address receiver,
uint256 amount
) internal {
// If the token to refund is the chains' native gas token we wrap
// then transfer it to prevent callback attack vectors.
if (CommonLib._isNative(token)) {
IWETH(wrappedNative).deposit{ value: amount }();
token = wrappedNative;
}
SafeTransferLib.safeTransfer(token, receiver, amount);
}
/// @notice Returns the Central Registry contract in interface form.
function _getCentralRegistry()
internal
view
override
returns (ICentralRegistry)
{
return centralRegistry;
}
}
// contracts/plugins/market/SimpleZapper.sol
/// @title Curvance Simple Zapper.
/// @notice Simple Asset-specific contract for executing zap related
/// actions.
/// @dev Curvance zapper contracts enshrine actions that
/// usually would require multiple sequential actions to facilitate,
/// specifically swapping, depositing, redemptions, and repayments.
///
/// Curvance token contracts facilitate these operations through our
/// standard contract interfaces and the plugin system.
///
/// Actions that include collateralization require plugin approval to the
/// corresponding zapper contract, to collateralize on behalf of another
/// user via a zapper both the zapper and the caller must have plugin
/// approval from the account being collateralized on behalf of.
///
/// The "Simple" contract is the zapper for working with generic
/// non-native erc20 tokens such as USDC or WETH.
///
contract SimpleZapper is BaseZapper {
/// CONSTRUCTOR ///
/// @param cr The address of the Protocol Central Registry.
/// @param wNative The address of wrapped native token.
constructor(ICentralRegistry cr, address wNative) BaseZapper(cr, wNative) {}
/// EXTERNAL FUNCTIONS ///
/// @notice Swaps then deposits `swapAction.outputToken`, a cToken asset,
/// and enters into Curvance position, for `receiver`.
/// @dev Requires plugin approval for collateralization.
/// @param cToken The Curvance token (cToken) address to deposit into.
/// @param depositAsWrappedNative Used when `inputToken` is the native gas
/// token, indicates depositing native token
/// into wrapped version or not.
/// @param swapAction Instructions for executing a swap into collateral
/// asset.
/// 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.
/// @param expectedShares The minimum expected amount of shares received
/// from depositing `amount` of
/// `swapAction.outputToken` into `cToken` position.
/// @param collateralizeFor Whether the deposit should be collateralized,
/// requires plugin approval.
/// @param receiver Address that should receive `cToken` shares.
/// @return outAmount The `cToken` output shares received by `receiver`.
function swapAndDeposit(
address cToken,
bool depositAsWrappedNative,
SwapperLib.Swap memory swapAction,
uint256 expectedShares,
bool collateralizeFor,
address receiver
) external virtual payable nonReentrant returns (uint256 outAmount) {
_prepareSwap(
swapAction.inputToken,
swapAction.inputAmount,
depositAsWrappedNative
);
// If we are trying to deposit wrapped native, we may be able to skip
// a swapper call by changing the input token and checking versus
// output token.
if (CommonLib._isNative(swapAction.inputToken) && depositAsWrappedNative) {
// Switch inputToken to wrapped native token address.
swapAction.inputToken = address(wrappedNative);
}
if (CommonLib._isMatchingToken(swapAction.inputToken, swapAction.outputToken)) {
outAmount = swapAction.inputAmount;
} else {
// Execute swap into cToken asset.
outAmount = SwapperLib._swapUnsafe(centralRegistry, swapAction);
}
// Enter Curvance position.
outAmount = _enterCurvance(
cToken,
swapAction.outputToken,
outAmount,
expectedShares,
collateralizeFor,
receiver
);
}
/// @notice Swaps then repays outstanding debt for `receiver`.
/// @dev Sends any excess debt token to `receiver`.
/// @param borrowableCToken The Curvance token address to repay debt to.
/// @param depositAsWrappedNative Used when `inputToken` is the native gas
/// token, indicates depositing native token
/// into wrapped version or not.
/// @param swapAction Instructions for executing a swap into debt asset.
/// 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.
/// @param repayAssets The amount of debt to be repaid, in assets.
/// @param receiver Address that should have its outstanding debt repaid.
/// @return outAmount The excess amount of debt token that was returned to
/// `receiver`.
function swapAndRepay(
address borrowableCToken,
bool depositAsWrappedNative,
SwapperLib.Swap memory swapAction,
uint256 repayAssets,
address receiver
) external payable nonReentrant returns (uint256 outAmount) {
_prepareSwap(
swapAction.inputToken,
swapAction.inputAmount,
depositAsWrappedNative
);
// If we are trying to repay wrapped native, we may be able to skip
// a swapper call by changing the input token and checking versus
// output token.
if (CommonLib._isNative(swapAction.inputToken) && depositAsWrappedNative) {
// Switch inputToken to wrapped native token address.
swapAction.inputToken = address(wrappedNative);
}
if (CommonLib._isMatchingToken(swapAction.inputToken, swapAction.outputToken)) {
outAmount = swapAction.inputAmount;
} else {
// Execute swap into cToken asset.
outAmount = SwapperLib._swapUnsafe(centralRegistry, swapAction);
}
// Repay `repayAssets` outstanding debt, 0 defaults to repaying
// everything.
outAmount = _repayDebt(
borrowableCToken,
swapAction.outputToken,
outAmount,
repayAssets,
receiver
);
}
/// @notice Withdraws from a Curvance position, and swaps it into
/// desired token (swapAction.outputToken).
/// @dev Requires plugin approval for redemption.
/// @param redeemAction Instructions for a redemption action containing:
/// cToken The address of the cToken corresponding to
/// the redemption action.
/// shares The amount of shares to redeemed.
/// forceRedeemCollateral Whether the collateral
/// should be always reduced
/// from caller's collateralized
/// shares.
/// @param swapAction Instructions for executing a swap into debt asset.
/// 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.
/// @param receiver Address that should receive `swapAction.outputToken`.
/// @return outAmount The amount of `swapAction.outputToken` that was
/// received by `receiver`.
function redeemAndSwap(
RedeemAction calldata redeemAction,
SwapperLib.Swap memory swapAction,
address receiver
) external nonReentrant returns (uint256 outAmount) {
// Exit Curvance position.
_exitCurvance(
redeemAction.cToken,
swapAction.inputToken,
redeemAction.shares,
swapAction.inputAmount,
redeemAction.forceRedeemCollateral,
receiver
);
if (CommonLib._isMatchingToken(swapAction.inputToken, swapAction.outputToken)) {
outAmount = swapAction.inputAmount;
} else {
outAmount = SwapperLib._swapUnsafe(centralRegistry, swapAction);
}
_transferToRecipient(swapAction.outputToken, receiver, outAmount);
}
/// @notice Withdraws a Curvance position, swaps it into
/// desired token (swapAction.outputToken) and then deposits
/// it into a new position.
/// @dev Requires plugin approval for redemption.
/// @param cToken The Curvance token (cToken) address.
/// @param redeemAction Instructions for a redemption action containing:
/// cToken The address of the cToken corresponding to
/// the redemption action.
/// shares The amount of shares to redeemed.
/// forceRedeemCollateral Whether the collateral
/// should be always reduced
/// from caller's collateralized
/// shares.
/// @param expectedShares The minimum expected amount of shares received
/// from depositing `amount` of
/// `swapAction.outputToken` into `cToken` position.
/// @param collateralizeFor Whether the deposit should be collateralized,
/// requires plugin approval.
/// @param receiver Address that should receive `cToken` shares.
/// @return outAmount The `cToken` output shares received by `receiver`.
function redeemSwapAndDeposit(
address cToken,
RedeemAction calldata redeemAction,
SwapperLib.Swap memory swapAction,
uint256 expectedShares,
bool collateralizeFor,
address receiver
) external nonReentrant returns (uint256 outAmount) {
// Exit Curvance position.
_exitCurvance(
redeemAction.cToken,
swapAction.inputToken,
redeemAction.shares,
swapAction.inputAmount,
redeemAction.forceRedeemCollateral,
receiver
);
if (CommonLib._isMatchingToken(swapAction.inputToken, swapAction.outputToken)) {
outAmount = swapAction.inputAmount;
} else {
// Execute swap into `swapAction.outputToken` which should be
// new cToken asset.
outAmount = SwapperLib._swapUnsafe(centralRegistry, swapAction);
}
// Enter Curvance position.
outAmount = _enterCurvance(
cToken,
swapAction.outputToken,
outAmount,
expectedShares,
collateralizeFor,
receiver
);
}
}
// contracts/plugins/market/NativeVaultZapper.sol
/// @title Curvance Native Vault Zapper.
/// @notice Native Vault-specific contract for executing zap related
/// actions.
/// @dev Curvance zapper contracts enshrine actions that
/// usually would require multiple sequential actions to facilitate,
/// specifically swapping, depositing, redemptions, and repayments.
///
/// Curvance token contracts facilitate these operations through our
/// standard contract interfaces and the plugin system.
///
/// Actions that include collateralization require plugin approval to the
/// corresponding zapper contract, to collateralize on behalf of another
/// user via a zapper both the zapper and the caller must have plugin
/// approval from the account being collateralized on behalf of.
///
/// The "Native Vault" contract is the zapper for working with
/// native-token based erc4626-like tokens such as shMON or aprMON. No type
/// specific "redeemAnd" is written as execution is intended to be the
/// as the "simple" zappers where redemptions are done directly on the
/// corresponding cToken.
///
contract NativeVaultZapper is SimpleZapper {
/// CONSTRUCTOR ///
/// @param cr The address of the Protocol Central Registry.
/// @param wNative The address of wrapped native token.
constructor(ICentralRegistry cr, address wNative) SimpleZapper(cr, wNative) {}
/// EXTERNAL FUNCTIONS ///
/// @notice Swaps, then deposits `swapAction.outputToken`, a cToken
/// asset, and enters into Curvance position, for `receiver`.
/// @dev Requires plugin approval for collateralization.
/// @param cToken The Curvance token (cToken) address to deposit into.
/// @param swapAction Instructions for executing a swap into collateral
/// asset.
/// 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.
/// @param expectedShares The minimum expected amount of shares received
/// from depositing `amount` of
/// `swapAction.outputToken` into `cToken` position.
/// @param collateralizeFor Whether the zapped deposit should be
/// collateralized afterwards.
/// @param receiver Address that should receive `cToken` shares.
/// @return outAmount The `cToken` output shares received by `receiver`.
function swapAndDeposit(
address cToken,
bool /* depositAsWrappedNative */,
SwapperLib.Swap memory swapAction,
uint256 expectedShares,
bool collateralizeFor,
address receiver
) external override payable nonReentrant returns (uint256 outAmount) {
_prepareSwap(swapAction.inputToken, swapAction.inputAmount, false);
if (!CommonLib._isNative(swapAction.outputToken)) {
revert BaseZapper__UnderlyingTokenIsNotInputToken();
}
if (CommonLib._isMatchingToken(swapAction.inputToken, swapAction.outputToken)) {
outAmount = swapAction.inputAmount;
} else if (swapAction.inputToken == wrappedNative) {
// Unwrap native
IWETH(wrappedNative).withdraw(swapAction.inputAmount);
outAmount = swapAction.inputAmount;
} else {
// Execute swap into cToken asset.
outAmount = SwapperLib._swapUnsafe(centralRegistry, swapAction);
}
address vault = ICToken(cToken).asset();
// Deposit into vault.
outAmount = IVault(vault)
.deposit{value: outAmount}(outAmount, address(this));
// Enter Curvance position.
outAmount = _enterCurvance(
cToken,
vault,
outAmount,
expectedShares,
collateralizeFor,
receiver
);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract ICentralRegistry","name":"cr","type":"address"},{"internalType":"address","name":"wNative","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BaseZapper__ExecutionError","type":"error"},{"inputs":[],"name":"BaseZapper__InsufficientToRepay","type":"error"},{"inputs":[],"name":"BaseZapper__Unauthorized","type":"error"},{"inputs":[],"name":"BaseZapper__UnderlyingTokenIsNotInputToken","type":"error"},{"inputs":[],"name":"CentralRegistryLib__InvalidCentralRegistry","type":"error"},{"inputs":[],"name":"LowLevelCallsHelper__CallFailed","type":"error"},{"inputs":[],"name":"LowLevelCallsHelper__InsufficientBalance","type":"error"},{"inputs":[],"name":"Multicall__InvalidTarget","type":"error"},{"inputs":[],"name":"Multicall__UnknownCalldata","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"SwapperLib__SameTokens","type":"error"},{"inputs":[],"name":"SwapperLib__UnknownCalldata","type":"error"},{"inputs":[],"name":"centralRegistry","outputs":[{"internalType":"contract ICentralRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bool","name":"isPriceUpdate","type":"bool"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Multicall.MulticallAction[]","name":"calls","type":"tuple[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"bool","name":"forceRedeemCollateral","type":"bool"}],"internalType":"struct BaseZapper.RedeemAction","name":"redeemAction","type":"tuple"},{"components":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"slippage","type":"uint256"},{"internalType":"bytes","name":"call","type":"bytes"}],"internalType":"struct SwapperLib.Swap","name":"swapAction","type":"tuple"},{"internalType":"address","name":"receiver","type":"address"}],"name":"redeemAndSwap","outputs":[{"internalType":"uint256","name":"outAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"components":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"bool","name":"forceRedeemCollateral","type":"bool"}],"internalType":"struct BaseZapper.RedeemAction","name":"redeemAction","type":"tuple"},{"components":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"slippage","type":"uint256"},{"internalType":"bytes","name":"call","type":"bytes"}],"internalType":"struct SwapperLib.Swap","name":"swapAction","type":"tuple"},{"internalType":"uint256","name":"expectedShares","type":"uint256"},{"internalType":"bool","name":"collateralizeFor","type":"bool"},{"internalType":"address","name":"receiver","type":"address"}],"name":"redeemSwapAndDeposit","outputs":[{"internalType":"uint256","name":"outAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"bool","name":"","type":"bool"},{"components":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"slippage","type":"uint256"},{"internalType":"bytes","name":"call","type":"bytes"}],"internalType":"struct SwapperLib.Swap","name":"swapAction","type":"tuple"},{"internalType":"uint256","name":"expectedShares","type":"uint256"},{"internalType":"bool","name":"collateralizeFor","type":"bool"},{"internalType":"address","name":"receiver","type":"address"}],"name":"swapAndDeposit","outputs":[{"internalType":"uint256","name":"outAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"borrowableCToken","type":"address"},{"internalType":"bool","name":"depositAsWrappedNative","type":"bool"},{"components":[{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"slippage","type":"uint256"},{"internalType":"bytes","name":"call","type":"bytes"}],"internalType":"struct SwapperLib.Swap","name":"swapAction","type":"tuple"},{"internalType":"uint256","name":"repayAssets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"swapAndRepay","outputs":[{"internalType":"uint256","name":"outAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"wrappedNative","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c060405234801561000f575f5ffd5b50604051611fe9380380611fe983398101604081905261002e91610177565b8181818161003b82610057565b6001600160a01b039182166080521660a052506101af92505050565b610068816399011ef160e01b610088565b610085576040516369b5e45b60e11b815260040160405180910390fd5b50565b5f610092836100aa565b80156100a357506100a383836100dd565b9392505050565b5f6100bc826301ffc9a760e01b6100dd565b80156100d757506100d5826001600160e01b03196100dd565b155b92915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f51905082801561014d575060208210155b801561015857505f81115b979650505050505050565b6001600160a01b0381168114610085575f5ffd5b5f5f60408385031215610188575f5ffd5b825161019381610163565b60208401519092506101a481610163565b809150509250929050565b60805160a051611dc66102235f395f818161017b015281816101fc015281816103280152818161036c015281816109360152818161106a01526110da01525f818160c601528181610245015281816103dc0152818161058501528181610654015281816106a2015261148d0152611dc65ff3fe608060405260043610610071575f3560e01c80639d2c4fe31161004c5780639d2c4fe314610100578063d4b386d11461011f578063e8bbf5d71461013e578063eb6d3a111461016a575f5ffd5b806367a3a4841461007c578063801c2e9f146100a25780638f73dcfa146100b5575f5ffd5b3661007857005b5f5ffd5b61008f61008a36600461187f565b61019d565b6040519081526020015b60405180910390f35b61008f6100b03660046118fa565b610295565b3480156100c0575f5ffd5b506100e87f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610099565b34801561010b575f5ffd5b5061008f61011a36600461199c565b610502565b34801561012a575f5ffd5b5061008f610139366004611a1a565b6105d7565b348015610149575f5ffd5b5061015d610158366004611a78565b61069e565b6040516100999190611b15565b348015610175575f5ffd5b506100e87f000000000000000000000000000000000000000000000000000000000000000081565b5f688000000000ab143c065c156101bb5763ab143c065f526004601cfd5b30688000000000ab143c065d6101d9845f0151856020015187610900565b83516101e4906109d5565b80156101ed5750845b1561021f576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001684525b610230845f01518560400151610a0e565b156102405750602083015161026d565b61026a7f000000000000000000000000000000000000000000000000000000000000000085610a5e565b90505b61027e868560400151838686610c00565b90505f688000000000ab143c065d95945050505050565b5f688000000000ab143c065c156102b35763ab143c065f526004601cfd5b30688000000000ab143c065d6102d1855f015186602001515f610900565b6102de85604001516109d5565b6102fb5760405163ecaf3a9760e01b815260040160405180910390fd5b61030c855f01518660400151610a0e565b1561031c57506020840151610404565b84516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169116036103d7576020850151604051632e1a7d4d60e01b815260048101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d906024015f604051808303815f87803b1580156103b5575f5ffd5b505af11580156103c7573d5f5f3e3d5ffd5b5050505084602001519050610404565b6104017f000000000000000000000000000000000000000000000000000000000000000086610a5e565b90505b5f876001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610441573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104659190611b78565b604051636e553f6560e01b8152600481018490523060248201529091506001600160a01b03821690636e553f6590849060440160206040518083038185885af11580156104b4573d5f5f3e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906104d99190611b93565b91506104e9888284888888610d38565b9150505f688000000000ab143c065d9695505050505050565b5f688000000000ab143c065c156105205763ab143c065f526004601cfd5b30688000000000ab143c065d61055f61053c6020880188611baa565b8651602080890151908a01359061055960608c0160408d01611bc5565b87610f11565b610570855f01518660400151610a0e565b15610580575060208401516105ad565b6105aa7f000000000000000000000000000000000000000000000000000000000000000086610a5e565b90505b6105bf87866040015183878787610d38565b90505f688000000000ab143c065d9695505050505050565b5f688000000000ab143c065c156105f55763ab143c065f526004601cfd5b30688000000000ab143c065d61062e6106116020860186611baa565b8451602080870151908801359061055960608a0160408b01611bc5565b61063f835f01518460400151610a0e565b1561064f5750602082015161067c565b6106797f000000000000000000000000000000000000000000000000000000000000000084610a5e565b90505b61068b8360400151838361105a565b5f688000000000ab143c065d9392505050565b60607f000000000000000000000000000000000000000000000000000000000000000082806001600160401b038111156106da576106da611729565b60405190808252806020026020018201604052801561070d57816020015b60608152602001906001900390816106f85790505b5060408051606080820183525f80835260208301819052928201529194505b828110156108f65786868281811061074657610746611be0565b90506020028101906107589190611bf4565b61076190611c12565b915081602001511561089857815160405163191d0cc560e11b81526001600160a01b0391821660048201525f9186169063323a198a90602401602060405180830381865afa1580156107b5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d99190611b78565b90506001600160a01b03811661080257604051632f3285fb60e21b815260040160405180910390fd5b8251604080850151905163bd0226d760e01b81526001600160a01b0384169263bd0226d7926108379233929190600401611c97565b5f604051808303815f87803b15801561084e575f5ffd5b505af1158015610860573d5f5f3e3d5ffd5b50505050610875835f01518460400151611107565b86838151811061088757610887611be0565b6020026020010181905250506108ee565b81516001600160a01b031630146108c257604051637720ccd960e01b815260040160405180910390fd5b6108d030836040015161117c565b8582815181106108e2576108e2611be0565b60200260200101819052505b60010161072c565b5050505092915050565b610909836109d5565b156109aa5734821461092e57604051630fc1653d60e11b815260040160405180910390fd5b80156109a5577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004015f604051808303818588803b15801561098d575f5ffd5b505af115801561099f573d5f5f3e3d5ffd5b50505050505b505050565b34156109c957604051630fc1653d60e11b815260040160405180910390fd5b6109a5833330856111d0565b5f6001600160a01b0382161580610a08575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038316145b92915050565b5f816001600160a01b0316836001600160a01b031603610a3057506001610a08565b610a39836109d5565b8015610a495750610a49826109d5565b15610a5657506001610a08565b505f92915050565b604081015181515f9190610a728183610a0e565b15610a9057604051636991e51560e11b815260040160405180910390fd5b6060840151604051631d4686fd60e31b81526001600160a01b0391821660048201525f9187169063ea3437e890602401602060405180830381865afa158015610adb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aff9190611b78565b90506001600160a01b038116610b2857604051637409771560e11b815260040160405180910390fd5b60405163383d5bf360e11b81526001600160a01b0382169063707ab7e690610b569088903090600401611cc2565b5f604051808303815f87803b158015610b6d575f5ffd5b505af1158015610b7f573d5f5f3e3d5ffd5b50505050610b96828660600151876020015161121f565b5f610ba084611237565b90505f610bac846109d5565b610bb6575f610bbc565b86602001515b9050610bd187606001518860a00151836112b7565b50610be0848860600151611350565b81610bea86611237565b610bf49190611d40565b98975050505050505050565b5f610c0b86866113e3565b825f03610c7e576040516357d159d560e01b81526001600160a01b0383811660048301528716906357d159d5906024016020604051808303815f875af1158015610c57573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7b9190611b93565b92505b82841015610c9f576040516367d8a00f60e01b815260040160405180910390fd5b610caa85878561121f565b604051632796469160e21b8152600481018490526001600160a01b038381166024830152871690639e591a44906044015f604051808303815f87803b158015610cf1575f5ffd5b505af1158015610d03573d5f5f3e3d5ffd5b50505050610d118587611350565b610d1b8385611d40565b93508315610d2e57610d2e85338661105a565b5091949350505050565b5f610d4387876113e3565b610d4e86888761121f565b8215610e6957336001600160a01b0383161480610dd45750604051635fec5d0b60e01b81526001600160a01b038381166004830152336024830152881690635fec5d0b90604401602060405180830381865afa158015610db0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dd49190611d5f565b15610e505760405163b3bffb4560e01b8152600481018690526001600160a01b03838116602483015288169063b3bffb45906044016020604051808303815f875af1158015610e25573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e499190611b93565b9050610edc565b604051630ba2198760e21b815260040160405180910390fd5b604051636e553f6560e01b8152600481018690526001600160a01b038381166024830152881690636e553f65906044016020604051808303815f875af1158015610eb5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ed99190611b93565b90505b83811015610efd57604051630fc1653d60e11b815260040160405180910390fd5b610f078688611350565b9695505050505050565b610f1b86866113e3565b5f8215610f9d57604051636779db5b60e01b8152600481018690523060248201523360448201526001600160a01b03881690636779db5b906064016020604051808303815f875af1158015610f72573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f969190611b93565b9050611014565b604051630b817f5160e31b8152600481018690523060248201523360448201526001600160a01b03881690635c0bfa88906064016020604051808303815f875af1158015610fed573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110119190611b93565b90505b8381101561103557604051630fc1653d60e11b815260040160405180910390fd5b8381111561105157611051868361104c8785611d40565b61105a565b50505050505050565b611063836109d5565b156110fc577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b1580156110c1575f5ffd5b505af11580156110d3573d5f5f3e3d5ffd5b50505050507f000000000000000000000000000000000000000000000000000000000000000092505b6109a5838383611618565b60605f5f846001600160a01b03165f856040516111249190611d7a565b5f6040518083038185875af1925050503d805f811461115e576040519150601f19603f3d011682016040523d82523d5f602084013e611163565b606091505b5091509150611173858383611658565b95945050505050565b60605f5f846001600160a01b0316846040516111989190611d7a565b5f60405180830381855af49150503d805f811461115e576040519150601f19603f3d011682016040523d82523d5f602084013e611163565b60405181606052826040528360601b602c526323b872dd60601b600c5260205f6064601c5f895af13d1560015f5114171661121257637939f4245f526004601cfd5b5f60605260405250505050565b611228836109d5565b6109a5576109a58383836116a0565b5f611241826109d5565b6112b0576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611287573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112ab9190611b93565b610a08565b4792915050565b6060814710156112da5760405163595909b560e11b815260040160405180910390fd5b5f5f856001600160a01b031684866040516112f59190611d7a565b5f6040518083038185875af1925050503d805f811461132f576040519150601f19603f3d011682016040523d82523d5f602084013e611334565b606091505b5091509150611344868383611658565b925050505b9392505050565b611359826109d5565b6113df57604051636eb1769f60e11b81523060048201526001600160a01b0382811660248301525f919084169063dd62ed3e90604401602060405180830381865afa1580156113aa573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113ce9190611b93565b11156113df576113df82825f6116a0565b5050565b6001600160a01b03821661140a57604051630fc1653d60e11b815260040160405180910390fd5b5f826001600160a01b03166341ed2c126040518163ffffffff1660e01b8152600401602060405180830381865afa158015611447573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061146b9190611b78565b604051637d5528bd60e01b81526001600160a01b0380831660048301529192507f000000000000000000000000000000000000000000000000000000000000000090911690637d5528bd90602401602060405180830381865afa1580156114d4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114f89190611d5f565b15806115695750604051637bca031760e11b81526001600160a01b03848116600483015282169063f794062e90602401602060405180830381865afa158015611543573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115679190611d5f565b155b1561158757604051630ba2198760e21b815260040160405180910390fd5b826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e79190611b78565b6001600160a01b0316826001600160a01b0316146109a55760405163ecaf3a9760e01b815260040160405180910390fd5b816014528060345263a9059cbb60601b5f5260205f604460105f875af13d1560015f5114171661164f576390b8ec185f526004601cfd5b5f603452505050565b606061166483836116d7565b815115801561167b57506001600160a01b0384163b155b15611699576040516314859aeb60e21b815260040160405180910390fd5b5092915050565b816014528060345263095ea7b360601b5f5260205f604460105f875af13d1560015f5114171661164f57633e3f8f735f526004601cfd5b816113df5780515f036116fd576040516314859aeb60e21b815260040160405180910390fd5b805181602001fd5b6001600160a01b0381168114611719575f5ffd5b50565b8015158114611719575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b038111828210171561175f5761175f611729565b60405290565b5f82601f830112611774575f5ffd5b81356001600160401b0381111561178d5761178d611729565b604051601f8201601f19908116603f011681016001600160401b03811182821017156117bb576117bb611729565b6040528181528382016020018510156117d2575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f60c082840312156117fe575f5ffd5b61180661173d565b9050813561181381611705565b815260208281013590820152604082013561182d81611705565b6040820152606082013561184081611705565b60608201526080828101359082015260a08201356001600160401b03811115611867575f5ffd5b61187384828501611765565b60a08301525092915050565b5f5f5f5f5f60a08688031215611893575f5ffd5b853561189e81611705565b945060208601356118ae8161171c565b935060408601356001600160401b038111156118c8575f5ffd5b6118d4888289016117ee565b9350506060860135915060808601356118ec81611705565b809150509295509295909350565b5f5f5f5f5f5f60c0878903121561190f575f5ffd5b863561191a81611705565b9550602087013561192a8161171c565b945060408701356001600160401b03811115611944575f5ffd5b61195089828a016117ee565b9450506060870135925060808701356119688161171c565b915060a087013561197881611705565b809150509295509295509295565b5f60608284031215611996575f5ffd5b50919050565b5f5f5f5f5f5f61010087890312156119b2575f5ffd5b86356119bd81611705565b95506119cc8860208901611986565b945060808701356001600160401b038111156119e6575f5ffd5b6119f289828a016117ee565b94505060a0870135925060c0870135611a0a8161171c565b915060e087013561197881611705565b5f5f5f60a08486031215611a2c575f5ffd5b611a368585611986565b925060608401356001600160401b03811115611a50575f5ffd5b611a5c868287016117ee565b9250506080840135611a6d81611705565b809150509250925092565b5f5f60208385031215611a89575f5ffd5b82356001600160401b03811115611a9e575f5ffd5b8301601f81018513611aae575f5ffd5b80356001600160401b03811115611ac3575f5ffd5b8560208260051b8401011115611ad7575f5ffd5b6020919091019590945092505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015611b6c57603f19878603018452611b57858351611ae7565b94506020938401939190910190600101611b3b565b50929695505050505050565b5f60208284031215611b88575f5ffd5b815161134981611705565b5f60208284031215611ba3575f5ffd5b5051919050565b5f60208284031215611bba575f5ffd5b813561134981611705565b5f60208284031215611bd5575f5ffd5b81356113498161171c565b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112611c08575f5ffd5b9190910192915050565b5f60608236031215611c22575f5ffd5b604051606081016001600160401b0381118282101715611c4457611c44611729565b6040528235611c5281611705565b81526020830135611c628161171c565b602082015260408301356001600160401b03811115611c7f575f5ffd5b611c8b36828601611765565b60408301525092915050565b6001600160a01b038481168252831660208201526060604082018190525f9061117390830184611ae7565b6040815260018060a01b0383511660408201526020830151606082015260018060a01b03604084015116608082015260018060a01b0360608401511660a0820152608083015160c08201525f60a084015160c060e0840152611d28610100840182611ae7565b91505061134960208301846001600160a01b03169052565b81810381811115610a0857634e487b7160e01b5f52601160045260245ffd5b5f60208284031215611d6f575f5ffd5b81516113498161171c565b5f82518060208501845e5f92019182525091905056fea26469706673582212208de869caa2e008353a01f58886a1c17bd57fea9e7129e0511f178b38a70da77e64736f6c634300081c00330000000000000000000000001310f352f1389969ece6741671c4b919523912ff0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a
Deployed Bytecode
0x608060405260043610610071575f3560e01c80639d2c4fe31161004c5780639d2c4fe314610100578063d4b386d11461011f578063e8bbf5d71461013e578063eb6d3a111461016a575f5ffd5b806367a3a4841461007c578063801c2e9f146100a25780638f73dcfa146100b5575f5ffd5b3661007857005b5f5ffd5b61008f61008a36600461187f565b61019d565b6040519081526020015b60405180910390f35b61008f6100b03660046118fa565b610295565b3480156100c0575f5ffd5b506100e87f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff81565b6040516001600160a01b039091168152602001610099565b34801561010b575f5ffd5b5061008f61011a36600461199c565b610502565b34801561012a575f5ffd5b5061008f610139366004611a1a565b6105d7565b348015610149575f5ffd5b5061015d610158366004611a78565b61069e565b6040516100999190611b15565b348015610175575f5ffd5b506100e87f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a81565b5f688000000000ab143c065c156101bb5763ab143c065f526004601cfd5b30688000000000ab143c065d6101d9845f0151856020015187610900565b83516101e4906109d5565b80156101ed5750845b1561021f576001600160a01b037f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a1684525b610230845f01518560400151610a0e565b156102405750602083015161026d565b61026a7f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff85610a5e565b90505b61027e868560400151838686610c00565b90505f688000000000ab143c065d95945050505050565b5f688000000000ab143c065c156102b35763ab143c065f526004601cfd5b30688000000000ab143c065d6102d1855f015186602001515f610900565b6102de85604001516109d5565b6102fb5760405163ecaf3a9760e01b815260040160405180910390fd5b61030c855f01518660400151610a0e565b1561031c57506020840151610404565b84516001600160a01b037f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a81169116036103d7576020850151604051632e1a7d4d60e01b815260048101919091527f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a6001600160a01b031690632e1a7d4d906024015f604051808303815f87803b1580156103b5575f5ffd5b505af11580156103c7573d5f5f3e3d5ffd5b5050505084602001519050610404565b6104017f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff86610a5e565b90505b5f876001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610441573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104659190611b78565b604051636e553f6560e01b8152600481018490523060248201529091506001600160a01b03821690636e553f6590849060440160206040518083038185885af11580156104b4573d5f5f3e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906104d99190611b93565b91506104e9888284888888610d38565b9150505f688000000000ab143c065d9695505050505050565b5f688000000000ab143c065c156105205763ab143c065f526004601cfd5b30688000000000ab143c065d61055f61053c6020880188611baa565b8651602080890151908a01359061055960608c0160408d01611bc5565b87610f11565b610570855f01518660400151610a0e565b15610580575060208401516105ad565b6105aa7f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff86610a5e565b90505b6105bf87866040015183878787610d38565b90505f688000000000ab143c065d9695505050505050565b5f688000000000ab143c065c156105f55763ab143c065f526004601cfd5b30688000000000ab143c065d61062e6106116020860186611baa565b8451602080870151908801359061055960608a0160408b01611bc5565b61063f835f01518460400151610a0e565b1561064f5750602082015161067c565b6106797f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff84610a5e565b90505b61068b8360400151838361105a565b5f688000000000ab143c065d9392505050565b60607f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff82806001600160401b038111156106da576106da611729565b60405190808252806020026020018201604052801561070d57816020015b60608152602001906001900390816106f85790505b5060408051606080820183525f80835260208301819052928201529194505b828110156108f65786868281811061074657610746611be0565b90506020028101906107589190611bf4565b61076190611c12565b915081602001511561089857815160405163191d0cc560e11b81526001600160a01b0391821660048201525f9186169063323a198a90602401602060405180830381865afa1580156107b5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107d99190611b78565b90506001600160a01b03811661080257604051632f3285fb60e21b815260040160405180910390fd5b8251604080850151905163bd0226d760e01b81526001600160a01b0384169263bd0226d7926108379233929190600401611c97565b5f604051808303815f87803b15801561084e575f5ffd5b505af1158015610860573d5f5f3e3d5ffd5b50505050610875835f01518460400151611107565b86838151811061088757610887611be0565b6020026020010181905250506108ee565b81516001600160a01b031630146108c257604051637720ccd960e01b815260040160405180910390fd5b6108d030836040015161117c565b8582815181106108e2576108e2611be0565b60200260200101819052505b60010161072c565b5050505092915050565b610909836109d5565b156109aa5734821461092e57604051630fc1653d60e11b815260040160405180910390fd5b80156109a5577f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a6001600160a01b031663d0e30db0836040518263ffffffff1660e01b81526004015f604051808303818588803b15801561098d575f5ffd5b505af115801561099f573d5f5f3e3d5ffd5b50505050505b505050565b34156109c957604051630fc1653d60e11b815260040160405180910390fd5b6109a5833330856111d0565b5f6001600160a01b0382161580610a08575073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038316145b92915050565b5f816001600160a01b0316836001600160a01b031603610a3057506001610a08565b610a39836109d5565b8015610a495750610a49826109d5565b15610a5657506001610a08565b505f92915050565b604081015181515f9190610a728183610a0e565b15610a9057604051636991e51560e11b815260040160405180910390fd5b6060840151604051631d4686fd60e31b81526001600160a01b0391821660048201525f9187169063ea3437e890602401602060405180830381865afa158015610adb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aff9190611b78565b90506001600160a01b038116610b2857604051637409771560e11b815260040160405180910390fd5b60405163383d5bf360e11b81526001600160a01b0382169063707ab7e690610b569088903090600401611cc2565b5f604051808303815f87803b158015610b6d575f5ffd5b505af1158015610b7f573d5f5f3e3d5ffd5b50505050610b96828660600151876020015161121f565b5f610ba084611237565b90505f610bac846109d5565b610bb6575f610bbc565b86602001515b9050610bd187606001518860a00151836112b7565b50610be0848860600151611350565b81610bea86611237565b610bf49190611d40565b98975050505050505050565b5f610c0b86866113e3565b825f03610c7e576040516357d159d560e01b81526001600160a01b0383811660048301528716906357d159d5906024016020604051808303815f875af1158015610c57573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7b9190611b93565b92505b82841015610c9f576040516367d8a00f60e01b815260040160405180910390fd5b610caa85878561121f565b604051632796469160e21b8152600481018490526001600160a01b038381166024830152871690639e591a44906044015f604051808303815f87803b158015610cf1575f5ffd5b505af1158015610d03573d5f5f3e3d5ffd5b50505050610d118587611350565b610d1b8385611d40565b93508315610d2e57610d2e85338661105a565b5091949350505050565b5f610d4387876113e3565b610d4e86888761121f565b8215610e6957336001600160a01b0383161480610dd45750604051635fec5d0b60e01b81526001600160a01b038381166004830152336024830152881690635fec5d0b90604401602060405180830381865afa158015610db0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dd49190611d5f565b15610e505760405163b3bffb4560e01b8152600481018690526001600160a01b03838116602483015288169063b3bffb45906044016020604051808303815f875af1158015610e25573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e499190611b93565b9050610edc565b604051630ba2198760e21b815260040160405180910390fd5b604051636e553f6560e01b8152600481018690526001600160a01b038381166024830152881690636e553f65906044016020604051808303815f875af1158015610eb5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ed99190611b93565b90505b83811015610efd57604051630fc1653d60e11b815260040160405180910390fd5b610f078688611350565b9695505050505050565b610f1b86866113e3565b5f8215610f9d57604051636779db5b60e01b8152600481018690523060248201523360448201526001600160a01b03881690636779db5b906064016020604051808303815f875af1158015610f72573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f969190611b93565b9050611014565b604051630b817f5160e31b8152600481018690523060248201523360448201526001600160a01b03881690635c0bfa88906064016020604051808303815f875af1158015610fed573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110119190611b93565b90505b8381101561103557604051630fc1653d60e11b815260040160405180910390fd5b8381111561105157611051868361104c8785611d40565b61105a565b50505050505050565b611063836109d5565b156110fc577f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a6001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b1580156110c1575f5ffd5b505af11580156110d3573d5f5f3e3d5ffd5b50505050507f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a92505b6109a5838383611618565b60605f5f846001600160a01b03165f856040516111249190611d7a565b5f6040518083038185875af1925050503d805f811461115e576040519150601f19603f3d011682016040523d82523d5f602084013e611163565b606091505b5091509150611173858383611658565b95945050505050565b60605f5f846001600160a01b0316846040516111989190611d7a565b5f60405180830381855af49150503d805f811461115e576040519150601f19603f3d011682016040523d82523d5f602084013e611163565b60405181606052826040528360601b602c526323b872dd60601b600c5260205f6064601c5f895af13d1560015f5114171661121257637939f4245f526004601cfd5b5f60605260405250505050565b611228836109d5565b6109a5576109a58383836116a0565b5f611241826109d5565b6112b0576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611287573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112ab9190611b93565b610a08565b4792915050565b6060814710156112da5760405163595909b560e11b815260040160405180910390fd5b5f5f856001600160a01b031684866040516112f59190611d7a565b5f6040518083038185875af1925050503d805f811461132f576040519150601f19603f3d011682016040523d82523d5f602084013e611334565b606091505b5091509150611344868383611658565b925050505b9392505050565b611359826109d5565b6113df57604051636eb1769f60e11b81523060048201526001600160a01b0382811660248301525f919084169063dd62ed3e90604401602060405180830381865afa1580156113aa573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113ce9190611b93565b11156113df576113df82825f6116a0565b5050565b6001600160a01b03821661140a57604051630fc1653d60e11b815260040160405180910390fd5b5f826001600160a01b03166341ed2c126040518163ffffffff1660e01b8152600401602060405180830381865afa158015611447573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061146b9190611b78565b604051637d5528bd60e01b81526001600160a01b0380831660048301529192507f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff90911690637d5528bd90602401602060405180830381865afa1580156114d4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114f89190611d5f565b15806115695750604051637bca031760e11b81526001600160a01b03848116600483015282169063f794062e90602401602060405180830381865afa158015611543573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115679190611d5f565b155b1561158757604051630ba2198760e21b815260040160405180910390fd5b826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e79190611b78565b6001600160a01b0316826001600160a01b0316146109a55760405163ecaf3a9760e01b815260040160405180910390fd5b816014528060345263a9059cbb60601b5f5260205f604460105f875af13d1560015f5114171661164f576390b8ec185f526004601cfd5b5f603452505050565b606061166483836116d7565b815115801561167b57506001600160a01b0384163b155b15611699576040516314859aeb60e21b815260040160405180910390fd5b5092915050565b816014528060345263095ea7b360601b5f5260205f604460105f875af13d1560015f5114171661164f57633e3f8f735f526004601cfd5b816113df5780515f036116fd576040516314859aeb60e21b815260040160405180910390fd5b805181602001fd5b6001600160a01b0381168114611719575f5ffd5b50565b8015158114611719575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b038111828210171561175f5761175f611729565b60405290565b5f82601f830112611774575f5ffd5b81356001600160401b0381111561178d5761178d611729565b604051601f8201601f19908116603f011681016001600160401b03811182821017156117bb576117bb611729565b6040528181528382016020018510156117d2575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f60c082840312156117fe575f5ffd5b61180661173d565b9050813561181381611705565b815260208281013590820152604082013561182d81611705565b6040820152606082013561184081611705565b60608201526080828101359082015260a08201356001600160401b03811115611867575f5ffd5b61187384828501611765565b60a08301525092915050565b5f5f5f5f5f60a08688031215611893575f5ffd5b853561189e81611705565b945060208601356118ae8161171c565b935060408601356001600160401b038111156118c8575f5ffd5b6118d4888289016117ee565b9350506060860135915060808601356118ec81611705565b809150509295509295909350565b5f5f5f5f5f5f60c0878903121561190f575f5ffd5b863561191a81611705565b9550602087013561192a8161171c565b945060408701356001600160401b03811115611944575f5ffd5b61195089828a016117ee565b9450506060870135925060808701356119688161171c565b915060a087013561197881611705565b809150509295509295509295565b5f60608284031215611996575f5ffd5b50919050565b5f5f5f5f5f5f61010087890312156119b2575f5ffd5b86356119bd81611705565b95506119cc8860208901611986565b945060808701356001600160401b038111156119e6575f5ffd5b6119f289828a016117ee565b94505060a0870135925060c0870135611a0a8161171c565b915060e087013561197881611705565b5f5f5f60a08486031215611a2c575f5ffd5b611a368585611986565b925060608401356001600160401b03811115611a50575f5ffd5b611a5c868287016117ee565b9250506080840135611a6d81611705565b809150509250925092565b5f5f60208385031215611a89575f5ffd5b82356001600160401b03811115611a9e575f5ffd5b8301601f81018513611aae575f5ffd5b80356001600160401b03811115611ac3575f5ffd5b8560208260051b8401011115611ad7575f5ffd5b6020919091019590945092505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015611b6c57603f19878603018452611b57858351611ae7565b94506020938401939190910190600101611b3b565b50929695505050505050565b5f60208284031215611b88575f5ffd5b815161134981611705565b5f60208284031215611ba3575f5ffd5b5051919050565b5f60208284031215611bba575f5ffd5b813561134981611705565b5f60208284031215611bd5575f5ffd5b81356113498161171c565b634e487b7160e01b5f52603260045260245ffd5b5f8235605e19833603018112611c08575f5ffd5b9190910192915050565b5f60608236031215611c22575f5ffd5b604051606081016001600160401b0381118282101715611c4457611c44611729565b6040528235611c5281611705565b81526020830135611c628161171c565b602082015260408301356001600160401b03811115611c7f575f5ffd5b611c8b36828601611765565b60408301525092915050565b6001600160a01b038481168252831660208201526060604082018190525f9061117390830184611ae7565b6040815260018060a01b0383511660408201526020830151606082015260018060a01b03604084015116608082015260018060a01b0360608401511660a0820152608083015160c08201525f60a084015160c060e0840152611d28610100840182611ae7565b91505061134960208301846001600160a01b03169052565b81810381811115610a0857634e487b7160e01b5f52601160045260245ffd5b5f60208284031215611d6f575f5ffd5b81516113498161171c565b5f82518060208501845e5f92019182525091905056fea26469706673582212208de869caa2e008353a01f58886a1c17bd57fea9e7129e0511f178b38a70da77e64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001310f352f1389969ece6741671c4b919523912ff0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a
-----Decoded View---------------
Arg [0] : cr (address): 0x1310f352f1389969Ece6741671c4B919523912fF
Arg [1] : wNative (address): 0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000001310f352f1389969ece6741671c4b919523912ff
Arg [1] : 0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a
Deployed Bytecode Sourcemap
156733:3261:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;149129:1397;;;;;;:::i;:::-;;:::i;:::-;;;3424:25:1;;;3412:2;3397:18;149129:1397:0;;;;;;;;158519:1472;;;;;;:::i;:::-;;:::i;132562:49::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4661:32:1;;;4643:51;;4631:2;4616:18;132562:49:0;4473:227:1;154338:1194:0;;;;;;;;;;-1:-1:-1;154338:1194:0;;;;;:::i;:::-;;:::i;152146:814::-;;;;;;;;;;-1:-1:-1;152146:814:0;;;;;:::i;:::-;;:::i;80573:1590::-;;;;;;;;;;-1:-1:-1;80573:1590:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;132686:38::-;;;;;;;;;;;;;;;149129:1397;149371:17;54996:22;54990:29;54987:146;;;55052:10;55046:4;55039:24;55113:4;55107;55100:18;54987:146;55178:9;55154:22;55147:41;149401:133:::1;149428:10;:21;;;149464:10;:22;;;149501;149401:12;:133::i;:::-;149749:21:::0;;149729:42:::1;::::0;:19:::1;:42::i;:::-;:68;;;;;149775:22;149729:68;149725:214;;;-1:-1:-1::0;;;;;149913:13:0::1;149881:46;::::0;;149725:214:::1;149955:73;149982:10;:21;;;150005:10;:22;;;149955:26;:73::i;:::-;149951:284;;;-1:-1:-1::0;150057:22:0::1;::::0;::::1;::::0;149951:284:::1;;;150172:51;150195:15;150212:10;150172:22;:51::i;:::-;150160:63;;149951:284;150356:162;150381:16;150412:10;:22;;;150449:9;150473:11;150499:8;150356:10;:162::i;:::-;150344:174;;55320:1:::0;55296:22;55289:33;149129:1397;;;;;;;:::o;158519:1472::-;158803:17;54996:22;54990:29;54987:146;;;55052:10;55046:4;55039:24;55113:4;55107;55100:18;54987:146;55178:9;55154:22;55147:41;158833:66:::1;158846:10;:21;;;158869:10;:22;;;158893:5;158833:12;:66::i;:::-;158917:43;158937:10;:22;;;158917:19;:43::i;:::-;158912:128;;158984:44;;-1:-1:-1::0;;;158984:44:0::1;;;;;;;;;;;158912:128;159056:73;159083:10;:21;;;159106:10;:22;;;159056:26;:73::i;:::-;159052:501;;;-1:-1:-1::0;159158:22:0::1;::::0;::::1;::::0;159052:501:::1;;;159210:21:::0;;-1:-1:-1;;;;;159235:13:0::1;159210:38:::0;::::1;::::0;::::1;::::0;159206:347:::1;;159325:22;::::0;::::1;::::0;159295:53:::1;::::0;-1:-1:-1;;;159295:53:0;;::::1;::::0;::::1;3424:25:1::0;;;;159301:13:0::1;-1:-1:-1::0;;;;;159295:29:0::1;::::0;::::1;::::0;3397:18:1;;159295:53:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;159375:10;:22;;;159363:34;;159206:347;;;159490:51;159513:15;159530:10;159490:22;:51::i;:::-;159478:63;;159206:347;159565:13;159589:6;-1:-1:-1::0;;;;;159581:21:0::1;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;159661:79;::::0;-1:-1:-1;;;159661:79:0;;::::1;::::0;::::1;8977:25:1::0;;;159734:4:0::1;9018:18:1::0;;;9011:60;159565:39:0;;-1:-1:-1;;;;;;159661:35:0;::::1;::::0;::::1;::::0;159704:9;;8950:18:1;;159661:79:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;159649:91;;159810:173;159839:6;159860:5;159880:9;159904:14;159933:16;159964:8;159810:14;:173::i;:::-;159798:185;;158822:1169;55320:1:::0;55296:22;55289:33;158519:1472;;;;;;;;:::o;154338:1194::-;154612:17;54996:22;54990:29;54987:146;;;55052:10;55046:4;55039:24;55113:4;55107;55100:18;54987:146;55178:9;55154:22;55147:41;154678:237:::1;154706:19;;::::0;::::1;:12:::0;:19:::1;:::i;:::-;154740:21:::0;;154776:19:::1;154810:22:::0;;::::1;::::0;154776:19;;::::1;;::::0;154847:34:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;154896:8;154678:13;:237::i;:::-;154932:73;154959:10;:21;;;154982:10;:22;;;154932:26;:73::i;:::-;154928:345;;;-1:-1:-1::0;155034:22:0::1;::::0;::::1;::::0;154928:345:::1;;;155210:51;155233:15;155250:10;155210:22;:51::i;:::-;155198:63;;154928:345;155334:190;155363:6;155384:10;:22;;;155421:9;155445:14;155474:16;155505:8;155334:14;:190::i;:::-;155322:202;;55320:1:::0;55296:22;55289:33;154338:1194;;;;;;;;:::o;152146:814::-;152323:17;54996:22;54990:29;54987:146;;;55052:10;55046:4;55039:24;55113:4;55107;55100:18;54987:146;55178:9;55154:22;55147:41;152389:237:::1;152417:19;;::::0;::::1;:12:::0;:19:::1;:::i;:::-;152451:21:::0;;152487:19:::1;152521:22:::0;;::::1;::::0;152487:19;;::::1;;::::0;152558:34:::1;::::0;;;::::1;::::0;::::1;;:::i;152389:237::-;152643:73;152670:10;:21;;;152693:10;:22;;;152643:26;:73::i;:::-;152639:236;;;-1:-1:-1::0;152745:22:0::1;::::0;::::1;::::0;152639:236:::1;;;152812:51;152835:15;152852:10;152812:22;:51::i;:::-;152800:63;;152639:236;152887:65;152908:10;:22;;;152932:8;152942:9;152887:20;:65::i;:::-;55320:1:::0;55296:22;55289:33;152146:814;;;;;:::o;80573:1590::-;80660:22;143354:15;80768:5;;-1:-1:-1;;;;;80801:21:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;80791:31:0;;-1:-1:-1;80879:1277:0;80899:8;80895:1;:12;80879:1277;;;80942:5;;80948:1;80942:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;80929:21;;;:::i;:::-;;;80983:10;:24;;;80979:810;;;81211:17;;81191:38;;-1:-1:-1;;;81191:38:0;;-1:-1:-1;;;;;4661:32:1;;;81191:38:0;;;4643:51:1;81173:15:0;;81191:19;;;;;4616:18:1;;81191:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81173:56;-1:-1:-1;;;;;;81320:21:0;;81316:105;;81373:28;;-1:-1:-1;;;81373:28:0;;;;;;;;;;;81316:105;81537:17;;81577:15;;;;;81441:170;;-1:-1:-1;;;81441:170:0;;-1:-1:-1;;;;;81441:40:0;;;;;:170;;81504:10;;81537:17;81577:15;81441:170;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81645:83;81693:10;:17;;;81712:10;:15;;;81645:47;:83::i;:::-;81632:7;81640:1;81632:10;;;;;;;;:::i;:::-;;;;;;:96;;;;81765:8;;;80979:810;81945:17;;-1:-1:-1;;;;;81928:34:0;81936:4;81928:34;81924:108;;81990:26;;-1:-1:-1;;;81990:26:0;;;;;;;;;;;81924:108;82061:83;82121:4;82128:10;:15;;;82061:51;:83::i;:::-;82048:7;82056:1;82048:10;;;;;;;;:::i;:::-;;;;;;:96;;;;80879:1277;80909:3;;80879:1277;;;;80684:1479;;;80573:1590;;;;:::o;140445:863::-;140595:31;140615:10;140595:19;:31::i;:::-;140591:391;;;140738:9;140723:11;:24;140719:100;;140775:28;;-1:-1:-1;;;140775:28:0;;;;;;;;;;;140719:100;140839:22;140835:115;;;140888:13;-1:-1:-1;;;;;140882:28:0;;140919:11;140882:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;140835:115;140445:863;;;:::o;140591:391::-;141063:9;:14;141059:82;;141101:28;;-1:-1:-1;;;141101:28:0;;;;;;;;;;;141059:82;141153:147;141200:10;141225;141258:4;141278:11;141153:32;:147::i;83510:185::-;83567:11;-1:-1:-1;;;;;83600:19:0;;;;:87;;-1:-1:-1;83645:42:0;-1:-1:-1;;;;;83636:51:0;;;83600:87;83591:96;83510:185;-1:-1:-1;;83510:185:0:o;82942:309::-;83048:4;83079:6;-1:-1:-1;;;;;83069:16:0;:6;-1:-1:-1;;;;;83069:16:0;;83065:60;;-1:-1:-1;83109:4:0;83102:11;;83065:60;83141:17;83151:6;83141:9;:17::i;:::-;:38;;;;;83162:17;83172:6;83162:9;:17::i;:::-;83137:82;;;-1:-1:-1;83203:4:0;83196:11;;83137:82;-1:-1:-1;83238:5:0;82942:309;;;;:::o;125338:1555::-;125495:18;;;;125545:17;;125443;;125495:18;125643:51;125545:17;125495:18;125643:26;:51::i;:::-;125639:115;;;125718:24;;-1:-1:-1;;;125718:24:0;;;;;;;;;;;125639:115;125819:13;;;;125792:41;;-1:-1:-1;;;125792:41:0;;-1:-1:-1;;;;;4661:32:1;;;125792:41:0;;;4643:51:1;125766:23:0;;125792:26;;;;;4616:18:1;;125792:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;125766:67;-1:-1:-1;;;;;;125908:29:0;;125904:98;;125961:29;;-1:-1:-1;;;125961:29:0;;;;;;;;;;;125904:98;126053:92;;-1:-1:-1;;;126053:92:0;;-1:-1:-1;;;;;126053:69:0;;;;;:92;;126123:6;;126139:4;;126053:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;126232:63;126249:10;126261:6;:13;;;126276:6;:18;;;126232:16;:63::i;:::-;126382:21;126406:33;126427:11;126406:20;:33::i;:::-;126382:57;;126452:17;126472:31;126492:10;126472:19;:31::i;:::-;:69;;126540:1;126472:69;;;126519:6;:18;;;126472:69;126452:89;;126584:124;126634:6;:13;;;126662:6;:11;;;126688:9;126584:35;:124::i;:::-;;126761:50;126785:10;126797:6;:13;;;126761:23;:50::i;:::-;126872:13;126836:33;126857:11;126836:20;:33::i;:::-;:49;;;;:::i;:::-;126824:61;125338:1555;-1:-1:-1;;;;;;;;125338:1555:0:o;138396:1500::-;138590:7;138610:44;138626:16;138644:9;138610:15;:44::i;:::-;138671:11;138686:1;138671:16;138667:247;;138820:82;;-1:-1:-1;;;138820:82:0;;-1:-1:-1;;;;;4661:32:1;;;138820:82:0;;;4643:51:1;138820:72:0;;;;;4616:18:1;;138820:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;138806:96;;138667:247;139013:11;139000:10;:24;138996:97;;;139048:33;;-1:-1:-1;;;139048:33:0;;;;;;;;;;;138996:97;139177:69;139205:9;139216:16;139234:11;139177:27;:69::i;:::-;139310:67;;-1:-1:-1;;;139310:67:0;;;;;8977:25:1;;;-1:-1:-1;;;;;9038:32:1;;;9018:18;;;9011:60;139310:44:0;;;;;8950:18:1;;139310:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;139440:63;139475:9;139486:16;139440:34;:63::i;:::-;139514:25;139528:11;139514:25;;:::i;:::-;;-1:-1:-1;139761:14:0;;139757:102;;139792:55;139813:9;139824:10;139836;139792:20;:55::i;:::-;-1:-1:-1;139878:10:0;;138396:1500;-1:-1:-1;;;;138396:1500:0:o;134238:1855::-;134453:14;134480:30;134496:6;134504:5;134480:15;:30::i;:::-;134569:50;134597:5;134604:6;134612;134569:27;:50::i;:::-;134875:16;134871:925;;;135200:10;-1:-1:-1;;;;;135200:22:0;;;;:100;;-1:-1:-1;135243:57:0;;-1:-1:-1;;;135243:57:0;;-1:-1:-1;;;;;12788:32:1;;;135243:57:0;;;12770:51:1;135289:10:0;12837:18:1;;;12830:60;135243:35:0;;;;;12743:18:1;;135243:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135178:373;;;135344:117;;-1:-1:-1;;;135344:117:0;;;;;8977:25:1;;;-1:-1:-1;;;;;9038:32:1;;;9018:18;;;9011:60;135344:38:0;;;;;8950:18:1;;135344:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135335:126;;134871:925;;135178:373;135509:26;;-1:-1:-1;;;135509:26:0;;;;;;;;;;;134871:925;135743:41;;-1:-1:-1;;;135743:41:0;;;;;8977:25:1;;;-1:-1:-1;;;;;9038:32:1;;;9018:18;;;9011:60;135743:23:0;;;;;8950:18:1;;135743:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135734:50;;134871:925;135896:14;135887:6;:23;135883:91;;;135934:28;;-1:-1:-1;;;135934:28:0;;;;;;;;;;;135883:91;136036:49;136071:5;136078:6;136036:34;:49::i;:::-;134238:1855;;;;;;;;:::o;136688:1089::-;136909:30;136925:6;136933:5;136909:15;:30::i;:::-;136950:14;137031:21;137027:367;;;137078:136;;-1:-1:-1;;;137078:136:0;;;;;13353:25:1;;;137165:4:0;13394:18:1;;;13387:60;137189:10:0;13463:18:1;;;13456:60;-1:-1:-1;;;;;137078:35:0;;;;;13326:18:1;;137078:136:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;137069:145;;137027:367;;;137256:126;;-1:-1:-1;;;137256:126:0;;;;;13353:25:1;;;137333:4:0;13394:18:1;;;13387:60;137357:10:0;13463:18:1;;;13456:60;-1:-1:-1;;;;;137256:25:0;;;;;13326:18:1;;137256:126:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;137247:135;;137027:367;137497:14;137488:6;:23;137484:91;;;137535:28;;-1:-1:-1;;;137535:28:0;;;;;;;;;;;137484:91;137665:14;137656:6;:23;137652:118;;;137696:62;137717:5;137724:8;137734:23;137743:14;137734:6;:23;:::i;:::-;137696:20;:62::i;:::-;136898:879;136688:1089;;;;;;:::o;142644:488::-;142921:26;142941:5;142921:19;:26::i;:::-;142917:142;;;142970:13;-1:-1:-1;;;;;142964:28:0;;143001:6;142964:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;143034:13;143026:21;;142917:142;143071:53;143100:5;143107:8;143117:6;143071:28;:53::i;49206:265::-;49299:12;49325;49339:23;49366:6;-1:-1:-1;;;;;49366:11:0;49385:1;49388:4;49366:27;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49324:69;;;;49421:42;49435:6;49443:7;49452:10;49421:13;:42::i;:::-;49414:49;49206:265;-1:-1:-1;;;;;49206:265:0:o;51086:263::-;51187:12;51213;51227:23;51254:6;-1:-1:-1;;;;;51254:19:0;51274:4;51254:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64891:1160;65077:4;65071:11;65143:6;65137:4;65130:20;65209:2;65203:4;65196:16;65275:4;65271:2;65267:13;65261:4;65254:27;-1:-1:-1;;;65332:4:0;65325:48;65744:4;65738;65732;65726;65723:1;65716:5;65709;65704:45;65637:16;65630:24;65626:1;65619:4;65613:11;65610:18;65607:48;65521:247;65493:412;;65816:10;65810:4;65803:24;65885:4;65879;65872:18;65493:412;65932:1;65926:4;65919:15;65989:4;65982:15;-1:-1:-1;;;;64891:1160:0:o;130016:246::-;130149:26;130169:5;130149:19;:26::i;:::-;130144:111;;130192:51;130220:5;130227:7;130236:6;130192:27;:51::i;83891:186::-;83949:9;83975:16;83985:5;83975:9;:16::i;:::-;:94;;84031:38;;-1:-1:-1;;;84031:38:0;;84063:4;84031:38;;;4643:51:1;-1:-1:-1;;;;;84031:23:0;;;;;4616:18:1;;84031:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;83975:94;;;83994:21;83971:98;83891:186;-1:-1:-1;;83891:186:0:o;50104:442::-;50231:12;50284:5;50260:21;:29;50256:111;;;50313:42;;-1:-1:-1;;;50313:42:0;;;;;;;;;;;50256:111;50380:12;50394:23;50421:6;-1:-1:-1;;;;;50421:11:0;50454:5;50471:4;50421:55;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50379:97;;;;50496:42;50510:6;50518:7;50527:10;50496:13;:42::i;:::-;50489:49;;;;50104:442;;;;;;:::o;130439:289::-;130529:26;130549:5;130529:19;:26::i;:::-;130524:197;;130576:47;;-1:-1:-1;;;130576:47:0;;130608:4;130576:47;;;12770:51:1;-1:-1:-1;;;;;12857:32:1;;;12837:18;;;12830:60;130626:1:0;;130576:23;;;;;;12743:18:1;;130576:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:51;130572:138;;;130648:46;130676:5;130683:7;130692:1;130648:27;:46::i;:::-;130439:289;;:::o;141555:731::-;-1:-1:-1;;;;;141695:20:0;;141691:88;;141739:28;;-1:-1:-1;;;141739:28:0;;;;;;;;;;;141691:88;141854:17;141882:6;-1:-1:-1;;;;;141874:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141935:44;;-1:-1:-1;;;141935:44:0;;-1:-1:-1;;;;;4661:32:1;;;141935:44:0;;;4643:51:1;141854::0;;-1:-1:-1;141935:15:0;:31;;;;;;4616:18:1;;141935:44:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141934:45;:82;;;-1:-1:-1;141997:19:0;;-1:-1:-1;;;141997:19:0;;-1:-1:-1;;;;;4661:32:1;;;141997:19:0;;;4643:51:1;141997:11:0;;;;;4616:18:1;;141997:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;141996:20;141934:82;141916:172;;;142050:26;;-1:-1:-1;;;142050:26:0;;;;;;;;;;;141916:172;142184:6;-1:-1:-1;;;;;142176:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;142167:32:0;:5;-1:-1:-1;;;;;142167:32:0;;142163:116;;142223:44;;-1:-1:-1;;;142223:44:0;;;;;;;;;;;68152:957;68318:2;68312:4;68305:16;68376:6;68370:4;68363:20;-1:-1:-1;;;68436:4:0;68429:48;68836:4;68830;68824;68818;68815:1;68808:5;68801;68796:45;68729:16;68722:24;68718:1;68711:4;68705:11;68702:18;68699:48;68613:247;68585:408;;68908:10;68902:4;68895:24;68973:4;68967;68960:18;68585:408;69020:1;69014:4;69007:15;68152:957;;;:::o;51563:513::-;51698:12;51723:36;51739:7;51748:10;51723:15;:36::i;:::-;51921:17;;:22;:49;;;;-1:-1:-1;;;;;;51947:18:0;;;:23;51921:49;51917:122;;;51994:33;;-1:-1:-1;;;51994:33:0;;;;;;;;;;;51917:122;-1:-1:-1;52058:10:0;51563:513;-1:-1:-1;;51563:513:0:o;71004:954::-;71169:2;71163:4;71156:16;71227:6;71221:4;71214:20;-1:-1:-1;;;71287:4:0;71280:48;71686:4;71680;71674;71668;71665:1;71658:5;71651;71646:45;71579:16;71572:24;71568:1;71561:4;71555:11;71552:18;71549:48;71463:247;71435:407;;71758:10;71752:4;71745:24;71822:4;71816;71809:18;52252:425;52371:7;52366:304;;52399:10;:17;52420:1;52399:22;52395:103;;52449:33;;-1:-1:-1;;;52449:33:0;;;;;;;;;;;52395:103;52632:10;52626:17;52613:10;52609:2;52605:19;52598:46;14:131:1;-1:-1:-1;;;;;89:31:1;;79:42;;69:70;;135:1;132;125:12;69:70;14:131;:::o;150:118::-;236:5;229:13;222:21;215:5;212:32;202:60;;258:1;255;248:12;273:127;334:10;329:3;325:20;322:1;315:31;365:4;362:1;355:15;389:4;386:1;379:15;405:248;472:2;466:9;514:4;502:17;;-1:-1:-1;;;;;534:34:1;;570:22;;;531:62;528:88;;;596:18;;:::i;:::-;632:2;625:22;405:248;:::o;658:745::-;700:5;753:3;746:4;738:6;734:17;730:27;720:55;;771:1;768;761:12;720:55;811:6;798:20;-1:-1:-1;;;;;833:6:1;830:30;827:56;;;863:18;;:::i;:::-;932:2;926:9;1024:2;986:17;;-1:-1:-1;;982:31:1;;;1015:2;978:40;974:54;962:67;;-1:-1:-1;;;;;1044:34:1;;1080:22;;;1041:62;1038:88;;;1106:18;;:::i;:::-;1142:2;1135:22;1166;;;1207:19;;;1228:4;1203:30;1200:39;-1:-1:-1;1197:59:1;;;1252:1;1249;1242:12;1197:59;1316:6;1309:4;1301:6;1297:17;1290:4;1282:6;1278:17;1265:58;1371:1;1343:19;;;1364:4;1339:30;1332:41;;;;1347:6;658:745;-1:-1:-1;;;658:745:1:o;1408:988::-;1459:5;1507:4;1495:9;1490:3;1486:19;1482:30;1479:50;;;1525:1;1522;1515:12;1479:50;1547:17;;:::i;:::-;1538:26;;1601:9;1588:23;1620:33;1645:7;1620:33;:::i;:::-;1662:22;;1757:2;1742:18;;;1729:32;1777:14;;;1770:31;1853:2;1838:18;;1825:32;1866:33;1825:32;1866:33;:::i;:::-;1926:2;1915:14;;1908:31;1991:2;1976:18;;1963:32;2004:33;1963:32;2004:33;:::i;:::-;2064:2;2053:14;;2046:31;2150:3;2135:19;;;2122:33;2171:15;;;2164:32;2247:3;2232:19;;2219:33;-1:-1:-1;;;;;2264:30:1;;2261:50;;;2307:1;2304;2297:12;2261:50;2344:45;2385:3;2376:6;2365:9;2361:22;2344:45;:::i;:::-;2338:3;2331:5;2327:15;2320:70;;1408:988;;;;:::o;2401:872::-;2515:6;2523;2531;2539;2547;2600:3;2588:9;2579:7;2575:23;2571:33;2568:53;;;2617:1;2614;2607:12;2568:53;2656:9;2643:23;2675:31;2700:5;2675:31;:::i;:::-;2725:5;-1:-1:-1;2782:2:1;2767:18;;2754:32;2795:30;2754:32;2795:30;:::i;:::-;2844:7;-1:-1:-1;2902:2:1;2887:18;;2874:32;-1:-1:-1;;;;;2918:30:1;;2915:50;;;2961:1;2958;2951:12;2915:50;2984:55;3031:7;3022:6;3011:9;3007:22;2984:55;:::i;:::-;2974:65;-1:-1:-1;;3112:2:1;3097:18;;3084:32;;-1:-1:-1;3194:3:1;3179:19;;3166:33;3208;3166;3208;:::i;:::-;3260:7;3250:17;;;2401:872;;;;;;;;:::o;3460:1008::-;3580:6;3588;3596;3604;3612;3620;3673:3;3661:9;3652:7;3648:23;3644:33;3641:53;;;3690:1;3687;3680:12;3641:53;3729:9;3716:23;3748:31;3773:5;3748:31;:::i;:::-;3798:5;-1:-1:-1;3855:2:1;3840:18;;3827:32;3868:30;3827:32;3868:30;:::i;:::-;3917:7;-1:-1:-1;3975:2:1;3960:18;;3947:32;-1:-1:-1;;;;;3991:30:1;;3988:50;;;4034:1;4031;4024:12;3988:50;4057:55;4104:7;4095:6;4084:9;4080:22;4057:55;:::i;:::-;4047:65;-1:-1:-1;;4185:2:1;4170:18;;4157:32;;-1:-1:-1;4267:3:1;4252:19;;4239:33;4281:30;4239:33;4281:30;:::i;:::-;4330:7;-1:-1:-1;4389:3:1;4374:19;;4361:33;4403;4361;4403;:::i;:::-;4455:7;4445:17;;;3460:1008;;;;;;;;:::o;4705:160::-;4770:5;4815:2;4806:6;4801:3;4797:16;4793:25;4790:45;;;4831:1;4828;4821:12;4790:45;-1:-1:-1;4853:6:1;4705:160;-1:-1:-1;4705:160:1:o;4870:1011::-;5025:6;5033;5041;5049;5057;5065;5118:3;5106:9;5097:7;5093:23;5089:33;5086:53;;;5135:1;5132;5125:12;5086:53;5174:9;5161:23;5193:31;5218:5;5193:31;:::i;:::-;5243:5;-1:-1:-1;5267:68:1;5327:7;5322:2;5307:18;;5267:68;:::i;:::-;5257:78;;5386:3;5375:9;5371:19;5358:33;-1:-1:-1;;;;;5406:6:1;5403:30;5400:50;;;5446:1;5443;5436:12;5400:50;5469:55;5516:7;5507:6;5496:9;5492:22;5469:55;:::i;:::-;5459:65;-1:-1:-1;;5597:3:1;5582:19;;5569:33;;-1:-1:-1;5680:3:1;5665:19;;5652:33;5694:30;5652:33;5694:30;:::i;:::-;5743:7;-1:-1:-1;5802:3:1;5787:19;;5774:33;5816;5774;5816;:::i;5886:612::-;6017:6;6025;6033;6086:3;6074:9;6065:7;6061:23;6057:33;6054:53;;;6103:1;6100;6093:12;6054:53;6126:59;6177:7;6166:9;6126:59;:::i;:::-;6116:69;;6236:2;6225:9;6221:18;6208:32;-1:-1:-1;;;;;6255:6:1;6252:30;6249:50;;;6295:1;6292;6285:12;6249:50;6318:55;6365:7;6356:6;6345:9;6341:22;6318:55;:::i;:::-;6308:65;;;6423:3;6412:9;6408:19;6395:33;6437:31;6462:5;6437:31;:::i;:::-;6487:5;6477:15;;;5886:612;;;;;:::o;6503:645::-;6624:6;6632;6685:2;6673:9;6664:7;6660:23;6656:32;6653:52;;;6701:1;6698;6691:12;6653:52;6741:9;6728:23;-1:-1:-1;;;;;6766:6:1;6763:30;6760:50;;;6806:1;6803;6796:12;6760:50;6829:22;;6882:4;6874:13;;6870:27;-1:-1:-1;6860:55:1;;6911:1;6908;6901:12;6860:55;6951:2;6938:16;-1:-1:-1;;;;;6969:6:1;6966:30;6963:50;;;7009:1;7006;6999:12;6963:50;7062:7;7057:2;7047:6;7044:1;7040:14;7036:2;7032:23;7028:32;7025:45;7022:65;;;7083:1;7080;7073:12;7022:65;7114:2;7106:11;;;;;7136:6;;-1:-1:-1;6503:645:1;-1:-1:-1;;;6503:645:1:o;7153:288::-;7194:3;7232:5;7226:12;7259:6;7254:3;7247:19;7315:6;7308:4;7301:5;7297:16;7290:4;7285:3;7281:14;7275:47;7367:1;7360:4;7351:6;7346:3;7342:16;7338:27;7331:38;7430:4;7423:2;7419:7;7414:2;7406:6;7402:15;7398:29;7393:3;7389:39;7385:50;7378:57;;;7153:288;;;;:::o;7446:779::-;7606:4;7654:2;7643:9;7639:18;7684:2;7673:9;7666:21;7707:6;7742;7736:13;7773:6;7765;7758:22;7811:2;7800:9;7796:18;7789:25;;7873:2;7863:6;7860:1;7856:14;7845:9;7841:30;7837:39;7823:53;;7911:2;7903:6;7899:15;7932:1;7942:254;7956:6;7953:1;7950:13;7942:254;;;8049:2;8045:7;8033:9;8025:6;8021:22;8017:36;8012:3;8005:49;8077:39;8109:6;8100;8094:13;8077:39;:::i;:::-;8067:49;-1:-1:-1;8151:2:1;8174:12;;;;8139:15;;;;;7978:1;7971:9;7942:254;;;-1:-1:-1;8213:6:1;;7446:779;-1:-1:-1;;;;;;7446:779:1:o;8547:251::-;8617:6;8670:2;8658:9;8649:7;8645:23;8641:32;8638:52;;;8686:1;8683;8676:12;8638:52;8718:9;8712:16;8737:31;8762:5;8737:31;:::i;9082:184::-;9152:6;9205:2;9193:9;9184:7;9180:23;9176:32;9173:52;;;9221:1;9218;9211:12;9173:52;-1:-1:-1;9244:16:1;;9082:184;-1:-1:-1;9082:184:1:o;9271:247::-;9330:6;9383:2;9371:9;9362:7;9358:23;9354:32;9351:52;;;9399:1;9396;9389:12;9351:52;9438:9;9425:23;9457:31;9482:5;9457:31;:::i;9523:241::-;9579:6;9632:2;9620:9;9611:7;9607:23;9603:32;9600:52;;;9648:1;9645;9638:12;9600:52;9687:9;9674:23;9706:28;9728:5;9706:28;:::i;9769:127::-;9830:10;9825:3;9821:20;9818:1;9811:31;9861:4;9858:1;9851:15;9885:4;9882:1;9875:15;9901:332;10002:4;10060:11;10047:25;10154:2;10150:7;10139:8;10123:14;10119:29;10115:43;10095:18;10091:68;10081:96;;10173:1;10170;10163:12;10081:96;10194:33;;;;;9901:332;-1:-1:-1;;9901:332:1:o;10238:902::-;10356:9;10415:4;10407:5;10391:14;10387:26;10383:37;10380:57;;;10433:1;10430;10423:12;10380:57;10486:2;10480:9;10528:4;10516:17;;-1:-1:-1;;;;;10548:34:1;;10584:22;;;10545:62;10542:88;;;10610:18;;:::i;:::-;10646:2;10639:22;10685:19;;10713:33;10685:19;10713:33;:::i;:::-;10755:23;;10826:2;10815:14;;10802:28;10839:30;10802:28;10839:30;:::i;:::-;10897:2;10885:15;;10878:32;10957:2;10946:14;;10933:28;-1:-1:-1;;;;;10973:30:1;;10970:50;;;11016:1;11013;11006:12;10970:50;11053:52;11090:14;11081:6;11074:5;11070:18;11053:52;:::i;:::-;11048:2;11036:15;;11029:77;-1:-1:-1;11040:6:1;10238:902;-1:-1:-1;;10238:902:1:o;11145:411::-;-1:-1:-1;;;;;11348:32:1;;;11330:51;;11417:32;;11412:2;11397:18;;11390:60;11486:2;11481;11466:18;;11459:30;;;-1:-1:-1;;11506:44:1;;11531:18;;11523:6;11506:44;:::i;11561:800::-;11762:2;11751:9;11744:21;11837:1;11833;11828:3;11824:11;11820:19;11811:6;11805:13;11801:39;11796:2;11785:9;11781:18;11774:67;11895:4;11887:6;11883:17;11877:24;11872:2;11861:9;11857:18;11850:52;11984:1;11980;11975:3;11971:11;11967:19;11961:2;11953:6;11949:15;11943:22;11939:48;11933:3;11922:9;11918:19;11911:77;12070:1;12066;12061:3;12057:11;12053:19;12047:2;12039:6;12035:15;12029:22;12025:48;12019:3;12008:9;12004:19;11997:77;12130:3;12122:6;12118:16;12112:23;12105:4;12094:9;12090:20;12083:53;11725:4;12183:3;12175:6;12171:16;12165:23;12225:4;12219:3;12208:9;12204:19;12197:33;12247:51;12293:3;12282:9;12278:19;12264:12;12247:51;:::i;:::-;12239:59;;;12307:48;12349:4;12338:9;12334:20;12326:6;-1:-1:-1;;;;;8296:31:1;8284:44;;8230:104;12366:225;12433:9;;;12454:11;;;12451:134;;;12507:10;12502:3;12498:20;12495:1;12488:31;12542:4;12539:1;12532:15;12570:4;12567:1;12560:15;12901:245;12968:6;13021:2;13009:9;13000:7;12996:23;12992:32;12989:52;;;13037:1;13034;13027:12;12989:52;13069:9;13063:16;13088:28;13110:5;13088:28;:::i;13527:301::-;13656:3;13694:6;13688:13;13740:6;13733:4;13725:6;13721:17;13716:3;13710:37;13802:1;13766:16;;13791:13;;;-1:-1:-1;13766:16:1;13527:301;-1:-1:-1;13527:301:1:o
Swarm Source
ipfs://8de869caa2e008353a01f58886a1c17bd57fea9e7129e0511f178b38a70da77e
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 ]
[ 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.