Source Code
Overview
MON Balance
MON Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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:
SimplePositionManager
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/ERC165.sol
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(
bytes4 interfaceId
) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// contracts/libraries/external/ERC165Checker.sol
// @author Modified from OpenZeppelin Contracts (utils/introspection/ERC165Checker.sol)
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/
library ERC165Checker {
// As per the EIP-165 spec, no interface should ever match 0xffffffff
bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;
/**
* @dev Returns true if `account` supports the {IERC165} interface.
*/
function supportsERC165(address account) internal view returns (bool) {
// Any contract that implements ERC165 must explicitly indicate support of
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
return
supportsERC165InterfaceUnchecked(
account,
type(IERC165).interfaceId
) &&
!supportsERC165InterfaceUnchecked(account, _INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/
function supportsInterface(
address account,
bytes4 interfaceId
) internal view returns (bool) {
// query support of both ERC165 as per the spec and support of _interfaceId
return
supportsERC165(account) &&
supportsERC165InterfaceUnchecked(account, interfaceId);
}
/**
* @notice Query if a contract implements an interface, does not check ERC165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
*
* Some precompiled contracts will falsely indicate support for a given interface, so caution
* should be exercised when using this function.
*
* Interface identification is specified in ERC-165.
*/
function supportsERC165InterfaceUnchecked(
address account,
bytes4 interfaceId
) internal view returns (bool) {
// prepare call
bytes memory encodedParams = abi.encodeCall(
IERC165.supportsInterface,
(interfaceId)
);
// perform static call
bool success;
uint256 returnSize;
uint256 returnValue;
assembly {
success := staticcall(
30000,
account,
add(encodedParams, 0x20),
mload(encodedParams),
0x00,
0x20
)
returnSize := returndatasize()
returnValue := mload(0x00)
}
return success && returnSize >= 0x20 && returnValue > 0;
}
}
// contracts/libraries/CentralRegistryLib.sol
/// @title Curvance Central Registry Validation Library
/// @notice For validating that Central Registry is configured properly
/// on launch.
library CentralRegistryLib {
/// ERRORS ///
error CentralRegistryLib__InvalidCentralRegistry();
/// INTERNAL FUNCTIONS ///
/// @notice Validates that `cr` is the Protocol Central Registry.
/// @param cr The proposed Protocol Central Registry.
function _isCentralRegistry(ICentralRegistry cr) internal view {
if (
!ERC165Checker.supportsInterface(
address(cr),
type(ICentralRegistry).interfaceId
)
) {
revert CentralRegistryLib__InvalidCentralRegistry();
}
}
}
// contracts/libraries/Multicall.sol
/// @title Curvance Multicall helper.
/// @notice Multicall implementation to support pull based oracles and
/// other chained actions within Curvance.
abstract contract Multicall {
/// TYPES ///
/// @notice Struct containing information on the desired
/// multicall action to execute.
/// @param target The address of the target contract to execute the call at.
/// @param isPriceUpdate Boolean indicating if the call is a price update.
/// @param data The data to attach to the call.
struct MulticallAction {
address target;
bool isPriceUpdate;
bytes data;
}
/// ERRORS ///
error Multicall__InvalidTarget();
error Multicall__UnknownCalldata();
/// EXTERNAL FUNCTIONS ///
/// @notice Executes multiple calls in a single transaction.
/// This can be used to update oracle prices before
/// a liquidity dependent action.
function multicall(
MulticallAction[] calldata calls
) external returns (bytes[] memory results) {
ICentralRegistry cr = _getCentralRegistry();
uint256 numCalls = calls.length;
results = new bytes[](numCalls);
MulticallAction memory cachedCall;
for (uint256 i; i < numCalls; ++i) {
cachedCall = calls[i];
if (cachedCall.isPriceUpdate) {
// CASE: We need to update a pull based price oracle and we
// need a direct call to the target address.
address checker = cr.multicallChecker(cachedCall.target);
// Validate we know how to verify this calldata.
if (checker == address(0)) {
revert Multicall__UnknownCalldata();
}
IMulticallChecker(checker).checkCalldata(
msg.sender,
cachedCall.target,
cachedCall.data
);
results[i] = LowLevelCallsHelper.
_call(cachedCall.target, cachedCall.data);
continue;
}
// CASE: Not a price update and we need delegate the call to the
// current address.
if (address(this) != cachedCall.target) {
revert Multicall__InvalidTarget();
}
results[i] = LowLevelCallsHelper.
_delegateCall(address(this), cachedCall.data);
}
}
/// @notice Returns the Protocol Central Registry contract in interface
/// form.
/// @dev MUST be overridden in every multicallable contract's
/// implementation.
function _getCentralRegistry()
internal
view
virtual
returns (ICentralRegistry);
}
// contracts/libraries/PluginDelegable.sol
/// @title Curvance Plugin Delegation Manager.
/// @notice Facilitates delegated actions on behalf of a user inside Curvance.
/// @dev `PluginDelegable` allows the Curvance Protocol to be a modular system
/// that plugins can be built on top of. By delegating action authority
/// to an address or addresses users can utilize potential third-party
/// features such as limit orders, crosschain actions, reward auto
/// compounding, chained (multiple sequential) actions, etc.
abstract contract PluginDelegable is IPluginDelegable {
/// CONSTANTS ///
/// @notice Curvance DAO Hub.
ICentralRegistry public immutable centralRegistry;
/// STORAGE ///
/// @notice Status of whether a user or contract has the ability to act
/// on behalf of an account.
/// @dev Account address => approval index => Spender address => Can act
/// on behalf of account.
mapping(address => mapping(uint256 => mapping(address => bool)))
internal _isDelegate;
/// EVENTS ///
event DelegateApproval(
address indexed owner,
address indexed delegate,
uint256 approvalIndex,
bool isApproved
);
/// ERRORS ///
error PluginDelegable__Unauthorized();
error PluginDelegable__DelegatingDisabled();
error PluginDelegable_InvalidParameter();
/// CONSTRUCTOR ///
/// @param cr The address of the Central Registry contract.
constructor(ICentralRegistry cr) {
CentralRegistryLib._isCentralRegistry(cr);
centralRegistry = cr;
}
/// EXTERNAL FUNCTIONS ///
/// @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 {
if (delegate == msg.sender) {
revert PluginDelegable_InvalidParameter();
}
// Validate that new delegation configuration is current allowed for
// the caller.
if (centralRegistry.checkNewDelegationDisabled(msg.sender)) {
revert PluginDelegable__DelegatingDisabled();
}
uint256 currentIndex = centralRegistry.userApprovalIndex(msg.sender);
_isDelegate[msg.sender][currentIndex][delegate] = isApproved;
emit DelegateApproval(msg.sender, delegate, currentIndex, isApproved);
}
/// @notice Returns `user`'s current approval index value.
/// @dev The approval index is a way to revoke approval on all tokens,
/// and features at once if a malicious delegation was allowed by
/// `user`.
/// @param user The user to check delegated approval index for.
/// @return result The `user`'s current approval index value.
function userApprovalIndex(
address user
) external view returns (uint256 result) {
result = centralRegistry.userApprovalIndex(user);
}
/// @notice Returns whether `delegate` has the ability to act on behalf of
/// `user`.
/// @param user The address to check whether `delegate` has delegation
/// permissions for.
/// @param delegate The address to check delegation permissions of `user`.
/// @return result Indicates whether `delegate` is an approved delegate or
/// not of `user`, true = is a delegate, false = is not
/// a delegate.
function isDelegate(
address user,
address delegate
) external view returns (bool result) {
result = _isDelegate[user][centralRegistry
.userApprovalIndex(user)][delegate];
}
/// @notice Returns whether a user has delegation disabled.
/// @dev This is not a silver bullet for phishing attacks, but, adds
/// an additional wall of defense.
/// @param user The user to check delegation status for.
/// @return result Indicates whether `user` has delegation disabled
/// or not, true = disabled, false = not disabled.
function checkNewDelegationDisabled(
address user
) external view returns (bool result) {
result = centralRegistry.checkNewDelegationDisabled(user);
}
/// INTERNAL FUNCTIONS ///
/// @notice Checks whether `delegate` has the ability to act on behalf of
/// `user`, reverts if they do not.
/// @param user The address to check whether `delegate` has delegation
/// permissions for.
/// @param delegate The address to check delegation permissions of `user`.
function _checkDelegate(address user, address delegate) internal view {
if (
!_isDelegate[user][centralRegistry
.userApprovalIndex(user)][delegate]
) {
revert PluginDelegable__Unauthorized();
}
}
}
// 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/market/position-management/BasePositionManager.sol
/// @title Curvance Base Position Manager.
/// @notice Base contract for executing leverage related actions.
/// @dev Curvance Position Manager contracts enshrine actions that
/// usually would require multiple sequential actions to facilitate,
/// specifically leveraging a position up or deleveraging it for
/// withdrawal.
///
/// Curvance token contracts facilitate these operations through
/// enshrined integrations with Position Manager callback functions.
///
/// NOTE:
/// Position Manager checks tokens against listed market manager token
/// list. If a market manager ever lists a token with callbacks such as
/// ERC777 this can allow callbacks to occur which could potentially
/// cause issues. Market with callback enabled tokens SHOULD NOT be
/// hooked up to a position manager contract.
///
/// Typical workflow for:
/// Leverage -> borrow assets from a borrowableCToken -> swap debt assets
/// into collateral assets -> deposit collateral assets and collateralize
/// received shares -> check that there is no liquidity shortfall from
/// the initial assets borrowed versus the new collateralized shares.
///
/// Deleverage -> redeem collateralized shares from a cToken for assets
/// -> swap collateral assets for debt assets -> repay outstanding debt
/// with debt assets -> check that there is no liquidity shortfall from
/// the initial shares redeemed versus the newly decreased outstanding
/// debt.
///
/// The "base" contract is the basis on which all position manager are
/// built on top of.
///
abstract contract BasePositionManager is
IPositionManager,
PluginDelegable,
ERC165,
ReentrancyGuard,
Multicall
{
/// CONSTANTS ///
/// @notice The address of wrapped native token on this chain.
address public immutable wrappedNative;
/// @notice Address of the Market Manager linked to this contract.
IMarketManager public immutable marketManager;
/// ERRORS ///
error BasePositionManager__Unauthorized();
error BasePositionManager__InvalidSlippage();
error BasePositionManager__InvalidMarketManager();
error BasePositionManager__InvalidParam();
error BasePositionManager__InvalidAmount();
error BasePositionManager__InvalidTokenPrice();
error BasePositionManager__InsufficientAssetsForRepayment();
/// MODIFIERS ///
/// @dev Executes a predeposit to a leverage action.
/// @param assets The amount of the underlying assets to deposit.
/// @param cToken Curvance token to deposit `assets` into.
modifier preDeposit(uint256 assets, ICToken cToken) {
address collateralAsset = cToken.asset();
// Transfer `collateralAsset` to deposit.
SafeTransferLib.safeTransferFrom(
collateralAsset,
msg.sender,
address(this),
assets
);
// Approve cToken to process a deposit.
SwapperLib._approveIfNeeded(collateralAsset, address(cToken), assets);
// Deposit and collateralize `collateralAsset` in cToken contract.
cToken.depositAsCollateral(assets, msg.sender);
// Remove any excess approval.
SwapperLib._removeApprovalIfNeeded(collateralAsset, address(cToken));
_;
}
/// @dev Checks slippage prior to and after leverage/deleverage action,
/// works similar to reentryguard with pre and post checks.
/// NOTE: This slippage check is primarily a sanity check rather than
/// a security guarantee that users should rely on for protection.
/// Users should perform their own slippage calculations and validations
/// before executing leverage/deleverage operations.
/// @param slippage Slippage accepted by the user for execution of
/// `action` leverage action, in `WAD`.
modifier checkSlippage(address account, uint256 slippage) {
(uint256 collateralBefore, , uint256 debtBefore) = marketManager
.statusOf(account);
uint256 valueIn = collateralBefore - debtBefore;
_;
(uint256 collateralAfter, , uint256 debtAfter) = marketManager
.statusOf(account);
uint256 valueOut = collateralAfter - debtAfter;
// If there was slippage, make sure its within slippage tolerance.
if (valueIn > valueOut) {
if ((valueIn - valueOut) > _mulDiv(valueIn, slippage, WAD)) {
revert BasePositionManager__InvalidSlippage();
}
}
}
/// CONSTRUCTOR ///
/// @param cr The address of the Protocol Central Registry.
/// @param mm The address of the MarketManager which manages liquidity
/// positions between linked cTokens inside a joint market.
/// @param wNative The address of wrapped native token.
constructor(
ICentralRegistry cr,
address mm,
address wNative
) PluginDelegable(cr) {
// Validate that `mm` is configured as a Market Manager inside the
// Protocol Central Registry.
if (!cr.isMarketManager(mm)) {
revert BasePositionManager__InvalidMarketManager();
}
marketManager = IMarketManager(mm);
wrappedNative = wNative;
}
/// EXTERNAL FUNCTIONS ///
/// @notice Allows contract to receive native gas tokens.
receive() external payable {}
/// @notice Deposits into a Curvance position and then leverages in favor
/// of increasing both collateral and debt inside the system.
/// @dev Measures slippage through pre/post conditional slippage check
/// in `checkSlippage` modifier.
/// NOTE: This position manager MUST be recognized as an official
/// Position Manager by the market manager connected to
/// `action.cToken`. Also, the caller MUST have approved this smart
/// contract to have delegated actions inside `action.cToken`.
/// Otherwise, the leveraged deposit will fail.
/// @param assets The amount of the underlying assets to deposit.
/// @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.
/// @param slippage Slippage accepted by the user for execution of
/// `action` leverage action, in WAD (1e18).
function depositAndLeverage(
uint256 assets,
LeverageAction calldata action,
uint256 slippage
) external nonReentrant preDeposit(
assets,
action.cToken
) checkSlippage(msg.sender, slippage) {
// Execute pre deposit, then the leverage action.
_leverage(action, msg.sender);
}
/// @notice Leverages an active Curvance position in favor of increasing
/// both collateral and debt inside the system.
/// @dev Measures slippage through pre/post conditional slippage check
/// in `checkSlippage` modifier.
/// @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.
/// @param slippage Slippage accepted by the user for execution of
/// `action` leverage action, in WAD (1e18).
function leverage(
LeverageAction calldata action,
uint256 slippage
) external nonReentrant checkSlippage(msg.sender, slippage) {
// Execute leverage action.
_leverage(action, msg.sender);
}
/// @notice Leverages an active Curvance position in favor of increasing
/// both collateral and debt inside the system, via delegation.
/// @dev Measures slippage through pre/post conditional slippage check
/// in `checkSlippage` modifier.
/// NOTE: Be careful who you approve here!
/// The caller can select slippage, potentially causing loss of funds
/// if delegation is provided to a malicious party.
/// @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.
/// @param account The account to leverage an active Curvance position
/// for.
/// @param slippage Slippage accepted by the user for execution of
/// `action` leverage action, in WAD (1e18).
function leverageFor(
LeverageAction calldata action,
address account,
uint256 slippage
) external nonReentrant checkSlippage(account, slippage) {
_checkDelegate(account, msg.sender);
// Check for delegation permissions, then the leverage action.
_leverage(action, account);
}
/// @notice Deleverages an active Curvance position in favor of decreasing
/// both collateral and debt inside the system.
/// @dev Measures slippage through pre/post conditional slippage check
/// in `checkSlippage` modifier.
/// NOTE: Be careful who you approve here!
/// The caller can select slippage, potentially causing loss of funds
/// if delegation is provided to a malicious party.
/// @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.
/// @param slippage Slippage accepted by the user for execution of
/// `action` deleverage action, in WAD (1e18).
function deleverage(
DeleverageAction calldata action,
uint256 slippage
) external nonReentrant checkSlippage(msg.sender, slippage) {
// Execute deleverage action.
_deleverage(action, msg.sender);
}
/// @notice Deleverages an active Curvance position in favor of decreasing
/// both collateral and debt inside the system, via delegation.
/// @dev Measures slippage through pre/post conditional slippage check
/// in `checkSlippage` modifier.
/// @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.
/// @param account The account to deleverage an active Curvance position
/// for.
/// @param slippage Slippage accepted by the user for execution of
/// `action` deleverage action, in WAD (1e18).
function deleverageFor(
DeleverageAction calldata action,
address account,
uint256 slippage
) external nonReentrant checkSlippage(account, slippage) {
_checkDelegate(account, msg.sender);
// Check for delegation permissions, then the deleverage action.
_deleverage(action, account);
}
/// @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 borrowable token 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 override {
ICToken cToken = action.cToken;
// Validate action.cToken is a listed Curvance market to prevent callbacks
// through untrusted tokens during the callback context.
if (!marketManager.isListed(address(cToken))) {
revert BasePositionManager__Unauthorized();
}
// Cache debt asset address.
address debtAsset = IBorrowableCToken(borrowableCToken).asset();
// Validate that `cToken` is listed inside `marketManager` and is the
// caller, then that the action instructions are built correct, then
// take the protocol fee, if any.
action.borrowAssets = _validateInputsAndApplyFee(
borrowableCToken,
borrowAssets,
address(action.borrowableCToken),
action.borrowAssets,
debtAsset
);
// Unwrap leverage instructions for collateral deposit.
address collateralAsset = cToken.asset();
// Swap borrowed assets into collateral asset underlying.
_swapDebtAssetToCollateralAsset(action, owner);
uint256 amount = IERC20(collateralAsset).balanceOf(address(this));
// Approve `amount` of `collateralAsset` to `cToken` contract.
SwapperLib._approveIfNeeded(collateralAsset, address(cToken), amount);
// Enter Curvance collateral position.
uint256 shares = cToken.depositAsCollateral(amount, owner);
// Make sure sufficient shares were received from deposit action.
if (shares < action.expectedShares) {
revert BasePositionManager__InvalidSlippage();
}
uint256 remaining = IERC20(debtAsset).balanceOf(address(this));
// Transfer remaining borrow underlying back to the user.
if (remaining > 0) {
SafeTransferLib.safeTransfer(debtAsset, owner, remaining);
}
// Remove any excess approval.
SwapperLib._removeApprovalIfNeeded(collateralAsset, address(cToken));
}
/// @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 cToken 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.
/// swapActions 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 override {
IBorrowableCToken borrowableCToken = action.borrowableCToken;
if (!marketManager.isListed(address(borrowableCToken))) {
revert BasePositionManager__Unauthorized();
}
// Cache collateral asset address.
address collateralAsset = ICToken(cToken).asset();
// Validate that `cToken` is listed inside `marketManager` and is the
// caller, then that the action instructions are built correct, then
// take the protocol fee, if any.
action.collateralAssets = _validateInputsAndApplyFee(
cToken,
collateralAssets,
address(action.cToken),
action.collateralAssets,
collateralAsset
);
// Swap redeemed `collateralAsset` assets into debt token assets.
_swapCollateralAssetToDebtAsset(action);
// Unwrap deleverage instructions for debt repayment.
address debtAsset = borrowableCToken.asset();
uint256 assetsHeld = IERC20(debtAsset).balanceOf(address(this));
uint256 repayAssets = action.repayAssets;
if (repayAssets == 0) {
// Accrue any interest owed so repayAssets includes all
// `owner` debt.
repayAssets = borrowableCToken.debtBalanceUpdated(owner);
}
if (repayAssets > assetsHeld) {
revert BasePositionManager__InsufficientAssetsForRepayment();
}
uint256 remaining = assetsHeld - repayAssets;
// Approve `repayAssets` of `debtAsset` to `borrowableCToken` contract.
SwapperLib._approveIfNeeded(
debtAsset,
address(borrowableCToken),
repayAssets
);
// Repay debt.
borrowableCToken.repayFor(repayAssets, owner);
// Transfer remaining borrow underlying back to user.
if (remaining > 0) {
SafeTransferLib.safeTransfer(debtAsset, owner, remaining);
}
remaining = IERC20(collateralAsset).balanceOf(address(this));
// Transfer remaining collateral underlying back to the user.
if (remaining > 0) {
SafeTransferLib.safeTransfer(collateralAsset, owner, remaining);
}
// Transfer remaining swap dust back to the user.
uint256 numSwaps = action.swapActions.length;
if (numSwaps > 0) {
for (uint256 i; i < numSwaps; ++i) {
remaining =
CommonLib._balanceOf(action.swapActions[i].outputToken);
if (remaining > 0) {
_transferToRecipient(
action.swapActions[i].outputToken,
owner,
remaining
);
}
}
}
// Remove any excess approval.
SwapperLib._removeApprovalIfNeeded(
debtAsset,
address(borrowableCToken)
);
}
/// PUBLIC FUNCTIONS ///
/// @inheritdoc ERC165
function supportsInterface(
bytes4 interfaceId
) public view override returns (bool result) {
result = interfaceId == type(IPositionManager).interfaceId ||
super.supportsInterface(interfaceId);
}
/// INTERNAL FUNCTIONS ///
/// @notice Validate `action` parameters versus function parameters and
/// apply any protocol fee.
/// @param cToken The Curvance token given from function parameters,
/// should be token used during the callback action.
/// @param assets The amount of `cTokenUnderlying` given from function
/// parameters to be used during the callback action.
/// @param actionToken The Curvance token given from `action` parameters,
/// should be token used during the callback action.
/// @param actionAssets The amount of `cTokenUnderlying` given from
/// `action` parameters to be used during the callback
/// action.
/// @param cTokenUnderlying The `asset()` token of `cToken`.
/// @return The `cTokenUnderlying` assets for callback action potentially
/// with fee applied.
function _validateInputsAndApplyFee(
address cToken,
uint256 assets,
address actionToken,
uint256 actionAssets,
address cTokenUnderlying
) internal returns (uint256) {
// Validate that the token itself is executing the callback and
// `cToken` is actually listed in this Market Manager.
if (msg.sender != cToken || !marketManager.isListed(cToken)) {
revert BasePositionManager__Unauthorized();
}
// Validate enough `cTokenUnderlying` was received to preform desired
// action.
if (IERC20(cTokenUnderlying).balanceOf(address(this)) < assets) {
revert BasePositionManager__InvalidAmount();
}
// Validate that calldata matches explicit action inputs.
if (cToken != address(actionToken) || assets != actionAssets) {
revert BasePositionManager__InvalidParam();
}
// Calculate protocol fee, rounded up, in favor of protocol.
uint256 fee = FixedPointMathLib.mulDivUp(
actionAssets,
centralRegistry.protocolLeverageFee(),
BPS
);
// Apply protocol fee, if there is any.
if (fee > 0) {
actionAssets -= fee;
SafeTransferLib.safeTransfer(
cTokenUnderlying,
centralRegistry.daoAddress(),
fee
);
}
// Return `cTokenUnderlying` assets for callback action potentially
// with fee applied.
return actionAssets;
}
/// @notice Leverages an active Curvance position in favor of increasing
/// both collateral and debt inside the system.
/// @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.
/// @param account The account to leverage an active Curvance position
/// for.
function _leverage(
LeverageAction memory action,
address account
) internal {
// Validate `action.borrowableCToken` is a known Curvance token.
if (!marketManager.isListed(address(action.borrowableCToken))) {
revert BasePositionManager__Unauthorized();
}
action.borrowableCToken.borrowForPositionManager(
action.borrowAssets,
account,
action
);
}
/// @notice Deleverages an active Curvance position in favor of decreasing
/// both collateral and debt inside the system.
/// @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.
/// @param account The account to deleverage an active Curvance position
/// for.
function _deleverage(
DeleverageAction memory action,
address account
) internal {
// Validate `action.cToken` is a known Curvance token.
if (!marketManager.isListed(address(action.cToken))) {
revert BasePositionManager__Unauthorized();
}
action.cToken.withdrawByPositionManager(
action.collateralAssets,
account,
action
);
}
/// @notice Helper function for efficiently transferring tokens
/// to desired user.
/// @param token The token to transfer to `recipient`,
/// this can be the network gas token.
/// @param recipient The user receiving `token`.
/// @param amount The amount of `token` to be transferred to `recipient`.
function _transferToRecipient(
address token,
address recipient,
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;
}
// Transfer `amount` tokens to refund to `recipient`.
SafeTransferLib.safeTransfer(token, recipient, amount);
}
/// @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) {
z = FixedPointMathLib.mulDiv(x, y, d);
}
/// @notice Returns the Central Registry contract in interface form.
function _getCentralRegistry()
internal
view
override
returns (ICentralRegistry)
{
return centralRegistry;
}
/// INTERNAL FUNCTIONS TO OVERRIDE ///
/// @notice Callback function on borrowing tokens from a Curvance token
/// providing instant liquidity in the debt token underlying which
/// is then swapped into the underlying of a collateral token that
/// a user currently has collateralized against the debt position,
/// creating/increasing a leveraged spot position.
/// @dev MUST be overridden in every Position Manager implementation.
function _swapDebtAssetToCollateralAsset(
LeverageAction memory, /* action */
address /* receiver */
) internal virtual;
/// @notice Callback function on redemption of tokens from a Curvance token
/// providing instant liquidity in the collateral token underlying
/// which is then swapped into the underlying of a debt token that
/// a user is currently borrowing from, partially or fully closing
/// a leveraged spot position.
/// @dev MUST be overridden in every Position Manager implementation.
function _swapCollateralAssetToDebtAsset(
DeleverageAction memory /* action */
) internal virtual;
}
// contracts/market/position-management/SimplePositionManager.sol
/// @title Curvance Simple Position Manager.
/// @notice Simple Asset-specific contract for executing leverage related
/// actions.
/// @dev Curvance Position Manager contracts enshrine actions that
/// usually would require multiple sequential actions to facilitate,
/// specifically leveraging a position up or deleveraging it for
/// withdrawal.
///
/// Curvance token contracts facilitate these operations through
/// enshrined integrations with Position Manager callback functions.
///
/// Typical workflow for:
/// Leverage -> borrow assets from a borrowableCToken -> swap debt assets
/// into collateral assets -> deposit collateral assets and collateralize
/// received shares -> check that there is no liquidity shortfall from
/// the initial assets borrowed versus the new collateralized shares.
///
/// Deleverage -> redeem collateralized shares from a cToken for assets
/// -> swap collateral assets for debt assets -> repay outstanding debt
/// with debt assets -> check that there is no liquidity shortfall from
/// the initial shares redeemed versus the newly decreased outstanding
/// debt.
///
/// The "Simple" contract is the position manager for working with
/// generic non-native erc20 tokens such as USDC or WETH.
///
contract SimplePositionManager is BasePositionManager {
/// CONSTRUCTOR ///
/// @param cr The address of the Protocol Central Registry.
/// @param mm The address of the MarketManager which manages liquidity
/// positions between linked cTokens inside a joint market.
/// @param wNative The address of wrapped native token.
constructor(
ICentralRegistry cr,
address mm,
address wNative
) BasePositionManager(cr, mm, wNative) {}
/// @notice Callback function on borrowing tokens from an borrowableCToken
/// contract providing instant liquidity in the borrowableCToken
/// underlying which is then swapped into the underlying of a
/// cToken that a user is currently putting up as collateral
/// against the borrowableCToken debt position, creating a
/// leveraged spot position.
/// @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 _swapDebtAssetToCollateralAsset(
LeverageAction memory action,
address /* receiver */
) internal virtual override {
address debtAsset = action.borrowableCToken.asset();
address collateralAsset = action.cToken.asset();
// This check implies they have selected the same cToken as both
// cToken and borrowableCToken, otherwise its not possible to have
// the same underlying.
if (CommonLib._isMatchingToken(debtAsset, collateralAsset)) {
revert BasePositionManager__InvalidParam();
}
SwapperLib.Swap memory swapAction = action.swapAction;
if (
swapAction.call.length == 0 ||
swapAction.target == address(0) ||
swapAction.inputToken != debtAsset ||
swapAction.outputToken != collateralAsset ||
swapAction.inputAmount != action.borrowAssets
) {
revert BasePositionManager__InvalidParam();
}
// Swap debt asset to collateral asset.
SwapperLib._swapSafe(centralRegistry, swapAction);
}
/// @notice Callback function on redemption of tokens from a cToken vault
/// providing instant liquidity in the cToken underlying which is
/// then swapped into the underlying of an borrowableCToken that a
/// user is currently borrowing from, partially or fully closing a
/// leveraged spot position.
/// @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 _swapCollateralAssetToDebtAsset(
DeleverageAction memory action
) internal virtual override {
address collateralAsset = action.cToken.asset();
address debtAsset = action.borrowableCToken.asset();
// This check implies they have selected the same cToken as both
// cToken and borrowableCToken, otherwise its not possible to have
// the same underlying.
if (CommonLib._isMatchingToken(debtAsset, collateralAsset)) {
revert BasePositionManager__InvalidParam();
}
// For simple actions there should only ever be one swap.
if (action.swapActions.length != 1) {
revert BasePositionManager__InvalidParam();
}
// Load the one swap action.
SwapperLib.Swap memory swapAction = action.swapActions[0];
if (
swapAction.call.length == 0 ||
swapAction.target == address(0) ||
swapAction.inputToken != collateralAsset ||
swapAction.outputToken != debtAsset ||
swapAction.inputAmount != action.collateralAssets
) {
revert BasePositionManager__InvalidParam();
}
// Swap collateral asset to debt asset.
SwapperLib._swapSafe(centralRegistry, swapAction);
}
}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":"mm","type":"address"},{"internalType":"address","name":"wNative","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BasePositionManager__InsufficientAssetsForRepayment","type":"error"},{"inputs":[],"name":"BasePositionManager__InvalidAmount","type":"error"},{"inputs":[],"name":"BasePositionManager__InvalidMarketManager","type":"error"},{"inputs":[],"name":"BasePositionManager__InvalidParam","type":"error"},{"inputs":[],"name":"BasePositionManager__InvalidSlippage","type":"error"},{"inputs":[],"name":"BasePositionManager__InvalidTokenPrice","type":"error"},{"inputs":[],"name":"BasePositionManager__Unauthorized","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":"PluginDelegable_InvalidParameter","type":"error"},{"inputs":[],"name":"PluginDelegable__DelegatingDisabled","type":"error"},{"inputs":[],"name":"PluginDelegable__Unauthorized","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[],"name":"SwapperLib__SameTokens","type":"error"},{"inputs":[{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"SwapperLib__Slippage","type":"error"},{"inputs":[{"internalType":"address","name":"inputToken","type":"address"}],"name":"SwapperLib__TokenPrice","type":"error"},{"inputs":[],"name":"SwapperLib__UnknownCalldata","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"approvalIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isApproved","type":"bool"}],"name":"DelegateApproval","type":"event"},{"inputs":[],"name":"centralRegistry","outputs":[{"internalType":"contract ICentralRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"checkNewDelegationDisabled","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract ICToken","name":"cToken","type":"address"},{"internalType":"uint256","name":"collateralAssets","type":"uint256"},{"internalType":"contract IBorrowableCToken","name":"borrowableCToken","type":"address"},{"internalType":"uint256","name":"repayAssets","type":"uint256"},{"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":"swapActions","type":"tuple[]"},{"internalType":"bytes","name":"auxData","type":"bytes"}],"internalType":"struct IPositionManager.DeleverageAction","name":"action","type":"tuple"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"deleverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract ICToken","name":"cToken","type":"address"},{"internalType":"uint256","name":"collateralAssets","type":"uint256"},{"internalType":"contract IBorrowableCToken","name":"borrowableCToken","type":"address"},{"internalType":"uint256","name":"repayAssets","type":"uint256"},{"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":"swapActions","type":"tuple[]"},{"internalType":"bytes","name":"auxData","type":"bytes"}],"internalType":"struct IPositionManager.DeleverageAction","name":"action","type":"tuple"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"deleverageFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"components":[{"internalType":"contract IBorrowableCToken","name":"borrowableCToken","type":"address"},{"internalType":"uint256","name":"borrowAssets","type":"uint256"},{"internalType":"contract ICToken","name":"cToken","type":"address"},{"internalType":"uint256","name":"expectedShares","type":"uint256"},{"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":"bytes","name":"auxData","type":"bytes"}],"internalType":"struct IPositionManager.LeverageAction","name":"action","type":"tuple"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"depositAndLeverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"delegate","type":"address"}],"name":"isDelegate","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IBorrowableCToken","name":"borrowableCToken","type":"address"},{"internalType":"uint256","name":"borrowAssets","type":"uint256"},{"internalType":"contract ICToken","name":"cToken","type":"address"},{"internalType":"uint256","name":"expectedShares","type":"uint256"},{"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":"bytes","name":"auxData","type":"bytes"}],"internalType":"struct IPositionManager.LeverageAction","name":"action","type":"tuple"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"leverage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"contract IBorrowableCToken","name":"borrowableCToken","type":"address"},{"internalType":"uint256","name":"borrowAssets","type":"uint256"},{"internalType":"contract ICToken","name":"cToken","type":"address"},{"internalType":"uint256","name":"expectedShares","type":"uint256"},{"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":"bytes","name":"auxData","type":"bytes"}],"internalType":"struct IPositionManager.LeverageAction","name":"action","type":"tuple"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"leverageFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"marketManager","outputs":[{"internalType":"contract IMarketManager","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":[{"internalType":"address","name":"borrowableCToken","type":"address"},{"internalType":"uint256","name":"borrowAssets","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"contract IBorrowableCToken","name":"borrowableCToken","type":"address"},{"internalType":"uint256","name":"borrowAssets","type":"uint256"},{"internalType":"contract ICToken","name":"cToken","type":"address"},{"internalType":"uint256","name":"expectedShares","type":"uint256"},{"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":"bytes","name":"auxData","type":"bytes"}],"internalType":"struct IPositionManager.LeverageAction","name":"action","type":"tuple"}],"name":"onBorrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"cToken","type":"address"},{"internalType":"uint256","name":"collateralAssets","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"components":[{"internalType":"contract ICToken","name":"cToken","type":"address"},{"internalType":"uint256","name":"collateralAssets","type":"uint256"},{"internalType":"contract IBorrowableCToken","name":"borrowableCToken","type":"address"},{"internalType":"uint256","name":"repayAssets","type":"uint256"},{"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":"swapActions","type":"tuple[]"},{"internalType":"bytes","name":"auxData","type":"bytes"}],"internalType":"struct IPositionManager.DeleverageAction","name":"action","type":"tuple"}],"name":"onRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"},{"internalType":"bool","name":"isApproved","type":"bool"}],"name":"setDelegateApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userApprovalIndex","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wrappedNative","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60e060405234801561000f575f5ffd5b50604051613b36380380613b3683398101604081905261002e91610203565b8282828261003b816100e3565b6001600160a01b03908116608052604051637d5528bd60e01b8152838216600482015290841690637d5528bd90602401602060405180830381865afa158015610086573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906100aa919061024d565b6100c757604051630afb42eb60e01b815260040160405180910390fd5b6001600160a01b0391821660c0521660a0525061026c92505050565b6100f4816399011ef160e01b610114565b610111576040516369b5e45b60e11b815260040160405180910390fd5b50565b5f61011e83610136565b801561012f575061012f8383610169565b9392505050565b5f610148826301ffc9a760e01b610169565b80156101635750610161826001600160e01b0319610169565b155b92915050565b6040516001600160e01b0319821660248201525f90819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b17815282519293505f9283928392909183918a617530fa92503d91505f5190508280156101d9575060208210155b80156101e457505f81115b979650505050505050565b6001600160a01b0381168114610111575f5ffd5b5f5f5f60608486031215610215575f5ffd5b8351610220816101ef565b6020850151909350610231816101ef565b6040850151909250610242816101ef565b809150509250925092565b5f6020828403121561025d575f5ffd5b8151801515811461012f575f5ffd5b60805160a05160c0516137ea61034c5f395f8181610142015281816103cd015281816108cb01528181610c2d01528181610ce001528181610f0d01528181610fc0015281816111790152818161170e015281816117cb015281816118f6015281816119c30152818161223e01526123a901525f818161031301528181611f320152611fa201525f818161022a0152818161080c015281816110bf01528181611241015281816112e7015281816113f10152818161146001528181611b1901528181611bb901528181611e19015281816121f0015261256201526137ea5ff3fe6080604052600436106100f2575f3560e01c80639616756e11610087578063e8bbf5d711610057578063e8bbf5d7146102d6578063eb6d3a1114610302578063ebf1965314610335578063fe391e8c14610354575f5ffd5b80639616756e1461024c578063abaa0bbf1461026b578063c3c854b61461028a578063e6248d55146102a9575f5ffd5b806363e6a0e4116100c257806363e6a0e4146101bc5780637f848328146101db57806387c88173146101fa5780638f73dcfa14610219575f5ffd5b806301ffc9a7146100fd57806341ed2c12146101315780634e908d061461017c5780635fec5d0b1461019d575f5ffd5b366100f957005b5f5ffd5b348015610108575f5ffd5b5061011c610117366004612c5c565b610373565b60405190151581526020015b60405180910390f35b34801561013c575f5ffd5b506101647f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610128565b348015610187575f5ffd5b5061019b610196366004612f3d565b6103a9565b005b3480156101a8575f5ffd5b5061011c6101b7366004612fa4565b6107d7565b3480156101c7575f5ffd5b5061019b6101d6366004613049565b6108a7565b3480156101e6575f5ffd5b5061019b6101f53660046130ba565b610bde565b348015610205575f5ffd5b5061019b6102143660046130fb565b610dba565b348015610224575f5ffd5b506101647f000000000000000000000000000000000000000000000000000000000000000081565b348015610257575f5ffd5b5061011c610266366004613147565b61109e565b348015610276575f5ffd5b5061019b6102853660046130ba565b61112a565b348015610295575f5ffd5b5061019b6102a436600461316f565b611203565b3480156102b4575f5ffd5b506102c86102c3366004613147565b6113d0565b604051908152602001610128565b3480156102e1575f5ffd5b506102f56102f036600461319b565b61145c565b6040516101289190613238565b34801561030d575f5ffd5b506101647f000000000000000000000000000000000000000000000000000000000000000081565b348015610340575f5ffd5b5061019b61034f36600461329b565b6116be565b34801561035f575f5ffd5b5061019b61036e36600461329b565b6118a6565b5f6001600160e01b031982166316bb16f160e11b14806103a357506301ffc9a760e01b6001600160e01b03198316145b92915050565b6040818101519051637bca031760e11b81526001600160a01b0380831660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f794062e90602401602060405180830381865afa158015610412573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061043691906132f0565b6104535760405163792b839760e11b815260040160405180910390fd5b5f856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610490573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104b4919061330b565b90506104ca8686855f0151866020015185611990565b60208401526104d883611c48565b5f826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610515573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610539919061330b565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610580573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a49190613326565b60608601519091505f819003610620576040516357d159d560e01b81526001600160a01b0388811660048301528616906357d159d5906024016020604051808303815f875af11580156105f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061061d9190613326565b90505b81811115610641576040516329efdcc960e11b815260040160405180910390fd5b5f61064c8284613351565b9050610659848784611e45565b604051632796469160e21b8152600481018390526001600160a01b038981166024830152871690639e591a44906044015f604051808303815f87803b1580156106a0575f5ffd5b505af11580156106b2573d5f5f3e3d5ffd5b505050505f8111156106c9576106c9848983611e62565b6040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa15801561070b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072f9190613326565b9050801561074257610742858983611e62565b60808701515180156107c0575f5b818110156107be576107828960800151828151811061077157610771613364565b602002602001015160400151611ea2565b925082156107b6576107b6896080015182815181106107a3576107a3613364565b6020026020010151604001518b85611f22565b600101610750565b505b6107ca8588611fcf565b5050505050505050505050565b6001600160a01b038281165f81815260208190526040808220905163e6248d5560e01b815260048101939093529092909183917f0000000000000000000000000000000000000000000000000000000000000000169063e6248d5590602401602060405180830381865afa158015610851573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108759190613326565b815260208082019290925260409081015f9081206001600160a01b039095168152939091529091205460ff1692915050565b6040818101519051637bca031760e11b81526001600160a01b0380831660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f794062e90602401602060405180830381865afa158015610910573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061093491906132f0565b6109515760405163792b839760e11b815260040160405180910390fd5b5f856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109b2919061330b565b90506109c88686855f0151866020015185611990565b8360200181815250505f826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a0e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a32919061330b565b9050610a3e8486612062565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610a82573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aa69190613326565b9050610ab3828583611e45565b604051632f4a61d960e01b8152600481018290526001600160a01b0387811660248301525f9190861690632f4a61d9906044016020604051808303815f875af1158015610b02573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b269190613326565b90508560600151811015610b4d576040516375633b0560e11b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610b91573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bb59190613326565b90508015610bc857610bc8858983611e62565b610bd28487611fcf565b50505050505050505050565b688000000000ab143c065c15610bfb5763ab143c065f526004601cfd5b30688000000000ab143c065d6040516397a5d5b560e01b815233600482018190529082905f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906397a5d5b5906024016060604051808303815f875af1158015610c73573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c979190613378565b92505091505f8183610ca99190613351565b9050610cbd610cb7886133a3565b3361221d565b6040516397a5d5b560e01b81526001600160a01b0386811660048301525f9182917f000000000000000000000000000000000000000000000000000000000000000016906397a5d5b5906024016060604051808303815f875af1158015610d26573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d4a9190613378565b92505091505f8183610d5c9190613351565b905080841115610da257610d798488670de0b6b3a7640000612325565b610d838286613351565b1115610da2576040516375633b0560e11b815260040160405180910390fd5b50505050505050505f688000000000ab143c065d5050565b688000000000ab143c065c15610dd75763ab143c065f526004601cfd5b30688000000000ab143c065d82610df46060840160408501613147565b5f816001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e31573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e55919061330b565b9050610e6381333086612339565b610e6e818385611e45565b604051632f4a61d960e01b8152600481018490523360248201526001600160a01b03831690632f4a61d9906044016020604051808303815f875af1158015610eb8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610edc9190613326565b50610ee78183611fcf565b6040516397a5d5b560e01b815233600482018190529085905f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906397a5d5b5906024016060604051808303815f875af1158015610f53573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f779190613378565b92505091505f8183610f899190613351565b9050610f9d610f978b6133ae565b33612388565b6040516397a5d5b560e01b81526001600160a01b0386811660048301525f9182917f000000000000000000000000000000000000000000000000000000000000000016906397a5d5b5906024016060604051808303815f875af1158015611006573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061102a9190613378565b92505091505f818361103c9190613351565b905080841115611082576110598488670de0b6b3a7640000612325565b6110638286613351565b1115611082576040516375633b0560e11b815260040160405180910390fd5b50505050505050505050505f688000000000ab143c065d505050565b604051634b0b3ab760e11b81526001600160a01b0382811660048301525f917f000000000000000000000000000000000000000000000000000000000000000090911690639616756e90602401602060405180830381865afa158015611106573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a391906132f0565b688000000000ab143c065c156111475763ab143c065f526004601cfd5b30688000000000ab143c065d6040516397a5d5b560e01b815233600482018190529082905f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906397a5d5b5906024016060604051808303815f875af11580156111bf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111e39190613378565b92505091505f81836111f59190613351565b9050610cbd610f97886133ae565b336001600160a01b0383160361122c57604051636eef2f3f60e11b815260040160405180910390fd5b604051634b0b3ab760e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690639616756e90602401602060405180830381865afa15801561128e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112b291906132f0565b156112d0576040516302d5da9f60e01b815260040160405180910390fd5b60405163e6248d5560e01b81523360048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e6248d5590602401602060405180830381865afa158015611334573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113589190613326565b335f8181526020818152604080832085845282528083206001600160a01b03891680855290835292819020805460ff191688151590811790915581518681529283015293945090927ffeeb3502e62327bd3fece59983b972dc941e6abedd652971aac3adea23cf7e17910160405180910390a3505050565b60405163e6248d5560e01b81526001600160a01b0382811660048301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063e6248d5590602401602060405180830381865afa158015611438573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a39190613326565b60607f000000000000000000000000000000000000000000000000000000000000000082806001600160401b0381111561149857611498612ca1565b6040519080825280602002602001820160405280156114cb57816020015b60608152602001906001900390816114b65790505b5060408051606080820183525f80835260208301819052928201529194505b828110156116b45786868281811061150457611504613364565b905060200281019061151691906133b9565b61151f906133d7565b915081602001511561165657815160405163191d0cc560e11b81526001600160a01b0391821660048201525f9186169063323a198a90602401602060405180830381865afa158015611573573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611597919061330b565b90506001600160a01b0381166115c057604051632f3285fb60e21b815260040160405180910390fd5b8251604080850151905163bd0226d760e01b81526001600160a01b0384169263bd0226d7926115f5923392919060040161345c565b5f604051808303815f87803b15801561160c575f5ffd5b505af115801561161e573d5f5f3e3d5ffd5b50505050611633835f01518460400151612467565b86838151811061164557611645613364565b6020026020010181905250506116ac565b81516001600160a01b0316301461168057604051637720ccd960e01b815260040160405180910390fd5b61168e3083604001516124dc565b8582815181106116a0576116a0613364565b60200260200101819052505b6001016114ea565b5050505092915050565b688000000000ab143c065c156116db5763ab143c065f526004601cfd5b30688000000000ab143c065d6040516397a5d5b560e01b81526001600160a01b038084166004830152839183915f9182917f000000000000000000000000000000000000000000000000000000000000000016906397a5d5b5906024016060604051808303815f875af1158015611754573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117789190613378565b92505091505f818361178a9190613351565b90506117968733612530565b6117a86117a2896133a3565b8861221d565b6040516397a5d5b560e01b81526001600160a01b0386811660048301525f9182917f000000000000000000000000000000000000000000000000000000000000000016906397a5d5b5906024016060604051808303815f875af1158015611811573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118359190613378565b92505091505f81836118479190613351565b90508084111561188d576118648488670de0b6b3a7640000612325565b61186e8286613351565b111561188d576040516375633b0560e11b815260040160405180910390fd5b50505050505050505f688000000000ab143c065d505050565b688000000000ab143c065c156118c35763ab143c065f526004601cfd5b30688000000000ab143c065d6040516397a5d5b560e01b81526001600160a01b038084166004830152839183915f9182917f000000000000000000000000000000000000000000000000000000000000000016906397a5d5b5906024016060604051808303815f875af115801561193c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119609190613378565b92505091505f81836119729190613351565b905061197e8733612530565b6117a861198a896133ae565b88612388565b5f336001600160a01b038716141580611a2e5750604051637bca031760e11b81526001600160a01b0387811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063f794062e90602401602060405180830381865afa158015611a08573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a2c91906132f0565b155b15611a4c5760405163792b839760e11b815260040160405180910390fd5b6040516370a0823160e01b815230600482015285906001600160a01b038416906370a0823190602401602060405180830381865afa158015611a90573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ab49190613326565b1015611ad3576040516307d198f760e11b815260040160405180910390fd5b836001600160a01b0316866001600160a01b0316141580611af45750828514155b15611b12576040516307c426b560e21b815260040160405180910390fd5b5f611b9f847f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fe5764846040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b73573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b979190613326565b612710612613565b90508015611c3d57611bb18185613351565b9350611c3d837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632131c68c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c13573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c37919061330b565b83611e62565b509195945050505050565b5f815f01516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c88573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cac919061330b565b90505f82604001516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cef573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d13919061330b565b9050611d1f818361263f565b15611d3d576040516307c426b560e21b815260040160405180910390fd5b826080015151600114611d63576040516307c426b560e21b815260040160405180910390fd5b5f83608001515f81518110611d7a57611d7a613364565b602002602001015190508060a00151515f1480611da2575060608101516001600160a01b0316155b80611dc25750826001600160a01b0316815f01516001600160a01b031614155b80611de35750816001600160a01b031681604001516001600160a01b031614155b80611df657508360200151816020015114155b15611e14576040516307c426b560e21b815260040160405180910390fd5b611e3e7f00000000000000000000000000000000000000000000000000000000000000008261268f565b5050505050565b611e4e83612763565b611e5d57611e5d838383612798565b505050565b816014528060345263a9059cbb60601b5f5260205f604460105f875af13d1560015f51141716611e99576390b8ec185f526004601cfd5b5f603452505050565b5f611eac82612763565b611f1b576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611ef2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f169190613326565b6103a3565b4792915050565b611f2b83612763565b15611fc4577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b158015611f89575f5ffd5b505af1158015611f9b573d5f5f3e3d5ffd5b50505050507f000000000000000000000000000000000000000000000000000000000000000092505b611e5d838383611e62565b611fd882612763565b61205e57604051636eb1769f60e11b81523060048201526001600160a01b0382811660248301525f919084169063dd62ed3e90604401602060405180830381865afa158015612029573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061204d9190613326565b111561205e5761205e82825f612798565b5050565b5f825f01516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120a2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120c6919061330b565b90505f83604001516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612109573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061212d919061330b565b9050612139828261263f565b15612157576040516307c426b560e21b815260040160405180910390fd5b608084015160a0810151511580612179575060608101516001600160a01b0316155b806121995750826001600160a01b0316815f01516001600160a01b031614155b806121ba5750816001600160a01b031681604001516001600160a01b031614155b806121cd57508460200151816020015114155b156121eb576040516307c426b560e21b815260040160405180910390fd5b6122157f00000000000000000000000000000000000000000000000000000000000000008261268f565b505050505050565b8151604051637bca031760e11b81526001600160a01b0391821660048201527f00000000000000000000000000000000000000000000000000000000000000009091169063f794062e90602401602060405180830381865afa158015612285573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122a991906132f0565b6122c65760405163792b839760e11b815260040160405180910390fd5b8151602083015160405163bdca672360e01b81526001600160a01b039092169163bdca6723916122fc91859087906004016134df565b5f604051808303815f87803b158015612313575f5ffd5b505af1158015612215573d5f5f3e3d5ffd5b5f6123318484846127cf565b949350505050565b60405181606052826040528360601b602c526323b872dd60601b600c5260205f6064601c5f895af13d1560015f5114171661237b57637939f4245f526004601cfd5b5f60605260405250505050565b8151604051637bca031760e11b81526001600160a01b0391821660048201527f00000000000000000000000000000000000000000000000000000000000000009091169063f794062e90602401602060405180830381865afa1580156123f0573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061241491906132f0565b6124315760405163792b839760e11b815260040160405180910390fd5b8151602083015160405163010b626160e71b81526001600160a01b03909216916385b13080916122fc91859087906004016135bc565b60605f5f846001600160a01b03165f856040516124849190613642565b5f6040518083038185875af1925050503d805f81146124be576040519150601f19603f3d011682016040523d82523d5f602084013e6124c3565b606091505b50915091506124d38583836127f3565b95945050505050565b60605f5f846001600160a01b0316846040516124f89190613642565b5f60405180830381855af49150503d805f81146124be576040519150601f19603f3d011682016040523d82523d5f602084013e6124c3565b6001600160a01b038281165f81815260208190526040808220905163e6248d5560e01b815260048101939093529290917f00000000000000000000000000000000000000000000000000000000000000009091169063e6248d5590602401602060405180830381865afa1580156125a9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125cd9190613326565b815260208082019290925260409081015f9081206001600160a01b038516825290925290205460ff1661205e576040516367ee2b0160e11b815260040160405180910390fd5b5f825f1904841183021582026126305763ad251c275f526004601cfd5b50910281810615159190040190565b5f816001600160a01b0316836001600160a01b031603612661575060016103a3565b61266a83612763565b801561267a575061267a82612763565b15612687575060016103a3565b505f92915050565b5f670de0b6b3a76400008260800151106126cd5781608001516040516319b3b4a760e01b81526004016126c491815260200190565b60405180910390fd5b6126d7838361283b565b90505f6126e3846129dd565b90505f6126f882855f01518660200151612a3e565b90505f61270a83866040015186612a3e565b90508181111561271c575050506103a3565b5f61273961272a8385613351565b670de0b6b3a764000085612613565b905085608001518111156116b4576040516319b3b4a760e01b8152600481018290526024016126c4565b5f6001600160a01b03821615806103a35750506001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1490565b816014528060345263095ea7b360601b5f5260205f604460105f875af13d1560015f51141716611e9957633e3f8f735f526004601cfd5b5f825f1904841183021582026127ec5763ad251c275f526004601cfd5b5091020490565b60606127ff8383612ba1565b815115801561281657506001600160a01b0384163b155b15612834576040516314859aeb60e21b815260040160405180910390fd5b5092915050565b604081015181515f919061284f818361263f565b1561286d57604051636991e51560e11b815260040160405180910390fd5b6060840151604051631d4686fd60e31b81526001600160a01b0391821660048201525f9187169063ea3437e890602401602060405180830381865afa1580156128b8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128dc919061330b565b90506001600160a01b03811661290557604051637409771560e11b815260040160405180910390fd5b60405163383d5bf360e11b81526001600160a01b0382169063707ab7e6906129339088903090600401613658565b5f604051808303815f87803b15801561294a575f5ffd5b505af115801561295c573d5f5f3e3d5ffd5b505050506129738286606001518760200151611e45565b5f61297d84611ea2565b90505f61298984612763565b612993575f612999565b86602001515b90506129ae87606001518860a0015183612bcf565b506129bd848860600151611fcf565b816129c786611ea2565b6129d19190613351565b98975050505050505050565b5f816001600160a01b031663565d878c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a1a573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a3919061330b565b5f6001600160a01b038316612a655773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92505b604051635ae6916360e01b81526001600160a01b03848116600483015260016024830181905260448301525f918291871690635ae69163906064016040805180830381865afa158015612aba573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ade9190613681565b915091505f8114612b0d576040516383a1fb8b60e01b81526001600160a01b03861660048201526024016126c4565b612b978285612b1b88612763565b612b8457876001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b5b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b7f91906136a3565b612b87565b60125b612b9290600a6137a6565b6127cf565b9695505050505050565b8161205e5780515f03612bc7576040516314859aeb60e21b815260040160405180910390fd5b805181602001fd5b606081471015612bf25760405163595909b560e11b815260040160405180910390fd5b5f5f856001600160a01b03168486604051612c0d9190613642565b5f6040518083038185875af1925050503d805f8114612c47576040519150601f19603f3d011682016040523d82523d5f602084013e612c4c565b606091505b5091509150612b978683836127f3565b5f60208284031215612c6c575f5ffd5b81356001600160e01b031981168114612c83575f5ffd5b9392505050565b6001600160a01b0381168114612c9e575f5ffd5b50565b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b0381118282101715612cd757612cd7612ca1565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612d0557612d05612ca1565b604052919050565b8035612d1881612c8a565b919050565b5f82601f830112612d2c575f5ffd5b81356001600160401b03811115612d4557612d45612ca1565b612d58601f8201601f1916602001612cdd565b818152846020838601011115612d6c575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f60c08284031215612d98575f5ffd5b612da0612cb5565b90508135612dad81612c8a565b8152602082810135908201526040820135612dc781612c8a565b60408201526060820135612dda81612c8a565b60608201526080828101359082015260a08201356001600160401b03811115612e01575f5ffd5b612e0d84828501612d1d565b60a08301525092915050565b5f82601f830112612e28575f5ffd5b81356001600160401b03811115612e4157612e41612ca1565b8060051b612e5160208201612cdd565b91825260208185018101929081019086841115612e6c575f5ffd5b6020860192505b83831015612b975782356001600160401b03811115612e90575f5ffd5b612e9f886020838a0101612d88565b83525060209283019290910190612e73565b5f60c08284031215612ec1575f5ffd5b612ec9612cb5565b9050612ed482612d0d565b815260208281013590820152612eec60408301612d0d565b60408201526060828101359082015260808201356001600160401b03811115612f13575f5ffd5b612f1f84828501612e19565b60808301525060a08201356001600160401b03811115612e01575f5ffd5b5f5f5f5f60808587031215612f50575f5ffd5b8435612f5b81612c8a565b9350602085013592506040850135612f7281612c8a565b915060608501356001600160401b03811115612f8c575f5ffd5b612f9887828801612eb1565b91505092959194509250565b5f5f60408385031215612fb5575f5ffd5b8235612fc081612c8a565b91506020830135612fd081612c8a565b809150509250929050565b5f60c08284031215612feb575f5ffd5b612ff3612cb5565b9050612ffe82612d0d565b81526020828101359082015261301660408301612d0d565b60408201526060828101359082015260808201356001600160401b0381111561303d575f5ffd5b612f1f84828501612d88565b5f5f5f5f6080858703121561305c575f5ffd5b843561306781612c8a565b935060208501359250604085013561307e81612c8a565b915060608501356001600160401b03811115613098575f5ffd5b612f9887828801612fdb565b5f60c082840312156130b4575f5ffd5b50919050565b5f5f604083850312156130cb575f5ffd5b82356001600160401b038111156130e0575f5ffd5b6130ec858286016130a4565b95602094909401359450505050565b5f5f5f6060848603121561310d575f5ffd5b8335925060208401356001600160401b03811115613129575f5ffd5b613135868287016130a4565b93969395505050506040919091013590565b5f60208284031215613157575f5ffd5b8135612c8381612c8a565b8015158114612c9e575f5ffd5b5f5f60408385031215613180575f5ffd5b823561318b81612c8a565b91506020830135612fd081613162565b5f5f602083850312156131ac575f5ffd5b82356001600160401b038111156131c1575f5ffd5b8301601f810185136131d1575f5ffd5b80356001600160401b038111156131e6575f5ffd5b8560208260051b84010111156131fa575f5ffd5b6020919091019590945092505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561328f57603f1987860301845261327a85835161320a565b9450602093840193919091019060010161325e565b50929695505050505050565b5f5f5f606084860312156132ad575f5ffd5b83356001600160401b038111156132c2575f5ffd5b6132ce868287016130a4565b93505060208401356132df81612c8a565b929592945050506040919091013590565b5f60208284031215613300575f5ffd5b8151612c8381613162565b5f6020828403121561331b575f5ffd5b8151612c8381612c8a565b5f60208284031215613336575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156103a3576103a361333d565b634e487b7160e01b5f52603260045260245ffd5b5f5f5f6060848603121561338a575f5ffd5b5050815160208301516040909301519094929350919050565b5f6103a33683612eb1565b5f6103a33683612fdb565b5f8235605e198336030181126133cd575f5ffd5b9190910192915050565b5f606082360312156133e7575f5ffd5b604051606081016001600160401b038111828210171561340957613409612ca1565b604052823561341781612c8a565b8152602083013561342781613162565b602082015260408301356001600160401b03811115613444575f5ffd5b61345036828601612d1d565b60408301525092915050565b6001600160a01b038481168252831660208201526060604082018190525f906124d39083018461320a565b80516001600160a01b03908116835260208083015190840152604080830151821690840152606080830151909116908301526080808201519083015260a08181015160c09184018290525f916123319085018261320a565b83815260018060a01b0383166020820152606060408201525f610120820160018060a01b0384511660608401526020840151608084015260018060a01b0360408501511660a0840152606084015160c0840152608084015160c060e0850152818151808452610140860191506101408160051b87010193506020830192505f5b818110156135915761013f1987860301835261357c858551613487565b9450602093840193929092019160010161355f565b5050505060a0840151838203605f19016101008501526135b1828261320a565b979650505050505050565b83815260018060a01b03831660208201526060604082015260018060a01b0382511660608201526020820151608082015260018060a01b0360408301511660a0820152606082015160c08201525f608083015160c060e0840152613624610120840182613487565b905060a0840151605f19848303016101008501526135b1828261320a565b5f82518060208501845e5f920191825250919050565b604081525f61366a6040830185613487565b905060018060a01b03831660208301529392505050565b5f5f60408385031215613692575f5ffd5b505080516020909101519092909150565b5f602082840312156136b3575f5ffd5b815160ff81168114612c83575f5ffd5b6001815b60018411156136fe578085048111156136e2576136e261333d565b60018416156136f057908102905b60019390931c9280026136c7565b935093915050565b5f82613714575060016103a3565b8161372057505f6103a3565b816001811461373657600281146137405761375c565b60019150506103a3565b60ff8411156137515761375161333d565b50506001821b6103a3565b5060208310610133831016604e8410600b841016171561377f575081810a6103a3565b61378b5f1984846136c3565b805f190482111561379e5761379e61333d565b029392505050565b5f612c8360ff84168361370656fea2646970667358221220957e331cc7d75b32c1b8a66ec9908bf2691ab50e24496acf8a1fa36373811b6c64736f6c634300081c00330000000000000000000000001310f352f1389969ece6741671c4b919523912ff000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c9440000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a
Deployed Bytecode
0x6080604052600436106100f2575f3560e01c80639616756e11610087578063e8bbf5d711610057578063e8bbf5d7146102d6578063eb6d3a1114610302578063ebf1965314610335578063fe391e8c14610354575f5ffd5b80639616756e1461024c578063abaa0bbf1461026b578063c3c854b61461028a578063e6248d55146102a9575f5ffd5b806363e6a0e4116100c257806363e6a0e4146101bc5780637f848328146101db57806387c88173146101fa5780638f73dcfa14610219575f5ffd5b806301ffc9a7146100fd57806341ed2c12146101315780634e908d061461017c5780635fec5d0b1461019d575f5ffd5b366100f957005b5f5ffd5b348015610108575f5ffd5b5061011c610117366004612c5c565b610373565b60405190151581526020015b60405180910390f35b34801561013c575f5ffd5b506101647f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c94481565b6040516001600160a01b039091168152602001610128565b348015610187575f5ffd5b5061019b610196366004612f3d565b6103a9565b005b3480156101a8575f5ffd5b5061011c6101b7366004612fa4565b6107d7565b3480156101c7575f5ffd5b5061019b6101d6366004613049565b6108a7565b3480156101e6575f5ffd5b5061019b6101f53660046130ba565b610bde565b348015610205575f5ffd5b5061019b6102143660046130fb565b610dba565b348015610224575f5ffd5b506101647f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff81565b348015610257575f5ffd5b5061011c610266366004613147565b61109e565b348015610276575f5ffd5b5061019b6102853660046130ba565b61112a565b348015610295575f5ffd5b5061019b6102a436600461316f565b611203565b3480156102b4575f5ffd5b506102c86102c3366004613147565b6113d0565b604051908152602001610128565b3480156102e1575f5ffd5b506102f56102f036600461319b565b61145c565b6040516101289190613238565b34801561030d575f5ffd5b506101647f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a81565b348015610340575f5ffd5b5061019b61034f36600461329b565b6116be565b34801561035f575f5ffd5b5061019b61036e36600461329b565b6118a6565b5f6001600160e01b031982166316bb16f160e11b14806103a357506301ffc9a760e01b6001600160e01b03198316145b92915050565b6040818101519051637bca031760e11b81526001600160a01b0380831660048301527f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c944169063f794062e90602401602060405180830381865afa158015610412573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061043691906132f0565b6104535760405163792b839760e11b815260040160405180910390fd5b5f856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610490573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104b4919061330b565b90506104ca8686855f0151866020015185611990565b60208401526104d883611c48565b5f826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610515573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610539919061330b565b6040516370a0823160e01b81523060048201529091505f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610580573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105a49190613326565b60608601519091505f819003610620576040516357d159d560e01b81526001600160a01b0388811660048301528616906357d159d5906024016020604051808303815f875af11580156105f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061061d9190613326565b90505b81811115610641576040516329efdcc960e11b815260040160405180910390fd5b5f61064c8284613351565b9050610659848784611e45565b604051632796469160e21b8152600481018390526001600160a01b038981166024830152871690639e591a44906044015f604051808303815f87803b1580156106a0575f5ffd5b505af11580156106b2573d5f5f3e3d5ffd5b505050505f8111156106c9576106c9848983611e62565b6040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa15801561070b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072f9190613326565b9050801561074257610742858983611e62565b60808701515180156107c0575f5b818110156107be576107828960800151828151811061077157610771613364565b602002602001015160400151611ea2565b925082156107b6576107b6896080015182815181106107a3576107a3613364565b6020026020010151604001518b85611f22565b600101610750565b505b6107ca8588611fcf565b5050505050505050505050565b6001600160a01b038281165f81815260208190526040808220905163e6248d5560e01b815260048101939093529092909183917f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff169063e6248d5590602401602060405180830381865afa158015610851573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108759190613326565b815260208082019290925260409081015f9081206001600160a01b039095168152939091529091205460ff1692915050565b6040818101519051637bca031760e11b81526001600160a01b0380831660048301527f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c944169063f794062e90602401602060405180830381865afa158015610910573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061093491906132f0565b6109515760405163792b839760e11b815260040160405180910390fd5b5f856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109b2919061330b565b90506109c88686855f0151866020015185611990565b8360200181815250505f826001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a0e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a32919061330b565b9050610a3e8486612062565b6040516370a0823160e01b81523060048201525f906001600160a01b038316906370a0823190602401602060405180830381865afa158015610a82573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aa69190613326565b9050610ab3828583611e45565b604051632f4a61d960e01b8152600481018290526001600160a01b0387811660248301525f9190861690632f4a61d9906044016020604051808303815f875af1158015610b02573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b269190613326565b90508560600151811015610b4d576040516375633b0560e11b815260040160405180910390fd5b6040516370a0823160e01b81523060048201525f906001600160a01b038616906370a0823190602401602060405180830381865afa158015610b91573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bb59190613326565b90508015610bc857610bc8858983611e62565b610bd28487611fcf565b50505050505050505050565b688000000000ab143c065c15610bfb5763ab143c065f526004601cfd5b30688000000000ab143c065d6040516397a5d5b560e01b815233600482018190529082905f9081906001600160a01b037f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c94416906397a5d5b5906024016060604051808303815f875af1158015610c73573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c979190613378565b92505091505f8183610ca99190613351565b9050610cbd610cb7886133a3565b3361221d565b6040516397a5d5b560e01b81526001600160a01b0386811660048301525f9182917f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c94416906397a5d5b5906024016060604051808303815f875af1158015610d26573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d4a9190613378565b92505091505f8183610d5c9190613351565b905080841115610da257610d798488670de0b6b3a7640000612325565b610d838286613351565b1115610da2576040516375633b0560e11b815260040160405180910390fd5b50505050505050505f688000000000ab143c065d5050565b688000000000ab143c065c15610dd75763ab143c065f526004601cfd5b30688000000000ab143c065d82610df46060840160408501613147565b5f816001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e31573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e55919061330b565b9050610e6381333086612339565b610e6e818385611e45565b604051632f4a61d960e01b8152600481018490523360248201526001600160a01b03831690632f4a61d9906044016020604051808303815f875af1158015610eb8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610edc9190613326565b50610ee78183611fcf565b6040516397a5d5b560e01b815233600482018190529085905f9081906001600160a01b037f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c94416906397a5d5b5906024016060604051808303815f875af1158015610f53573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f779190613378565b92505091505f8183610f899190613351565b9050610f9d610f978b6133ae565b33612388565b6040516397a5d5b560e01b81526001600160a01b0386811660048301525f9182917f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c94416906397a5d5b5906024016060604051808303815f875af1158015611006573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061102a9190613378565b92505091505f818361103c9190613351565b905080841115611082576110598488670de0b6b3a7640000612325565b6110638286613351565b1115611082576040516375633b0560e11b815260040160405180910390fd5b50505050505050505050505f688000000000ab143c065d505050565b604051634b0b3ab760e11b81526001600160a01b0382811660048301525f917f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff90911690639616756e90602401602060405180830381865afa158015611106573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a391906132f0565b688000000000ab143c065c156111475763ab143c065f526004601cfd5b30688000000000ab143c065d6040516397a5d5b560e01b815233600482018190529082905f9081906001600160a01b037f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c94416906397a5d5b5906024016060604051808303815f875af11580156111bf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111e39190613378565b92505091505f81836111f59190613351565b9050610cbd610f97886133ae565b336001600160a01b0383160361122c57604051636eef2f3f60e11b815260040160405180910390fd5b604051634b0b3ab760e11b81523360048201527f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff6001600160a01b031690639616756e90602401602060405180830381865afa15801561128e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112b291906132f0565b156112d0576040516302d5da9f60e01b815260040160405180910390fd5b60405163e6248d5560e01b81523360048201525f907f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff6001600160a01b03169063e6248d5590602401602060405180830381865afa158015611334573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113589190613326565b335f8181526020818152604080832085845282528083206001600160a01b03891680855290835292819020805460ff191688151590811790915581518681529283015293945090927ffeeb3502e62327bd3fece59983b972dc941e6abedd652971aac3adea23cf7e17910160405180910390a3505050565b60405163e6248d5560e01b81526001600160a01b0382811660048301525f917f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff9091169063e6248d5590602401602060405180830381865afa158015611438573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a39190613326565b60607f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff82806001600160401b0381111561149857611498612ca1565b6040519080825280602002602001820160405280156114cb57816020015b60608152602001906001900390816114b65790505b5060408051606080820183525f80835260208301819052928201529194505b828110156116b45786868281811061150457611504613364565b905060200281019061151691906133b9565b61151f906133d7565b915081602001511561165657815160405163191d0cc560e11b81526001600160a01b0391821660048201525f9186169063323a198a90602401602060405180830381865afa158015611573573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611597919061330b565b90506001600160a01b0381166115c057604051632f3285fb60e21b815260040160405180910390fd5b8251604080850151905163bd0226d760e01b81526001600160a01b0384169263bd0226d7926115f5923392919060040161345c565b5f604051808303815f87803b15801561160c575f5ffd5b505af115801561161e573d5f5f3e3d5ffd5b50505050611633835f01518460400151612467565b86838151811061164557611645613364565b6020026020010181905250506116ac565b81516001600160a01b0316301461168057604051637720ccd960e01b815260040160405180910390fd5b61168e3083604001516124dc565b8582815181106116a0576116a0613364565b60200260200101819052505b6001016114ea565b5050505092915050565b688000000000ab143c065c156116db5763ab143c065f526004601cfd5b30688000000000ab143c065d6040516397a5d5b560e01b81526001600160a01b038084166004830152839183915f9182917f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c94416906397a5d5b5906024016060604051808303815f875af1158015611754573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117789190613378565b92505091505f818361178a9190613351565b90506117968733612530565b6117a86117a2896133a3565b8861221d565b6040516397a5d5b560e01b81526001600160a01b0386811660048301525f9182917f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c94416906397a5d5b5906024016060604051808303815f875af1158015611811573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118359190613378565b92505091505f81836118479190613351565b90508084111561188d576118648488670de0b6b3a7640000612325565b61186e8286613351565b111561188d576040516375633b0560e11b815260040160405180910390fd5b50505050505050505f688000000000ab143c065d505050565b688000000000ab143c065c156118c35763ab143c065f526004601cfd5b30688000000000ab143c065d6040516397a5d5b560e01b81526001600160a01b038084166004830152839183915f9182917f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c94416906397a5d5b5906024016060604051808303815f875af115801561193c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119609190613378565b92505091505f81836119729190613351565b905061197e8733612530565b6117a861198a896133ae565b88612388565b5f336001600160a01b038716141580611a2e5750604051637bca031760e11b81526001600160a01b0387811660048301527f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c944169063f794062e90602401602060405180830381865afa158015611a08573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a2c91906132f0565b155b15611a4c5760405163792b839760e11b815260040160405180910390fd5b6040516370a0823160e01b815230600482015285906001600160a01b038416906370a0823190602401602060405180830381865afa158015611a90573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ab49190613326565b1015611ad3576040516307d198f760e11b815260040160405180910390fd5b836001600160a01b0316866001600160a01b0316141580611af45750828514155b15611b12576040516307c426b560e21b815260040160405180910390fd5b5f611b9f847f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff6001600160a01b031663fe5764846040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b73573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b979190613326565b612710612613565b90508015611c3d57611bb18185613351565b9350611c3d837f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff6001600160a01b0316632131c68c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c13573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c37919061330b565b83611e62565b509195945050505050565b5f815f01516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c88573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cac919061330b565b90505f82604001516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cef573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d13919061330b565b9050611d1f818361263f565b15611d3d576040516307c426b560e21b815260040160405180910390fd5b826080015151600114611d63576040516307c426b560e21b815260040160405180910390fd5b5f83608001515f81518110611d7a57611d7a613364565b602002602001015190508060a00151515f1480611da2575060608101516001600160a01b0316155b80611dc25750826001600160a01b0316815f01516001600160a01b031614155b80611de35750816001600160a01b031681604001516001600160a01b031614155b80611df657508360200151816020015114155b15611e14576040516307c426b560e21b815260040160405180910390fd5b611e3e7f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff8261268f565b5050505050565b611e4e83612763565b611e5d57611e5d838383612798565b505050565b816014528060345263a9059cbb60601b5f5260205f604460105f875af13d1560015f51141716611e99576390b8ec185f526004601cfd5b5f603452505050565b5f611eac82612763565b611f1b576040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611ef2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f169190613326565b6103a3565b4792915050565b611f2b83612763565b15611fc4577f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a6001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b158015611f89575f5ffd5b505af1158015611f9b573d5f5f3e3d5ffd5b50505050507f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a92505b611e5d838383611e62565b611fd882612763565b61205e57604051636eb1769f60e11b81523060048201526001600160a01b0382811660248301525f919084169063dd62ed3e90604401602060405180830381865afa158015612029573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061204d9190613326565b111561205e5761205e82825f612798565b5050565b5f825f01516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120a2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120c6919061330b565b90505f83604001516001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612109573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061212d919061330b565b9050612139828261263f565b15612157576040516307c426b560e21b815260040160405180910390fd5b608084015160a0810151511580612179575060608101516001600160a01b0316155b806121995750826001600160a01b0316815f01516001600160a01b031614155b806121ba5750816001600160a01b031681604001516001600160a01b031614155b806121cd57508460200151816020015114155b156121eb576040516307c426b560e21b815260040160405180910390fd5b6122157f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff8261268f565b505050505050565b8151604051637bca031760e11b81526001600160a01b0391821660048201527f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c9449091169063f794062e90602401602060405180830381865afa158015612285573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122a991906132f0565b6122c65760405163792b839760e11b815260040160405180910390fd5b8151602083015160405163bdca672360e01b81526001600160a01b039092169163bdca6723916122fc91859087906004016134df565b5f604051808303815f87803b158015612313575f5ffd5b505af1158015612215573d5f5f3e3d5ffd5b5f6123318484846127cf565b949350505050565b60405181606052826040528360601b602c526323b872dd60601b600c5260205f6064601c5f895af13d1560015f5114171661237b57637939f4245f526004601cfd5b5f60605260405250505050565b8151604051637bca031760e11b81526001600160a01b0391821660048201527f000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c9449091169063f794062e90602401602060405180830381865afa1580156123f0573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061241491906132f0565b6124315760405163792b839760e11b815260040160405180910390fd5b8151602083015160405163010b626160e71b81526001600160a01b03909216916385b13080916122fc91859087906004016135bc565b60605f5f846001600160a01b03165f856040516124849190613642565b5f6040518083038185875af1925050503d805f81146124be576040519150601f19603f3d011682016040523d82523d5f602084013e6124c3565b606091505b50915091506124d38583836127f3565b95945050505050565b60605f5f846001600160a01b0316846040516124f89190613642565b5f60405180830381855af49150503d805f81146124be576040519150601f19603f3d011682016040523d82523d5f602084013e6124c3565b6001600160a01b038281165f81815260208190526040808220905163e6248d5560e01b815260048101939093529290917f0000000000000000000000001310f352f1389969ece6741671c4b919523912ff9091169063e6248d5590602401602060405180830381865afa1580156125a9573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125cd9190613326565b815260208082019290925260409081015f9081206001600160a01b038516825290925290205460ff1661205e576040516367ee2b0160e11b815260040160405180910390fd5b5f825f1904841183021582026126305763ad251c275f526004601cfd5b50910281810615159190040190565b5f816001600160a01b0316836001600160a01b031603612661575060016103a3565b61266a83612763565b801561267a575061267a82612763565b15612687575060016103a3565b505f92915050565b5f670de0b6b3a76400008260800151106126cd5781608001516040516319b3b4a760e01b81526004016126c491815260200190565b60405180910390fd5b6126d7838361283b565b90505f6126e3846129dd565b90505f6126f882855f01518660200151612a3e565b90505f61270a83866040015186612a3e565b90508181111561271c575050506103a3565b5f61273961272a8385613351565b670de0b6b3a764000085612613565b905085608001518111156116b4576040516319b3b4a760e01b8152600481018290526024016126c4565b5f6001600160a01b03821615806103a35750506001600160a01b031673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1490565b816014528060345263095ea7b360601b5f5260205f604460105f875af13d1560015f51141716611e9957633e3f8f735f526004601cfd5b5f825f1904841183021582026127ec5763ad251c275f526004601cfd5b5091020490565b60606127ff8383612ba1565b815115801561281657506001600160a01b0384163b155b15612834576040516314859aeb60e21b815260040160405180910390fd5b5092915050565b604081015181515f919061284f818361263f565b1561286d57604051636991e51560e11b815260040160405180910390fd5b6060840151604051631d4686fd60e31b81526001600160a01b0391821660048201525f9187169063ea3437e890602401602060405180830381865afa1580156128b8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128dc919061330b565b90506001600160a01b03811661290557604051637409771560e11b815260040160405180910390fd5b60405163383d5bf360e11b81526001600160a01b0382169063707ab7e6906129339088903090600401613658565b5f604051808303815f87803b15801561294a575f5ffd5b505af115801561295c573d5f5f3e3d5ffd5b505050506129738286606001518760200151611e45565b5f61297d84611ea2565b90505f61298984612763565b612993575f612999565b86602001515b90506129ae87606001518860a0015183612bcf565b506129bd848860600151611fcf565b816129c786611ea2565b6129d19190613351565b98975050505050505050565b5f816001600160a01b031663565d878c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a1a573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a3919061330b565b5f6001600160a01b038316612a655773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee92505b604051635ae6916360e01b81526001600160a01b03848116600483015260016024830181905260448301525f918291871690635ae69163906064016040805180830381865afa158015612aba573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ade9190613681565b915091505f8114612b0d576040516383a1fb8b60e01b81526001600160a01b03861660048201526024016126c4565b612b978285612b1b88612763565b612b8457876001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b5b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b7f91906136a3565b612b87565b60125b612b9290600a6137a6565b6127cf565b9695505050505050565b8161205e5780515f03612bc7576040516314859aeb60e21b815260040160405180910390fd5b805181602001fd5b606081471015612bf25760405163595909b560e11b815260040160405180910390fd5b5f5f856001600160a01b03168486604051612c0d9190613642565b5f6040518083038185875af1925050503d805f8114612c47576040519150601f19603f3d011682016040523d82523d5f602084013e612c4c565b606091505b5091509150612b978683836127f3565b5f60208284031215612c6c575f5ffd5b81356001600160e01b031981168114612c83575f5ffd5b9392505050565b6001600160a01b0381168114612c9e575f5ffd5b50565b634e487b7160e01b5f52604160045260245ffd5b60405160c081016001600160401b0381118282101715612cd757612cd7612ca1565b60405290565b604051601f8201601f191681016001600160401b0381118282101715612d0557612d05612ca1565b604052919050565b8035612d1881612c8a565b919050565b5f82601f830112612d2c575f5ffd5b81356001600160401b03811115612d4557612d45612ca1565b612d58601f8201601f1916602001612cdd565b818152846020838601011115612d6c575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f60c08284031215612d98575f5ffd5b612da0612cb5565b90508135612dad81612c8a565b8152602082810135908201526040820135612dc781612c8a565b60408201526060820135612dda81612c8a565b60608201526080828101359082015260a08201356001600160401b03811115612e01575f5ffd5b612e0d84828501612d1d565b60a08301525092915050565b5f82601f830112612e28575f5ffd5b81356001600160401b03811115612e4157612e41612ca1565b8060051b612e5160208201612cdd565b91825260208185018101929081019086841115612e6c575f5ffd5b6020860192505b83831015612b975782356001600160401b03811115612e90575f5ffd5b612e9f886020838a0101612d88565b83525060209283019290910190612e73565b5f60c08284031215612ec1575f5ffd5b612ec9612cb5565b9050612ed482612d0d565b815260208281013590820152612eec60408301612d0d565b60408201526060828101359082015260808201356001600160401b03811115612f13575f5ffd5b612f1f84828501612e19565b60808301525060a08201356001600160401b03811115612e01575f5ffd5b5f5f5f5f60808587031215612f50575f5ffd5b8435612f5b81612c8a565b9350602085013592506040850135612f7281612c8a565b915060608501356001600160401b03811115612f8c575f5ffd5b612f9887828801612eb1565b91505092959194509250565b5f5f60408385031215612fb5575f5ffd5b8235612fc081612c8a565b91506020830135612fd081612c8a565b809150509250929050565b5f60c08284031215612feb575f5ffd5b612ff3612cb5565b9050612ffe82612d0d565b81526020828101359082015261301660408301612d0d565b60408201526060828101359082015260808201356001600160401b0381111561303d575f5ffd5b612f1f84828501612d88565b5f5f5f5f6080858703121561305c575f5ffd5b843561306781612c8a565b935060208501359250604085013561307e81612c8a565b915060608501356001600160401b03811115613098575f5ffd5b612f9887828801612fdb565b5f60c082840312156130b4575f5ffd5b50919050565b5f5f604083850312156130cb575f5ffd5b82356001600160401b038111156130e0575f5ffd5b6130ec858286016130a4565b95602094909401359450505050565b5f5f5f6060848603121561310d575f5ffd5b8335925060208401356001600160401b03811115613129575f5ffd5b613135868287016130a4565b93969395505050506040919091013590565b5f60208284031215613157575f5ffd5b8135612c8381612c8a565b8015158114612c9e575f5ffd5b5f5f60408385031215613180575f5ffd5b823561318b81612c8a565b91506020830135612fd081613162565b5f5f602083850312156131ac575f5ffd5b82356001600160401b038111156131c1575f5ffd5b8301601f810185136131d1575f5ffd5b80356001600160401b038111156131e6575f5ffd5b8560208260051b84010111156131fa575f5ffd5b6020919091019590945092505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561328f57603f1987860301845261327a85835161320a565b9450602093840193919091019060010161325e565b50929695505050505050565b5f5f5f606084860312156132ad575f5ffd5b83356001600160401b038111156132c2575f5ffd5b6132ce868287016130a4565b93505060208401356132df81612c8a565b929592945050506040919091013590565b5f60208284031215613300575f5ffd5b8151612c8381613162565b5f6020828403121561331b575f5ffd5b8151612c8381612c8a565b5f60208284031215613336575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156103a3576103a361333d565b634e487b7160e01b5f52603260045260245ffd5b5f5f5f6060848603121561338a575f5ffd5b5050815160208301516040909301519094929350919050565b5f6103a33683612eb1565b5f6103a33683612fdb565b5f8235605e198336030181126133cd575f5ffd5b9190910192915050565b5f606082360312156133e7575f5ffd5b604051606081016001600160401b038111828210171561340957613409612ca1565b604052823561341781612c8a565b8152602083013561342781613162565b602082015260408301356001600160401b03811115613444575f5ffd5b61345036828601612d1d565b60408301525092915050565b6001600160a01b038481168252831660208201526060604082018190525f906124d39083018461320a565b80516001600160a01b03908116835260208083015190840152604080830151821690840152606080830151909116908301526080808201519083015260a08181015160c09184018290525f916123319085018261320a565b83815260018060a01b0383166020820152606060408201525f610120820160018060a01b0384511660608401526020840151608084015260018060a01b0360408501511660a0840152606084015160c0840152608084015160c060e0850152818151808452610140860191506101408160051b87010193506020830192505f5b818110156135915761013f1987860301835261357c858551613487565b9450602093840193929092019160010161355f565b5050505060a0840151838203605f19016101008501526135b1828261320a565b979650505050505050565b83815260018060a01b03831660208201526060604082015260018060a01b0382511660608201526020820151608082015260018060a01b0360408301511660a0820152606082015160c08201525f608083015160c060e0840152613624610120840182613487565b905060a0840151605f19848303016101008501526135b1828261320a565b5f82518060208501845e5f920191825250919050565b604081525f61366a6040830185613487565b905060018060a01b03831660208301529392505050565b5f5f60408385031215613692575f5ffd5b505080516020909101519092909150565b5f602082840312156136b3575f5ffd5b815160ff81168114612c83575f5ffd5b6001815b60018411156136fe578085048111156136e2576136e261333d565b60018416156136f057908102905b60019390931c9280026136c7565b935093915050565b5f82613714575060016103a3565b8161372057505f6103a3565b816001811461373657600281146137405761375c565b60019150506103a3565b60ff8411156137515761375161333d565b50506001821b6103a3565b5060208310610133831016604e8410600b841016171561377f575081810a6103a3565b61378b5f1984846136c3565b805f190482111561379e5761379e61333d565b029392505050565b5f612c8360ff84168361370656fea2646970667358221220957e331cc7d75b32c1b8a66ec9908bf2691ab50e24496acf8a1fa36373811b6c64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001310f352f1389969ece6741671c4b919523912ff000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c9440000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a
-----Decoded View---------------
Arg [0] : cr (address): 0x1310f352f1389969Ece6741671c4B919523912fF
Arg [1] : mm (address): 0x830D40CDFdc494BC1A2729a7381bfCe44326c944
Arg [2] : wNative (address): 0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000001310f352f1389969ece6741671c4b919523912ff
Arg [1] : 000000000000000000000000830d40cdfdc494bc1a2729a7381bfce44326c944
Arg [2] : 0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a
Deployed Bytecode Sourcemap
170058:5608:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;159872:236;;;;;;;;;;-1:-1:-1;159872:236:0;;;;;:::i;:::-;;:::i;:::-;;;470:14:1;;463:22;445:41;;433:2;418:18;159872:236:0;;;;;;;;138644:45;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;683:32:1;;;665:51;;653:2;638:18;138644:45:0;497:225:1;156623:3181:0;;;;;;;;;;-1:-1:-1;156623:3181:0;;;;;:::i;:::-;;:::i;:::-;;86868:223;;;;;;;;;;-1:-1:-1;86868:223:0;;;;;:::i;:::-;;:::i;152865:2215::-;;;;;;;;;;-1:-1:-1;152865:2215:0;;;;;:::i;:::-;;:::i;149284:244::-;;;;;;;;;;-1:-1:-1;149284:244:0;;;;;:::i;:::-;;:::i;143928:352::-;;;;;;;;;;-1:-1:-1;143928:352:0;;;;;:::i;:::-;;:::i;83510:49::-;;;;;;;;;;;;;;;87489:178;;;;;;;;;;-1:-1:-1;87489:178:0;;;;;:::i;:::-;;:::i;145544:236::-;;;;;;;;;;-1:-1:-1;145544:236:0;;;;;:::i;:::-;;:::i;85158:666::-;;;;;;;;;;-1:-1:-1;85158:666:0;;;;;:::i;:::-;;:::i;86206:163::-;;;;;;;;;;-1:-1:-1;86206:163:0;;;;;:::i;:::-;;:::i;:::-;;;10888:25:1;;;10876:2;10861:18;86206:163:0;10742:177:1;80918:1590:0;;;;;;;;;;-1:-1:-1;80918:1590:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;138527:38::-;;;;;;;;;;;;;;;151040:348;;;;;;;;;;-1:-1:-1;151040:348:0;;;;;:::i;:::-;;:::i;147360:340::-;;;;;;;;;;-1:-1:-1;147360:340:0;;;;;:::i;:::-;;:::i;159872:236::-;159965:11;-1:-1:-1;;;;;;159998:49:0;;-1:-1:-1;;;159998:49:0;;:102;;-1:-1:-1;;;;;;;;;;75629:40:0;;;160064:36;159989:111;159872:236;-1:-1:-1;;159872:236:0:o;156623:3181::-;156839:23;;;;;156880:49;;-1:-1:-1;;;156880:49:0;;-1:-1:-1;;;;;683:32:1;;;156880:49:0;;;665:51:1;156880:13:0;:22;;;;638:18:1;;156880:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;156875:125;;156953:35;;-1:-1:-1;;;156953:35:0;;;;;;;;;;;156875:125;157056:23;157090:6;-1:-1:-1;;;;;157082:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;157056:49;;157344:194;157385:6;157406:16;157445:6;:13;;;157474:6;:23;;;157512:15;157344:26;:194::i;:::-;157318:23;;;:220;157626:39;157318:6;157626:31;:39::i;:::-;157741:17;157761:16;-1:-1:-1;;;;;157761:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;157817:42;;-1:-1:-1;;;157817:42:0;;157853:4;157817:42;;;665:51:1;157741:44:0;;-1:-1:-1;157796:18:0;;-1:-1:-1;;;;;157817:27:0;;;;;638:18:1;;157817:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;157892:18;;;;157796:63;;-1:-1:-1;157870:19:0;157925:16;;;157921:204;;158071:42;;-1:-1:-1;;;158071:42:0;;-1:-1:-1;;;;;683:32:1;;;158071:42:0;;;665:51:1;158071:35:0;;;;;638:18:1;;158071:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;158057:56;;157921:204;158155:10;158141:11;:24;158137:117;;;158189:53;;-1:-1:-1;;;158189:53:0;;;;;;;;;;;158137:117;158264:17;158284:24;158297:11;158284:10;:24;:::i;:::-;158264:44;;158402:128;158444:9;158476:16;158508:11;158402:27;:128::i;:::-;158567:45;;-1:-1:-1;;;158567:45:0;;;;;15305:25:1;;;-1:-1:-1;;;;;15366:32:1;;;15346:18;;;15339:60;158567:25:0;;;;;15278:18:1;;158567:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;158704:1;158692:9;:13;158688:103;;;158722:57;158751:9;158762:5;158769:9;158722:28;:57::i;:::-;158815:48;;-1:-1:-1;;;158815:48:0;;158857:4;158815:48;;;665:51:1;-1:-1:-1;;;;;158815:33:0;;;;;638:18:1;;158815:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;158803:60;-1:-1:-1;158951:13:0;;158947:109;;158981:63;159010:15;159027:5;159034:9;158981:28;:63::i;:::-;159146:18;;;;:25;159186:12;;159182:453;;159220:9;159215:409;159235:8;159231:1;:12;159215:409;;;159302:55;159323:6;:18;;;159342:1;159323:21;;;;;;;;:::i;:::-;;;;;;;:33;;;159302:20;:55::i;:::-;159269:88;-1:-1:-1;159380:13:0;;159376:233;;159418:171;159465:6;:18;;;159484:1;159465:21;;;;;;;;:::i;:::-;;;;;;;:33;;;159525:5;159557:9;159418:20;:171::i;:::-;159245:3;;159215:409;;;;159182:453;159687:109;159736:9;159768:16;159687:34;:109::i;:::-;156791:3013;;;;;;;156623:3181;;;;:::o;86868:223::-;-1:-1:-1;;;;;87001:17:0;;;86968:11;87001:17;;;;;;;;;;;87019:53;;-1:-1:-1;;;87019:53:0;;;;;665:51:1;;;;86968:11:0;;87001:17;;86968:11;;87019:15;:47;;;;638:18:1;;87019:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;87001:72;;;;;;;;;;;;;;-1:-1:-1;87001:72:0;;;-1:-1:-1;;;;;87001:82:0;;;;;;;;;;;;;;;;86868:223;-1:-1:-1;;86868:223:0:o;152865:2215::-;153065:13;;;;;153246:39;;-1:-1:-1;;;153246:39:0;;-1:-1:-1;;;;;683:32:1;;;153246:39:0;;;665:51:1;153246:13:0;:22;;;;638:18:1;;153246:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;153241:115;;153309:35;;-1:-1:-1;;;153309:35:0;;;;;;;;;;;153241:115;153406:17;153444:16;-1:-1:-1;;;;;153426:41:0;;:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;153406:63;;153704:200;153745:16;153776:12;153811:6;:23;;;153850:6;:19;;;153884:9;153704:26;:200::i;:::-;153682:6;:19;;:222;;;;;153982:23;154008:6;-1:-1:-1;;;;;154008:12:0;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;153982:40;;154102:46;154134:6;154142:5;154102:31;:46::i;:::-;154178:48;;-1:-1:-1;;;154178:48:0;;154220:4;154178:48;;;665:51:1;154161:14:0;;-1:-1:-1;;;;;154178:33:0;;;;;638:18:1;;154178:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154161:65;;154311:69;154339:15;154364:6;154373;154311:27;:69::i;:::-;154458:41;;-1:-1:-1;;;154458:41:0;;;;;15305:25:1;;;-1:-1:-1;;;;;15366:32:1;;;15346:18;;;15339:60;154441:14:0;;154458:26;;;;;;15278:18:1;;154458:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154441:58;;154600:6;:21;;;154591:6;:30;154587:108;;;154645:38;;-1:-1:-1;;;154645:38:0;;;;;;;;;;;154587:108;154727:42;;-1:-1:-1;;;154727:42:0;;154763:4;154727:42;;;665:51:1;154707:17:0;;-1:-1:-1;;;;;154727:27:0;;;;;638:18:1;;154727:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;154707:62;-1:-1:-1;154853:13:0;;154849:103;;154883:57;154912:9;154923:5;154930:9;154883:28;:57::i;:::-;155004:68;155039:15;155064:6;155004:34;:68::i;:::-;153037:2043;;;;;;152865:2215;;;;:::o;149284:244::-;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;140753:45:::1;::::0;-1:-1:-1;;;140753:45:0;;149417:10:::1;140753:45;::::0;::::1;665:51:1::0;;;149417:10:0;149429:8;;140703:24:::1;::::0;;;-1:-1:-1;;;;;140753:13:0::1;:36;::::0;::::1;::::0;638:18:1;;140753:45:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140702:96;;;;;140809:15;140846:10;140827:16;:29;;;;:::i;:::-;140809:47:::0;-1:-1:-1;149489:31:0::2;;149501:6:::0;149489:31:::2;:::i;:::-;149509:10;149489:11;:31::i;:::-;140932:45:::1;::::0;-1:-1:-1;;;140932:45:0;;-1:-1:-1;;;;;683:32:1;;;140932:45:0::1;::::0;::::1;665:51:1::0;140884:23:0::1;::::0;;;140932:13:::1;:36;::::0;::::1;::::0;638:18:1;;140932:45:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140883:94;;;;;140988:16;141025:9;141007:15;:27;;;;:::i;:::-;140988:46;;141137:8;141127:7;:18;141123:190;;;141189:31;141197:7;141206:8;636:4;141189:7;:31::i;:::-;141167:18;141177:8:::0;141167:7;:18:::1;:::i;:::-;141166:54;141162:140;;;141248:38;;-1:-1:-1::0;;;141248:38:0::1;;;;;;;;;;;141162:140;140691:629;;;;;;55209:1;;55320::::0;55296:22;55289:33;149284:244;;:::o;143928:352::-;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;144099:6;144116:13:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;139374:23;139400:6;-1:-1:-1::0;;;;;139400:12:0::1;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;139374:40;;139486:147;139533:15;139563:10;139596:4;139616:6;139486:32;:147::i;:::-;139695:69;139723:15;139748:6;139757;139695:27;:69::i;:::-;139853:46;::::0;-1:-1:-1;;;139853:46:0;;::::1;::::0;::::1;15305:25:1::0;;;139888:10:0::1;15346:18:1::0;;;15339:60;-1:-1:-1;;;;;139853:26:0;::::1;::::0;::::1;::::0;15278:18:1;;139853:46:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;139952:68;139987:15;140012:6;139952:34;:68::i;:::-;140753:45:::2;::::0;-1:-1:-1;;;140753:45:0;;144151:10:::2;140753:45;::::0;::::2;665:51:1::0;;;144151:10:0;144163:8;;140703:24:::2;::::0;;;-1:-1:-1;;;;;140753:13:0::2;:36;::::0;::::2;::::0;638:18:1;;140753:45:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140702:96;;;;;140809:15;140846:10;140827:16;:29;;;;:::i;:::-;140809:47:::0;-1:-1:-1;144243:29:0::3;;144253:6:::0;144243:29:::3;:::i;:::-;144261:10;144243:9;:29::i;:::-;140932:45:::2;::::0;-1:-1:-1;;;140932:45:0;;-1:-1:-1;;;;;683:32:1;;;140932:45:0::2;::::0;::::2;665:51:1::0;140884:23:0::2;::::0;;;140932:13:::2;:36;::::0;::::2;::::0;638:18:1;;140932:45:0::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140883:94;;;;;140988:16;141025:9;141007:15;:27;;;;:::i;:::-;140988:46;;141137:8;141127:7;:18;141123:190;;;141189:31;141197:7;141206:8;636:4;141189:7;:31::i;:::-;141167:18;141177:8:::0;141167:7;:18:::2;:::i;:::-;141166:54;141162:140;;;141248:38;;-1:-1:-1::0;;;141248:38:0::2;;;;;;;;;;;141162:140;140691:629;;;;;;140033:1;;139363:679:::1;55209:1;;55320::::0;55296:22;55289:33;143928:352;;;:::o;87489:178::-;87611:48;;-1:-1:-1;;;87611:48:0;;-1:-1:-1;;;;;683:32:1;;;87611:48:0;;;665:51:1;87578:11:0;;87611:15;:42;;;;;;638:18:1;;87611:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;145544:236::-;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;140753:45:::1;::::0;-1:-1:-1;;;140753:45:0;;145673:10:::1;140753:45;::::0;::::1;665:51:1::0;;;145673:10:0;145685:8;;140703:24:::1;::::0;;;-1:-1:-1;;;;;140753:13:0::1;:36;::::0;::::1;::::0;638:18:1;;140753:45:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140702:96;;;;;140809:15;140846:10;140827:16;:29;;;;:::i;:::-;140809:47:::0;-1:-1:-1;145743:29:0::2;;145753:6:::0;145743:29:::2;:::i;85158:666::-:0;85258:10;-1:-1:-1;;;;;85246:22:0;;;85242:96;;85292:34;;-1:-1:-1;;;85292:34:0;;;;;;;;;;;85242:96;85456:54;;-1:-1:-1;;;85456:54:0;;85499:10;85456:54;;;665:51:1;85456:15:0;-1:-1:-1;;;;;85456:42:0;;;;638:18:1;;85456:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;85452:131;;;85534:37;;-1:-1:-1;;;85534:37:0;;;;;;;;;;;85452:131;85618:45;;-1:-1:-1;;;85618:45:0;;85652:10;85618:45;;;665:51:1;85595:20:0;;85618:15;-1:-1:-1;;;;;85618:33:0;;;;638:18:1;;85618:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;85686:10;85674:11;:23;;;;;;;;;;;:37;;;;;;;;-1:-1:-1;;;;;85674:47:0;;;;;;;;;;;;:60;;-1:-1:-1;;85674:60:0;;;;;;;;;;85752:64;;16883:25:1;;;16924:18;;;16917:50;85674:37:0;;-1:-1:-1;85674:47:0;;85752:64;;16856:18:1;85752:64:0;;;;;;;85231:593;85158:666;;:::o;86206:163::-;86322:39;;-1:-1:-1;;;86322:39:0;;-1:-1:-1;;;;;683:32:1;;;86322:39:0;;;665:51:1;86286:14:0;;86322:15;:33;;;;;;638:18:1;;86322:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;80918:1590::-;81005:22;167387:15;81113:5;;-1:-1:-1;;;;;81146:21:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;81136:31:0;;-1:-1:-1;81224:1277:0;81244:8;81240:1;:12;81224:1277;;;81287:5;;81293:1;81287:8;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;81274:21;;;:::i;:::-;;;81328:10;:24;;;81324:810;;;81556:17;;81536:38;;-1:-1:-1;;;81536:38:0;;-1:-1:-1;;;;;683:32:1;;;81536:38:0;;;665:51:1;81518:15:0;;81536:19;;;;;638:18:1;;81536:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;81518:56;-1:-1:-1;;;;;;81665:21:0;;81661:105;;81718:28;;-1:-1:-1;;;81718:28:0;;;;;;;;;;;81661:105;81882:17;;81922:15;;;;;81786:170;;-1:-1:-1;;;81786:170:0;;-1:-1:-1;;;;;81786:40:0;;;;;:170;;81849:10;;81882:17;81922:15;81786:170;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81990:83;82038:10;:17;;;82057:10;:15;;;81990:47;:83::i;:::-;81977:7;81985:1;81977:10;;;;;;;;:::i;:::-;;;;;;:96;;;;82110:8;;;81324:810;82290:17;;-1:-1:-1;;;;;82273:34:0;82281:4;82273:34;82269:108;;82335:26;;-1:-1:-1;;;82335:26:0;;;;;;;;;;;82269:108;82406:83;82466:4;82473:10;:15;;;82406:51;:83::i;:::-;82393:7;82401:1;82393:10;;;;;;;;:::i;:::-;;;;;;:96;;;;81224:1277;81254:3;;81224:1277;;;;81029:1479;;;80918:1590;;;;:::o;151040:348::-;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;140753:45:::1;::::0;-1:-1:-1;;;140753:45:0;;-1:-1:-1;;;;;683:32:1;;;140753:45:0::1;::::0;::::1;665:51:1::0;151202:7:0;;151211:8;;140703:24:::1;::::0;;;140753:13:::1;:36;::::0;::::1;::::0;638:18:1;;140753:45:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140702:96;;;;;140809:15;140846:10;140827:16;:29;;;;:::i;:::-;140809:47;;151232:35:::2;151247:7;151256:10;151232:14;:35::i;:::-;151352:28;;151364:6:::0;151352:28:::2;:::i;:::-;151372:7;151352:11;:28::i;:::-;140932:45:::1;::::0;-1:-1:-1;;;140932:45:0;;-1:-1:-1;;;;;683:32:1;;;140932:45:0::1;::::0;::::1;665:51:1::0;140884:23:0::1;::::0;;;140932:13:::1;:36;::::0;::::1;::::0;638:18:1;;140932:45:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140883:94;;;;;140988:16;141025:9;141007:15;:27;;;;:::i;:::-;140988:46;;141137:8;141127:7;:18;141123:190;;;141189:31;141197:7;141206:8;636:4;141189:7;:31::i;:::-;141167:18;141177:8:::0;141167:7;:18:::1;:::i;:::-;141166:54;141162:140;;;141248:38;;-1:-1:-1::0;;;141248:38:0::1;;;;;;;;;;;141162:140;140691:629;;;;;;55209:1;;55320::::0;55296:22;55289:33;151040:348;;;:::o;147360:340::-;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;140753:45:::1;::::0;-1:-1:-1;;;140753:45:0;;-1:-1:-1;;;;;683:32:1;;;140753:45:0::1;::::0;::::1;665:51:1::0;147518:7:0;;147527:8;;140703:24:::1;::::0;;;140753:13:::1;:36;::::0;::::1;::::0;638:18:1;;140753:45:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;140702:96;;;;;140809:15;140846:10;140827:16;:29;;;;:::i;:::-;140809:47;;147548:35:::2;147563:7;147572:10;147548:14;:35::i;:::-;147666:26;;147676:6:::0;147666:26:::2;:::i;:::-;147684:7;147666:9;:26::i;161089:1608::-:0;161296:7;161457:10;-1:-1:-1;;;;;161457:20:0;;;;;:55;;-1:-1:-1;161482:30:0;;-1:-1:-1;;;161482:30:0;;-1:-1:-1;;;;;683:32:1;;;161482:30:0;;;665:51:1;161482:13:0;:22;;;;638:18:1;;161482:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;161481:31;161457:55;161453:130;;;161536:35;;-1:-1:-1;;;161536:35:0;;;;;;;;;;;161453:130;161698:49;;-1:-1:-1;;;161698:49:0;;161741:4;161698:49;;;665:51:1;161750:6:0;;-1:-1:-1;;;;;161698:34:0;;;;;638:18:1;;161698:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;161694:134;;;161780:36;;-1:-1:-1;;;161780:36:0;;;;;;;;;;;161694:134;161929:11;-1:-1:-1;;;;;161911:30:0;:6;-1:-1:-1;;;;;161911:30:0;;;:56;;;;161955:12;161945:6;:22;;161911:56;161907:131;;;161991:35;;-1:-1:-1;;;161991:35:0;;;;;;;;;;;161907:131;162120:11;162134:134;162175:12;162202:15;-1:-1:-1;;;;;162202:35:0;;:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;745:3;162134:26;:134::i;:::-;162120:148;-1:-1:-1;162334:7:0;;162330:221;;162358:19;162374:3;162358:19;;:::i;:::-;;;162392:147;162439:16;162474:15;-1:-1:-1;;;;;162474:26:0;;:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;162521:3;162392:28;:147::i;:::-;-1:-1:-1;162677:12:0;;161089:1608;-1:-1:-1;;;;;161089:1608:0:o;174326:1337::-;174452:23;174478:6;:13;;;-1:-1:-1;;;;;174478:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;174452:47;;174510:17;174530:6;:23;;;-1:-1:-1;;;;;174530:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;174510:51;;174769:54;174796:9;174807:15;174769:26;:54::i;:::-;174765:129;;;174847:35;;-1:-1:-1;;;174847:35:0;;;;;;;;;;;174765:129;174977:6;:18;;;:25;175006:1;174977:30;174973:105;;175031:35;;-1:-1:-1;;;175031:35:0;;;;;;;;;;;174973:105;175128:33;175164:6;:18;;;175183:1;175164:21;;;;;;;;:::i;:::-;;;;;;;175128:57;;175214:10;:15;;;:22;175240:1;175214:27;:75;;;-1:-1:-1;175258:17:0;;;;-1:-1:-1;;;;;175258:31:0;;175214:75;:132;;;;175331:15;-1:-1:-1;;;;;175306:40:0;:10;:21;;;-1:-1:-1;;;;;175306:40:0;;;175214:132;:184;;;;175389:9;-1:-1:-1;;;;;175363:35:0;:10;:22;;;-1:-1:-1;;;;;175363:35:0;;;175214:184;:250;;;;175441:6;:23;;;175415:10;:22;;;:49;;175214:250;175196:349;;;175498:35;;-1:-1:-1;;;175498:35:0;;;;;;;;;;;175196:349;175606:49;175627:15;175644:10;175606:20;:49::i;:::-;;174441:1222;;;174326:1337;:::o;135833:246::-;135966:26;135986:5;135966:19;:26::i;:::-;135961:111;;136009:51;136037:5;136044:7;136053:6;136009:27;:51::i;:::-;135833:246;;;:::o;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;89708:186::-;89766:9;89792:16;89802:5;89792:9;:16::i;:::-;:94;;89848:38;;-1:-1:-1;;;89848:38:0;;89880:4;89848:38;;;665:51:1;-1:-1:-1;;;;;89848:23:0;;;;;638:18:1;;89848:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;89792:94;;;89811:21;89788:98;89708:186;-1:-1:-1;;89708:186:0:o;166333:553::-;166611:26;166631:5;166611:19;:26::i;:::-;166607:142;;;166660:13;-1:-1:-1;;;;;166654:28:0;;166691:6;166654:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;166724:13;166716:21;;166607:142;166824:54;166853:5;166860:9;166871:6;166824:28;:54::i;136256:289::-;136346:26;136366:5;136346:19;:26::i;:::-;136341:197;;136393:47;;-1:-1:-1;;;136393:47:0;;136425:4;136393:47;;;18812:51:1;-1:-1:-1;;;;;18899:32:1;;;18879:18;;;18872:60;136443:1:0;;136393:23;;;;;;18785:18:1;;136393:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:51;136389:138;;;136465:46;136493:5;136500:7;136509:1;136465:27;:46::i;:::-;136256:289;;:::o;171847:1130::-;172004:17;172024:6;:23;;;-1:-1:-1;;;;;172024:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;172004:51;;172066:23;172092:6;:13;;;-1:-1:-1;;;;;172092:19:0;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;172066:47;;172313:54;172340:9;172351:15;172313:26;:54::i;:::-;172309:129;;;172391:35;;-1:-1:-1;;;172391:35:0;;;;;;;;;;;172309:129;172486:17;;;;172532:15;;;;:22;:27;;:75;;-1:-1:-1;172576:17:0;;;;-1:-1:-1;;;;;172576:31:0;;172532:75;:126;;;;172649:9;-1:-1:-1;;;;;172624:34:0;:10;:21;;;-1:-1:-1;;;;;172624:34:0;;;172532:126;:184;;;;172701:15;-1:-1:-1;;;;;172675:41:0;:10;:22;;;-1:-1:-1;;;;;172675:41:0;;;172532:184;:246;;;;172759:6;:19;;;172733:10;:22;;;:45;;172532:246;172514:345;;;172812:35;;-1:-1:-1;;;172812:35:0;;;;;;;;;;;172514:345;172920:49;172941:15;172958:10;172920:20;:49::i;:::-;;171993:984;;;171847:1130;;:::o;165520:452::-;165735:13;;165704:46;;-1:-1:-1;;;165704:46:0;;-1:-1:-1;;;;;683:32:1;;;165704:46:0;;;665:51:1;165704:13:0;:22;;;;;;638:18:1;;165704:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;165699:122;;165774:35;;-1:-1:-1;;;165774:35:0;;;;;;;;;;;165699:122;165833:13;;165887:23;;;;165833:131;;-1:-1:-1;;;165833:131:0;;-1:-1:-1;;;;;165833:39:0;;;;;;:131;;165925:7;;165833:6;;:131;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;166991:174;167098:9;167124:33;167149:1;167152;167155;167124:24;:33::i;:::-;167120:37;166991:174;-1:-1:-1;;;;166991:174:0:o;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;163809:473::-;164030:23;;163999:56;;-1:-1:-1;;;163999:56:0;;-1:-1:-1;;;;;683:32:1;;;163999:56:0;;;665:51:1;163999:13:0;:22;;;;;;638:18:1;;163999:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;163994:132;;164079:35;;-1:-1:-1;;;164079:35:0;;;;;;;;;;;163994:132;164138:23;;164201:19;;;;164138:136;;-1:-1:-1;;;164138:136:0;;-1:-1:-1;;;;;164138:48:0;;;;;;:136;;164235:7;;164138:6;;:136;;;:::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;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;88031:270;-1:-1:-1;;;;;88131:17:0;;;:11;:17;;;;;;;;;;;88149:57;;-1:-1:-1;;;88149:57:0;;;;;665:51:1;;;;88131:17:0;:11;;88149:15;:51;;;;;;638:18:1;;88149:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;88131:76;;;;;;;;;;;;;;-1:-1:-1;88131:76:0;;;-1:-1:-1;;;;;88131:86:0;;;;;;;;;;;;88112:182;;88251:31;;-1:-1:-1;;;88251:31:0;;;;;;;;;;;8475:518;8549:9;8776:1;8772;8768:6;8764:14;8761:1;8758:21;8755:1;8751:29;8744:37;8741:1;8737:45;8727:172;;8816:10;8810:4;8803:24;8879:4;8873;8866:18;8727:172;-1:-1:-1;8961:9:0;;8936:17;;;8929:25;8922:33;8957:17;;;8918:57;;8475:518::o;88759:309::-;88865:4;88896:6;-1:-1:-1;;;;;88886:16:0;:6;-1:-1:-1;;;;;88886:16:0;;88882:60;;-1:-1:-1;88926:4:0;88919:11;;88882:60;88958:17;88968:6;88958:9;:17::i;:::-;:38;;;;;88979:17;88989:6;88979:9;:17::i;:::-;88954:82;;;-1:-1:-1;89020:4:0;89013:11;;88954:82;-1:-1:-1;89055:5:0;88759:309;;;;:::o;133610:939::-;133713:17;636:4;133747:6;:15;;;:22;133743:99;;133814:6;:15;;;133793:37;;-1:-1:-1;;;133793:37:0;;;;;;10888:25:1;;10876:2;10861:18;;10742:177;133793:37:0;;;;;;;;133743:99;133866:23;133878:2;133882:6;133866:11;:23::i;:::-;133854:35;;133902:17;133922:28;133947:2;133922:24;:28::i;:::-;133902:48;;133961:15;133979:52;133989:2;133993:6;:17;;;134012:6;:18;;;133979:9;:52::i;:::-;133961:70;;134042:16;134061:44;134071:2;134075:6;:18;;;134095:9;134061;:44::i;:::-;134042:63;;134187:7;134176:8;:18;134172:67;;;134211:16;;;;;134172:67;134304:16;134323:110;134364:18;134374:8;134364:7;:18;:::i;:::-;636:4;134415:7;134323:26;:110::i;:::-;134304:129;;134461:6;:15;;;134450:8;:26;134446:96;;;134500:30;;-1:-1:-1;;;134500:30:0;;;;;10888:25:1;;;10861:18;;134500:30:0;10742:177:1;89327:185:0;89384:11;-1:-1:-1;;;;;89417:19:0;;;;:87;;-1:-1:-1;;;;;;;89453:51:0;89462:42;89453:51;;89327:185::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;7895:476;7967:9;8194:1;8190;8186:6;8182:14;8179:1;8176:21;8173:1;8169:29;8162:37;8159:1;8155:45;8145:172;;8234:10;8228:4;8221:24;8297:4;8291;8284:18;8145:172;-1:-1:-1;8340:9:0;;8336:17;;7895:476::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;131155:1555::-;131312:18;;;;131362:17;;131260;;131312:18;131460:51;131362:17;131312:18;131460:26;:51::i;:::-;131456:115;;;131535:24;;-1:-1:-1;;;131535:24:0;;;;;;;;;;;131456:115;131636:13;;;;131609:41;;-1:-1:-1;;;131609:41:0;;-1:-1:-1;;;;;683:32:1;;;131609:41:0;;;665:51:1;131583:23:0;;131609:26;;;;;638:18:1;;131609:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;131583:67;-1:-1:-1;;;;;;131725:29:0;;131721:98;;131778:29;;-1:-1:-1;;;131778:29:0;;;;;;;;;;;131721:98;131870:92;;-1:-1:-1;;;131870:92:0;;-1:-1:-1;;;;;131870:69:0;;;;;:92;;131940:6;;131956:4;;131870:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132049:63;132066:10;132078:6;:13;;;132093:6;:18;;;132049:16;:63::i;:::-;132199:21;132223:33;132244:11;132223:20;:33::i;:::-;132199:57;;132269:17;132289:31;132309:10;132289:19;:31::i;:::-;:69;;132357:1;132289:69;;;132336:6;:18;;;132289:69;132269:89;;132401:124;132451:6;:13;;;132479:6;:11;;;132505:9;132401:35;:124::i;:::-;;132578:50;132602:10;132614:6;:13;;;132578:23;:50::i;:::-;132689:13;132653:33;132674:11;132653:20;:33::i;:::-;:49;;;;:::i;:::-;132641:61;131155:1555;-1:-1:-1;;;;;;;;131155:1555:0:o;90109:183::-;90193:28;90265:2;-1:-1:-1;;;;;90265:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;134874:745::-;135000:14;-1:-1:-1;;;;;135145:19:0;;135141:66;;130028:42;135181:14;;135141:66;135264:30;;-1:-1:-1;;;135264:30:0;;-1:-1:-1;;;;;22892:32:1;;;135264:30:0;;;22874:51:1;135283:4:0;22941:18:1;;;22934:50;;;23000:18;;;22993:50;135228:13:0;;;;135264:11;;;;;22847:18:1;;135264:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135227:67;;;;1036:1;135309:9;:21;135305:90;;135354:29;;-1:-1:-1;;;135354:29:0;;-1:-1:-1;;;;;683:32:1;;135354:29:0;;;665:51:1;638:18;;135354:29:0;497:225:1;135305:90:0;135454:157;135493:5;135513:6;135541:26;135561:5;135541:19;:26::i;:::-;:58;;135582:5;-1:-1:-1;;;;;135575:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;135541:58;;;135570:2;135541:58;135534:66;;:2;:66;:::i;:::-;135454:24;:157::i;:::-;135445:166;134874:745;-1:-1:-1;;;;;;134874:745:0:o;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;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;14:286:1:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:1;;209:43;;199:71;;266:1;263;256:12;199:71;289:5;14:286;-1:-1:-1;;;14:286:1:o;727:131::-;-1:-1:-1;;;;;802:31:1;;792:42;;782:70;;848:1;845;838:12;782:70;727:131;:::o;863:127::-;924:10;919:3;915:20;912:1;905:31;955:4;952:1;945:15;979:4;976:1;969:15;995:253;1067:2;1061:9;1109:4;1097:17;;-1:-1:-1;;;;;1129:34:1;;1165:22;;;1126:62;1123:88;;;1191:18;;:::i;:::-;1227:2;1220:22;995:253;:::o;1253:275::-;1324:2;1318:9;1389:2;1370:13;;-1:-1:-1;;1366:27:1;1354:40;;-1:-1:-1;;;;;1409:34:1;;1445:22;;;1406:62;1403:88;;;1471:18;;:::i;:::-;1507:2;1500:22;1253:275;;-1:-1:-1;1253:275:1:o;1533:143::-;1610:20;;1639:31;1610:20;1639:31;:::i;:::-;1533:143;;;:::o;1681:558::-;1723:5;1776:3;1769:4;1761:6;1757:17;1753:27;1743:55;;1794:1;1791;1784:12;1743:55;1834:6;1821:20;-1:-1:-1;;;;;1856:6:1;1853:30;1850:56;;;1886:18;;:::i;:::-;1930:59;1977:2;1954:17;;-1:-1:-1;;1950:31:1;1983:4;1946:42;1930:59;:::i;:::-;2014:6;2005:7;1998:23;2068:3;2061:4;2052:6;2044;2040:19;2036:30;2033:39;2030:59;;;2085:1;2082;2075:12;2030:59;2150:6;2143:4;2135:6;2131:17;2124:4;2115:7;2111:18;2098:59;2206:1;2177:20;;;2199:4;2173:31;2166:42;;;;2181:7;1681:558;-1:-1:-1;;;1681:558:1:o;2244:993::-;2295:5;2343:4;2331:9;2326:3;2322:19;2318:30;2315:50;;;2361:1;2358;2351:12;2315:50;2383:22;;:::i;:::-;2374:31;;2442:9;2429:23;2461:33;2486:7;2461:33;:::i;:::-;2503:22;;2598:2;2583:18;;;2570:32;2618:14;;;2611:31;2694:2;2679:18;;2666:32;2707:33;2666:32;2707:33;:::i;:::-;2767:2;2756:14;;2749:31;2832:2;2817:18;;2804:32;2845:33;2804:32;2845:33;:::i;:::-;2905:2;2894:14;;2887:31;2991:3;2976:19;;;2963:33;3012:15;;;3005:32;3088:3;3073:19;;3060:33;-1:-1:-1;;;;;3105:30:1;;3102:50;;;3148:1;3145;3138:12;3102:50;3185:45;3226:3;3217:6;3206:9;3202:22;3185:45;:::i;:::-;3179:3;3172:5;3168:15;3161:70;;2244:993;;;;:::o;3242:889::-;3300:5;3353:3;3346:4;3338:6;3334:17;3330:27;3320:55;;3371:1;3368;3361:12;3320:55;3411:6;3398:20;-1:-1:-1;;;;;3433:6:1;3430:30;3427:56;;;3463:18;;:::i;:::-;3509:6;3506:1;3502:14;3536:30;3560:4;3556:2;3552:13;3536:30;:::i;:::-;3602:19;;;3646:4;3678:15;;;3674:26;;;3637:14;;;;3712:15;;;3709:35;;;3740:1;3737;3730:12;3709:35;3776:4;3768:6;3764:17;3753:28;;3790:310;3806:6;3801:3;3798:15;3790:310;;;3894:3;3881:17;-1:-1:-1;;;;;3917:11:1;3914:35;3911:55;;;3962:1;3959;3952:12;3911:55;3991:64;4051:3;4044:4;4030:11;4022:6;4018:24;4014:35;3991:64;:::i;:::-;3979:77;;-1:-1:-1;4085:4:1;3823:14;;;;4076;;;;3790:310;;4136:965;4199:5;4247:4;4235:9;4230:3;4226:19;4222:30;4219:50;;;4265:1;4262;4255:12;4219:50;4287:22;;:::i;:::-;4278:31;;4332:38;4360:9;4332:38;:::i;:::-;4318:53;;4444:2;4429:18;;;4416:32;4464:14;;;4457:31;4520:47;4563:2;4548:18;;4520:47;:::i;:::-;4515:2;4504:14;;4497:71;4641:2;4626:18;;;4613:32;4661:14;;;4654:31;4736:3;4721:19;;4708:33;-1:-1:-1;;;;;4753:30:1;;4750:50;;;4796:1;4793;4786:12;4750:50;4833:61;4890:3;4881:6;4870:9;4866:22;4833:61;:::i;:::-;4827:3;4820:5;4816:15;4809:86;;4948:3;4937:9;4933:19;4920:33;-1:-1:-1;;;;;4968:8:1;4965:32;4962:52;;;5010:1;5007;5000:12;5106:760;5226:6;5234;5242;5250;5303:3;5291:9;5282:7;5278:23;5274:33;5271:53;;;5320:1;5317;5310:12;5271:53;5359:9;5346:23;5378:31;5403:5;5378:31;:::i;:::-;5428:5;-1:-1:-1;5506:2:1;5491:18;;5478:32;;-1:-1:-1;5588:2:1;5573:18;;5560:32;5601:33;5560:32;5601:33;:::i;:::-;5653:7;-1:-1:-1;5711:2:1;5696:18;;5683:32;-1:-1:-1;;;;;5727:30:1;;5724:50;;;5770:1;5767;5760:12;5724:50;5793:67;5852:7;5843:6;5832:9;5828:22;5793:67;:::i;:::-;5783:77;;;5106:760;;;;;;;:::o;5871:388::-;5939:6;5947;6000:2;5988:9;5979:7;5975:23;5971:32;5968:52;;;6016:1;6013;6006:12;5968:52;6055:9;6042:23;6074:31;6099:5;6074:31;:::i;:::-;6124:5;-1:-1:-1;6181:2:1;6166:18;;6153:32;6194:33;6153:32;6194:33;:::i;:::-;6246:7;6236:17;;;5871:388;;;;;:::o;6264:953::-;6325:5;6373:4;6361:9;6356:3;6352:19;6348:30;6345:50;;;6391:1;6388;6381:12;6345:50;6413:22;;:::i;:::-;6404:31;;6458:38;6486:9;6458:38;:::i;:::-;6444:53;;6570:2;6555:18;;;6542:32;6590:14;;;6583:31;6646:47;6689:2;6674:18;;6646:47;:::i;:::-;6641:2;6630:14;;6623:71;6767:2;6752:18;;;6739:32;6787:14;;;6780:31;6862:3;6847:19;;6834:33;-1:-1:-1;;;;;6879:30:1;;6876:50;;;6922:1;6919;6912:12;6876:50;6959:51;7006:3;6997:6;6986:9;6982:22;6959:51;:::i;7222:756::-;7340:6;7348;7356;7364;7417:3;7405:9;7396:7;7392:23;7388:33;7385:53;;;7434:1;7431;7424:12;7385:53;7473:9;7460:23;7492:31;7517:5;7492:31;:::i;:::-;7542:5;-1:-1:-1;7620:2:1;7605:18;;7592:32;;-1:-1:-1;7702:2:1;7687:18;;7674:32;7715:33;7674:32;7715:33;:::i;:::-;7767:7;-1:-1:-1;7825:2:1;7810:18;;7797:32;-1:-1:-1;;;;;7841:30:1;;7838:50;;;7884:1;7881;7874:12;7838:50;7907:65;7964:7;7955:6;7944:9;7940:22;7907:65;:::i;7983:165::-;8052:5;8097:3;8088:6;8083:3;8079:16;8075:26;8072:46;;;8114:1;8111;8104:12;8072:46;-1:-1:-1;8136:6:1;7983:165;-1:-1:-1;7983:165:1:o;8153:488::-;8257:6;8265;8318:2;8306:9;8297:7;8293:23;8289:32;8286:52;;;8334:1;8331;8324:12;8286:52;8374:9;8361:23;-1:-1:-1;;;;;8399:6:1;8396:30;8393:50;;;8439:1;8436;8429:12;8393:50;8462:76;8530:7;8521:6;8510:9;8506:22;8462:76;:::i;:::-;8452:86;8607:2;8592:18;;;;8579:32;;-1:-1:-1;;;;8153:488:1:o;8646:606::-;8757:6;8765;8773;8826:2;8814:9;8805:7;8801:23;8797:32;8794:52;;;8842:1;8839;8832:12;8794:52;8887:23;;;-1:-1:-1;8985:2:1;8970:18;;8957:32;-1:-1:-1;;;;;9001:30:1;;8998:50;;;9044:1;9041;9034:12;8998:50;9067:76;9135:7;9126:6;9115:9;9111:22;9067:76;:::i;:::-;8646:606;;9057:86;;-1:-1:-1;;;;9216:2:1;9201:18;;;;9188:32;;8646:606::o;9489:247::-;9548:6;9601:2;9589:9;9580:7;9576:23;9572:32;9569:52;;;9617:1;9614;9607:12;9569:52;9656:9;9643:23;9675:31;9700:5;9675:31;:::i;10232:118::-;10318:5;10311:13;10304:21;10297:5;10294:32;10284:60;;10340:1;10337;10330:12;10355:382;10420:6;10428;10481:2;10469:9;10460:7;10456:23;10452:32;10449:52;;;10497:1;10494;10487:12;10449:52;10536:9;10523:23;10555:31;10580:5;10555:31;:::i;:::-;10605:5;-1:-1:-1;10662:2:1;10647:18;;10634:32;10675:30;10634:32;10675:30;:::i;10924:645::-;11045:6;11053;11106:2;11094:9;11085:7;11081:23;11077:32;11074:52;;;11122:1;11119;11112:12;11074:52;11162:9;11149:23;-1:-1:-1;;;;;11187:6:1;11184:30;11181:50;;;11227:1;11224;11217:12;11181:50;11250:22;;11303:4;11295:13;;11291:27;-1:-1:-1;11281:55:1;;11332:1;11329;11322:12;11281:55;11372:2;11359:16;-1:-1:-1;;;;;11390:6:1;11387:30;11384:50;;;11430:1;11427;11420:12;11384:50;11483:7;11478:2;11468:6;11465:1;11461:14;11457:2;11453:23;11449:32;11446:45;11443:65;;;11504:1;11501;11494:12;11443:65;11535:2;11527:11;;;;;11557:6;;-1:-1:-1;10924:645:1;-1:-1:-1;;;10924:645:1:o;11574:288::-;11615:3;11653:5;11647:12;11680:6;11675:3;11668:19;11736:6;11729:4;11722:5;11718:16;11711:4;11706:3;11702:14;11696:47;11788:1;11781:4;11772:6;11767:3;11763:16;11759:27;11752:38;11851:4;11844:2;11840:7;11835:2;11827:6;11823:15;11819:29;11814:3;11810:39;11806:50;11799:57;;;11574:288;;;;:::o;11867:779::-;12027:4;12075:2;12064:9;12060:18;12105:2;12094:9;12087:21;12128:6;12163;12157:13;12194:6;12186;12179:22;12232:2;12221:9;12217:18;12210:25;;12294:2;12284:6;12281:1;12277:14;12266:9;12262:30;12258:39;12244:53;;12332:2;12324:6;12320:15;12353:1;12363:254;12377:6;12374:1;12371:13;12363:254;;;12470:2;12466:7;12454:9;12446:6;12442:22;12438:36;12433:3;12426:49;12498:39;12530:6;12521;12515:13;12498:39;:::i;:::-;12488:49;-1:-1:-1;12572:2:1;12595:12;;;;12560:15;;;;;12399:1;12392:9;12363:254;;;-1:-1:-1;12634:6:1;;11867:779;-1:-1:-1;;;;;;11867:779:1:o;12859:629::-;12972:6;12980;12988;13041:2;13029:9;13020:7;13016:23;13012:32;13009:52;;;13057:1;13054;13047:12;13009:52;13097:9;13084:23;-1:-1:-1;;;;;13122:6:1;13119:30;13116:50;;;13162:1;13159;13152:12;13116:50;13185:76;13253:7;13244:6;13233:9;13229:22;13185:76;:::i;:::-;13175:86;;;13311:2;13300:9;13296:18;13283:32;13324:31;13349:5;13324:31;:::i;:::-;12859:629;;13374:5;;-1:-1:-1;;;13452:2:1;13437:18;;;;13424:32;;12859:629::o;14125:245::-;14192:6;14245:2;14233:9;14224:7;14220:23;14216:32;14213:52;;;14261:1;14258;14251:12;14213:52;14293:9;14287:16;14312:28;14334:5;14312:28;:::i;14375:251::-;14445:6;14498:2;14486:9;14477:7;14473:23;14469:32;14466:52;;;14514:1;14511;14504:12;14466:52;14546:9;14540:16;14565:31;14590:5;14565:31;:::i;14631:230::-;14701:6;14754:2;14742:9;14733:7;14729:23;14725:32;14722:52;;;14770:1;14767;14760:12;14722:52;-1:-1:-1;14815:16:1;;14631:230;-1:-1:-1;14631:230:1:o;14866:127::-;14927:10;14922:3;14918:20;14915:1;14908:31;14958:4;14955:1;14948:15;14982:4;14979:1;14972:15;14998:128;15065:9;;;15086:11;;;15083:37;;;15100:18;;:::i;15410:127::-;15471:10;15466:3;15462:20;15459:1;15452:31;15502:4;15499:1;15492:15;15526:4;15523:1;15516:15;15542:456;15630:6;15638;15646;15699:2;15687:9;15678:7;15674:23;15670:32;15667:52;;;15715:1;15712;15705:12;15667:52;-1:-1:-1;;15760:16:1;;15866:2;15851:18;;15845:25;15962:2;15947:18;;;15941:25;15760:16;;15845:25;;-1:-1:-1;15941:25:1;15542:456;-1:-1:-1;15542:456:1:o;16003:220::-;16123:9;16160:57;16202:14;16195:5;16160:57;:::i;16496:214::-;16612:9;16649:55;16689:14;16682:5;16649:55;:::i;16978:332::-;17079:4;17137:11;17124:25;17231:2;17227:7;17216:8;17200:14;17196:29;17192:43;17172:18;17168:68;17158:96;;17250:1;17247;17240:12;17158:96;17271:33;;;;;16978:332;-1:-1:-1;;16978:332:1:o;17315:902::-;17433:9;17492:4;17484:5;17468:14;17464:26;17460:37;17457:57;;;17510:1;17507;17500:12;17457:57;17563:2;17557:9;17605:4;17593:17;;-1:-1:-1;;;;;17625:34:1;;17661:22;;;17622:62;17619:88;;;17687:18;;:::i;:::-;17723:2;17716:22;17762:19;;17790:33;17762:19;17790:33;:::i;:::-;17832:23;;17903:2;17892:14;;17879:28;17916:30;17879:28;17916:30;:::i;:::-;17974:2;17962:15;;17955:32;18034:2;18023:14;;18010:28;-1:-1:-1;;;;;18050:30:1;;18047:50;;;18093:1;18090;18083:12;18047:50;18130:52;18167:14;18158:6;18151:5;18147:18;18130:52;:::i;:::-;18125:2;18113:15;;18106:77;-1:-1:-1;18117:6:1;17315:902;-1:-1:-1;;17315:902:1:o;18222:411::-;-1:-1:-1;;;;;18425:32:1;;;18407:51;;18494:32;;18489:2;18474:18;;18467:60;18563:2;18558;18543:18;;18536:30;;;-1:-1:-1;;18583:44:1;;18608:18;;18600:6;18583:44;:::i;18943:549::-;19024:12;;-1:-1:-1;;;;;19020:38:1;;;19008:51;;19108:4;19097:16;;;19091:23;19075:14;;;19068:47;19168:4;19157:16;;;19151:23;19147:49;;19131:14;;;19124:73;19250:4;19239:16;;;19233:23;19229:49;;;19213:14;;;19206:73;19328:4;19317:16;;;19311:23;19295:14;;;19288:47;19046:3;19370:16;;;19364:23;19419:4;19403:14;;;19396:28;;;-1:-1:-1;;19440:46:1;;19471:14;;19364:23;19440:46;:::i;19497:1508::-;19750:6;19739:9;19732:25;19822:1;19818;19813:3;19809:11;19805:19;19797:6;19793:32;19788:2;19777:9;19773:18;19766:60;19862:2;19857;19846:9;19842:18;19835:30;19713:4;19903:3;19892:9;19888:19;19979:1;19975;19970:3;19966:11;19962:19;19953:6;19947:13;19943:39;19938:2;19927:9;19923:18;19916:67;20038:2;20030:6;20026:15;20020:22;20014:3;20003:9;19999:19;19992:51;20125:1;20121;20116:3;20112:11;20108:19;20102:2;20094:6;20090:15;20084:22;20080:48;20074:3;20063:9;20059:19;20052:77;20185:2;20177:6;20173:15;20167:22;20160:4;20149:9;20145:20;20138:52;20237:3;20229:6;20225:16;20219:23;20279:4;20273:3;20262:9;20258:19;20251:33;20304:6;20339:12;20333:19;20376:6;20368;20361:22;20414:3;20403:9;20399:19;20392:26;;20477:3;20467:6;20464:1;20460:14;20449:9;20445:30;20441:40;20427:54;;20522:2;20508:12;20504:21;20490:35;;20543:1;20553:261;20567:6;20564:1;20561:13;20553:261;;;20660:3;20656:8;20644:9;20636:6;20632:22;20628:37;20623:3;20616:50;20689:45;20727:6;20718;20712:13;20689:45;:::i;:::-;20679:55;-1:-1:-1;20769:2:1;20757:15;;;;20792:12;;;;;20589:1;20582:9;20553:261;;;-1:-1:-1;;;;20863:3:1;20851:16;;20845:23;20909:22;;;-1:-1:-1;;20905:36:1;20899:3;20884:19;;20877:65;20959:40;20913:6;20845:23;20959:40;:::i;:::-;20951:48;19497:1508;-1:-1:-1;;;;;;;19497:1508:1:o;21010:1012::-;21259:6;21248:9;21241:25;21331:1;21327;21322:3;21318:11;21314:19;21306:6;21302:32;21297:2;21286:9;21282:18;21275:60;21371:2;21366;21355:9;21351:18;21344:30;21446:1;21442;21437:3;21433:11;21429:19;21420:6;21414:13;21410:39;21405:2;21394:9;21390:18;21383:67;21505:2;21497:6;21493:15;21487:22;21481:3;21470:9;21466:19;21459:51;21592:1;21588;21583:3;21579:11;21575:19;21569:2;21561:6;21557:15;21551:22;21547:48;21541:3;21530:9;21526:19;21519:77;21652:2;21644:6;21640:15;21634:22;21627:4;21616:9;21612:20;21605:52;21222:4;21704:3;21696:6;21692:16;21686:23;21746:4;21740:3;21729:9;21725:19;21718:33;21774:57;21826:3;21815:9;21811:19;21797:12;21774:57;:::i;:::-;21760:71;;21880:3;21872:6;21868:16;21862:23;21954:2;21950:7;21938:9;21930:6;21926:22;21922:36;21916:3;21905:9;21901:19;21894:65;21976:40;22009:6;21993:14;21976:40;:::i;22027:301::-;22156:3;22194:6;22188:13;22240:6;22233:4;22225:6;22221:17;22216:3;22210:37;22302:1;22266:16;;22291:13;;;-1:-1:-1;22266:16:1;22027:301;-1:-1:-1;22027:301:1:o;22333:346::-;22534:2;22523:9;22516:21;22497:4;22554:50;22600:2;22589:9;22585:18;22577:6;22554:50;:::i;:::-;22546:58;;22669:1;22665;22660:3;22656:11;22652:19;22644:6;22640:32;22635:2;22624:9;22620:18;22613:60;22333:346;;;;;:::o;23054:343::-;23133:6;23141;23194:2;23182:9;23173:7;23169:23;23165:32;23162:52;;;23210:1;23207;23200:12;23162:52;-1:-1:-1;;23255:16:1;;23361:2;23346:18;;;23340:25;23255:16;;23340:25;;-1:-1:-1;23054:343:1:o;23402:273::-;23470:6;23523:2;23511:9;23502:7;23498:23;23494:32;23491:52;;;23539:1;23536;23529:12;23491:52;23571:9;23565:16;23621:4;23614:5;23610:16;23603:5;23600:27;23590:55;;23641:1;23638;23631:12;23680:375;23768:1;23786:5;23800:249;23821:1;23811:8;23808:15;23800:249;;;23871:4;23866:3;23862:14;23856:4;23853:24;23850:50;;;23880:18;;:::i;:::-;23930:1;23920:8;23916:16;23913:49;;;23944:16;;;;23913:49;24027:1;24023:16;;;;;23983:15;;23800:249;;;23680:375;;;;;;:::o;24060:902::-;24109:5;24139:8;24129:80;;-1:-1:-1;24180:1:1;24194:5;;24129:80;24228:4;24218:76;;-1:-1:-1;24265:1:1;24279:5;;24218:76;24310:4;24328:1;24323:59;;;;24396:1;24391:174;;;;24303:262;;24323:59;24353:1;24344:10;;24367:5;;;24391:174;24428:3;24418:8;24415:17;24412:43;;;24435:18;;:::i;:::-;-1:-1:-1;;24491:1:1;24477:16;;24550:5;;24303:262;;24649:2;24639:8;24636:16;24630:3;24624:4;24621:13;24617:36;24611:2;24601:8;24598:16;24593:2;24587:4;24584:12;24580:35;24577:77;24574:203;;;-1:-1:-1;24686:19:1;;;24762:5;;24574:203;24809:42;-1:-1:-1;;24834:8:1;24828:4;24809:42;:::i;:::-;24887:6;24883:1;24879:6;24875:19;24866:7;24863:32;24860:58;;;24898:18;;:::i;:::-;24936:20;;24060:902;-1:-1:-1;;;24060:902:1:o;24967:140::-;25025:5;25054:47;25095:4;25085:8;25081:19;25075:4;25054:47;:::i
Swarm Source
ipfs://957e331cc7d75b32c1b8a66ec9908bf2691ab50e24496acf8a1fa36373811b6c
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
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.