Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
NuriV3Connector
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { INuriNonfungiblePositionManager } from
"contracts/interfaces/external/nuri/INuriNonfungiblePositionManager.sol";
import { NftAddLiquidity } from "contracts/structs/NftLiquidityStructs.sol";
import { RamsesV3Connector } from
"contracts/connectors/ramses/RamsesV3Connector.sol";
contract NuriV3Connector is RamsesV3Connector {
function _mint(
NftAddLiquidity memory addLiquidityParams
) internal override {
INuriNonfungiblePositionManager.MintParams memory params =
INuriNonfungiblePositionManager.MintParams({
token0: addLiquidityParams.pool.token0,
token1: addLiquidityParams.pool.token1,
fee: addLiquidityParams.pool.fee,
tickLower: addLiquidityParams.tickLower,
tickUpper: addLiquidityParams.tickUpper,
amount0Desired: addLiquidityParams.amount0Desired,
amount1Desired: addLiquidityParams.amount1Desired,
amount0Min: addLiquidityParams.amount0Min,
amount1Min: addLiquidityParams.amount1Min,
recipient: address(this),
deadline: block.timestamp + 1
});
INuriNonfungiblePositionManager(address(addLiquidityParams.nft)).mint(
params
);
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
import { IERC721Enumerable } from
"lib/openzeppelin-contracts/contracts/interfaces/IERC721Enumerable.sol";
/// @title Non-fungible token for positions
/// @notice Wraps Pharaoh V2 positions in a non-fungible token interface which
/// allows for them to be transferred
/// and authorized.
interface INuriNonfungiblePositionManager is IERC721Enumerable {
/// @notice Emitted when liquidity is increased for a position NFT
/// @dev Also emitted when a token is minted
/// @param tokenId The ID of the token for which liquidity was increased
/// @param liquidity The amount by which liquidity for the NFT position was
/// increased
/// @param amount0 The amount of token0 that was paid for the increase in
/// liquidity
/// @param amount1 The amount of token1 that was paid for the increase in
/// liquidity
event IncreaseLiquidity(
uint256 indexed tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
/// @notice Emitted when liquidity is decreased for a position NFT
/// @param tokenId The ID of the token for which liquidity was decreased
/// @param liquidity The amount by which liquidity for the NFT position was
/// decreased
/// @param amount0 The amount of token0 that was accounted for the decrease
/// in liquidity
/// @param amount1 The amount of token1 that was accounted for the decrease
/// in liquidity
event DecreaseLiquidity(
uint256 indexed tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
/// @notice Emitted when tokens are collected for a position NFT
/// @dev The amounts reported may not be exactly equivalent to the amounts
/// transferred, due to rounding behavior
/// @param tokenId The ID of the token for which underlying tokens were
/// collected
/// @param recipient The address of the account that received the collected
/// tokens
/// @param amount0 The amount of token0 owed to the position that was
/// collected
/// @param amount1 The amount of token1 owed to the position that was
/// collected
event Collect(
uint256 indexed tokenId,
address recipient,
uint256 amount0,
uint256 amount1
);
/// @notice Returns the position information associated with a given token
/// ID.
/// @dev Throws if the token ID is not valid.
/// @param tokenId The ID of the token that represents the position
/// @return nonce The nonce for permits
/// @return operator The address that is approved for spending
/// @return token0 The address of the token0 for a specific pool
/// @return token1 The address of the token1 for a specific pool
/// @return fee The fee associated with the pool
/// @return tickLower The lower end of the tick range for the position
/// @return tickUpper The higher end of the tick range for the position
/// @return liquidity The liquidity of the position
/// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last
/// action on the individual position
/// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last
/// action on the individual position
/// @return tokensOwed0 The uncollected amount of token0 owed to the
/// position as of the last computation
/// @return tokensOwed1 The uncollected amount of token1 owed to the
/// position as of the last computation
function positions(uint256 tokenId)
external
view
returns (
uint96 nonce,
address operator,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
// details about the Pharaoh position
struct Position {
// the nonce for permits
uint96 nonce;
// the address that is approved for spending this token
address operator;
// the ID of the pool with which this token is connected
uint80 poolId;
// the tick range of the position
int24 tickLower;
int24 tickUpper;
// the liquidity of the position
uint128 liquidity;
// the fee growth of the aggregate position as of the last action on the
// individual position
uint256 feeGrowthInside0LastX128;
uint256 feeGrowthInside1LastX128;
// how many uncollected tokens are owed to the position, as of the last
// computation
uint128 tokensOwed0;
uint128 tokensOwed1;
}
/// @notice Creates a new position wrapped in a NFT
/// @dev Call this when the pool does exist and is initialized. Note that if
/// the pool is created but not initialized
/// a method does not exist, i.e. the pool is assumed to be initialized.
/// @param params The params necessary to mint a position, encoded as
/// `MintParams` in calldata
/// @return tokenId The ID of the token that represents the minted position
/// @return liquidity The amount of liquidity for this position
/// @return amount0 The amount of token0
/// @return amount1 The amount of token1
function mint(MintParams calldata params)
external
payable
returns (
uint256 tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
struct IncreaseLiquidityParams {
uint256 tokenId;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
/// @notice Increases the amount of liquidity in a position, with tokens
/// paid by the `msg.sender`
/// @param params tokenId The ID of the token for which liquidity is being
/// increased,
/// amount0Desired The desired amount of token0 to be spent,
/// amount1Desired The desired amount of token1 to be spent,
/// amount0Min The minimum amount of token0 to spend, which serves as a
/// slippage check,
/// amount1Min The minimum amount of token1 to spend, which serves as a
/// slippage check,
/// deadline The time by which the transaction must be included to effect
/// the change
/// @return liquidity The new liquidity amount as a result of the increase
/// @return amount0 The amount of token0 to acheive resulting liquidity
/// @return amount1 The amount of token1 to acheive resulting liquidity
function increaseLiquidity(IncreaseLiquidityParams calldata params)
external
payable
returns (uint128 liquidity, uint256 amount0, uint256 amount1);
struct DecreaseLiquidityParams {
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
/// @notice Decreases the amount of liquidity in a position and accounts it
/// to the position
/// @param params tokenId The ID of the token for which liquidity is being
/// decreased,
/// amount The amount by which liquidity will be decreased,
/// amount0Min The minimum amount of token0 that should be accounted for the
/// burned liquidity,
/// amount1Min The minimum amount of token1 that should be accounted for the
/// burned liquidity,
/// deadline The time by which the transaction must be included to effect
/// the change
/// @return amount0 The amount of token0 accounted to the position's tokens
/// owed
/// @return amount1 The amount of token1 accounted to the position's tokens
/// owed
function decreaseLiquidity(DecreaseLiquidityParams calldata params)
external
payable
returns (uint256 amount0, uint256 amount1);
struct CollectParams {
uint256 tokenId;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
/// @notice Collects up to a maximum amount of fees owed to a specific
/// position to the recipient
/// @param params tokenId The ID of the NFT for which tokens are being
/// collected,
/// recipient The account that should receive the tokens,
/// amount0Max The maximum amount of token0 to collect,
/// amount1Max The maximum amount of token1 to collect
/// @return amount0 The amount of fees collected in token0
/// @return amount1 The amount of fees collected in token1
function collect(CollectParams calldata params)
external
payable
returns (uint256 amount0, uint256 amount1);
/// @notice Burns a token ID, which deletes it from the NFT contract. The
/// token must have 0 liquidity and all tokens
/// must be collected first.
/// @param tokenId The ID of the token that is being burned
function burn(uint256 tokenId) external payable;
function getReward(uint256 tokenId, address[] memory tokens) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { INonfungiblePositionManager } from
"contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
struct Pool {
address token0;
address token1;
uint24 fee;
}
struct NftAddLiquidity {
INonfungiblePositionManager nft;
uint256 tokenId;
Pool pool;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
bytes extraData;
}
struct NftRemoveLiquidity {
INonfungiblePositionManager nft;
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min; // For decreasing
uint256 amount1Min;
uint128 amount0Max; // For collecting
uint128 amount1Max;
bytes extraData;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
import {
INftFarmConnector,
Farm,
NftPosition
} from "contracts/interfaces/INftFarmConnector.sol";
import
"contracts/interfaces/external/ramses/IRamsesNonfungiblePositionManager.sol";
import { ISwapRouter } from
"contracts/interfaces/external/uniswap/ISwapRouter.sol";
import {
UniswapV3Connector,
NftAddLiquidity
} from "contracts/connectors/UniswapV3Connector.sol";
import { INonfungiblePositionManager } from
"contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
struct RamsesV3SwapExtraData {
address pool;
bytes path;
}
contract RamsesV3Connector is UniswapV3Connector {
function swapExactTokensForTokens(
SwapParams memory swap
) external payable override {
RamsesV3SwapExtraData memory extraData =
abi.decode(swap.extraData, (RamsesV3SwapExtraData));
IERC20(swap.tokenIn).approve(extraData.pool, swap.amountIn);
ISwapRouter.ExactInputParams memory params = ISwapRouter
.ExactInputParams({
path: extraData.path,
recipient: address(this),
deadline: block.timestamp + 1,
amountIn: swap.amountIn,
amountOutMinimum: swap.minAmountOut
});
ISwapRouter(swap.router).exactInput(params);
}
function claim(
NftPosition calldata position,
address[] memory rewardTokens,
uint128 amount0Max,
uint128 amount1Max,
bytes calldata // extraData
) external payable override {
IRamsesNonfungiblePositionManager(address(position.nft)).getReward(
position.tokenId, rewardTokens
);
if (amount0Max > 0 || amount1Max > 0) {
IRamsesNonfungiblePositionManager.CollectParams memory params =
IRamsesNonfungiblePositionManager.CollectParams({
tokenId: position.tokenId,
recipient: address(this),
amount0Max: amount0Max,
amount1Max: amount1Max
});
IRamsesNonfungiblePositionManager(address(position.nft)).collect(
params
);
}
}
function _mint(
NftAddLiquidity memory addLiquidityParams
) internal virtual override {
IRamsesNonfungiblePositionManager.MintParams memory params =
IRamsesNonfungiblePositionManager.MintParams({
token0: addLiquidityParams.pool.token0,
token1: addLiquidityParams.pool.token1,
fee: addLiquidityParams.pool.fee,
tickLower: addLiquidityParams.tickLower,
tickUpper: addLiquidityParams.tickUpper,
amount0Desired: addLiquidityParams.amount0Desired,
amount1Desired: addLiquidityParams.amount1Desired,
amount0Min: addLiquidityParams.amount0Min,
amount1Min: addLiquidityParams.amount1Min,
recipient: address(this),
deadline: block.timestamp + 1,
veRamTokenId: 0
});
IRamsesNonfungiblePositionManager(address(addLiquidityParams.nft)).mint(
params
);
}
}// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../token/ERC721/extensions/IERC721Enumerable.sol";
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC721Enumerable } from
"openzeppelin-contracts/contracts/interfaces/IERC721Enumerable.sol";
interface INonfungiblePositionManager is IERC721Enumerable {
struct IncreaseLiquidityParams {
uint256 tokenId;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
struct DecreaseLiquidityParams {
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
struct CollectParams {
uint256 tokenId;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
function increaseLiquidity(IncreaseLiquidityParams memory params)
external
payable
returns (uint256 amount0, uint256 amount1, uint256 liquidity);
function decreaseLiquidity(DecreaseLiquidityParams calldata params)
external
payable
returns (uint256 amount0, uint256 amount1);
function mint(MintParams memory params)
external
payable
returns (uint256 tokenId, uint256 amount0, uint256 amount1);
function collect(CollectParams calldata params)
external
payable
returns (uint256 amount0, uint256 amount1);
function burn(uint256 tokenId) external payable;
function positions(uint256 tokenId)
external
view
returns (
uint96 nonce,
address operator,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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 Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
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);
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
struct AddLiquidityParams {
address router;
address lpToken;
address[] tokens;
uint256[] desiredAmounts;
uint256[] minAmounts;
bytes extraData;
}
struct RemoveLiquidityParams {
address router;
address lpToken;
address[] tokens;
uint256 lpAmountIn;
uint256[] minAmountsOut;
bytes extraData;
}
struct SwapParams {
address router;
uint256 amountIn;
uint256 minAmountOut;
address tokenIn;
bytes extraData;
}
struct GetAmountOutParams {
address router;
address lpToken;
address tokenIn;
address tokenOut;
uint256 amountIn;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { INonfungiblePositionManager } from
"contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
import { Farm } from "contracts/structs/FarmStrategyStructs.sol";
import { NftPosition } from "contracts/structs/NftFarmStrategyStructs.sol";
interface INftFarmConnector {
function depositExistingNft(
NftPosition calldata position,
bytes calldata extraData
) external payable;
function withdrawNft(
NftPosition calldata position,
bytes calldata extraData
) external payable;
// Payable in case an NFT is withdrawn to be increased with ETH
function claim(
NftPosition calldata position,
address[] memory rewardTokens,
uint128 maxAmount0, // For collecting
uint128 maxAmount1,
bytes calldata extraData
) external payable;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;
/// @title Non-fungible token for positions
/// @notice Wraps Ramses V2 positions in a non-fungible token interface which
/// allows for them to be transferred
/// and authorized.
interface IRamsesNonfungiblePositionManager {
/// @notice Emitted when liquidity is increased for a position NFT
/// @dev Also emitted when a token is minted
/// @param tokenId The ID of the token for which liquidity was increased
/// @param liquidity The amount by which liquidity for the NFT position was
/// increased
/// @param amount0 The amount of token0 that was paid for the increase in
/// liquidity
/// @param amount1 The amount of token1 that was paid for the increase in
/// liquidity
event IncreaseLiquidity(
uint256 indexed tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
/// @notice Emitted when liquidity is decreased for a position NFT
/// @param tokenId The ID of the token for which liquidity was decreased
/// @param liquidity The amount by which liquidity for the NFT position was
/// decreased
/// @param amount0 The amount of token0 that was accounted for the decrease
/// in liquidity
/// @param amount1 The amount of token1 that was accounted for the decrease
/// in liquidity
event DecreaseLiquidity(
uint256 indexed tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
/// @notice Emitted when tokens are collected for a position NFT
/// @dev The amounts reported may not be exactly equivalent to the amounts
/// transferred, due to rounding behavior
/// @param tokenId The ID of the token for which underlying tokens were
/// collected
/// @param recipient The address of the account that received the collected
/// tokens
/// @param amount0 The amount of token0 owed to the position that was
/// collected
/// @param amount1 The amount of token1 owed to the position that was
/// collected
event Collect(
uint256 indexed tokenId,
address recipient,
uint256 amount0,
uint256 amount1
);
/// @notice Emitted when the attachment of an NFP is switched to a different
/// veRam NFT.
/// @param tokenId The identifier of the NFP for which the attachment is
/// switched.
/// @param oldVeRamTokenId The identifier of the previous veRam NFT to which
/// the NFP was attached.
/// @param newVeRamTokenId The identifier of the new veRam NFT to which the
/// NFP was attached.
event SwitchAttachment(
uint256 indexed tokenId,
uint256 oldVeRamTokenId,
uint256 newVeRamTokenId
);
/// @notice The address of the veRam NFTs
function veRam() external view returns (address);
/// @notice Returns the position information associated with a given token
/// ID.
/// @dev Throws if the token ID is not valid.
/// @param tokenId The ID of the token that represents the position
/// @return nonce The nonce for permits
/// @return operator The address that is approved for spending
/// @return token0 The address of the token0 for a specific pool
/// @return token1 The address of the token1 for a specific pool
/// @return fee The fee associated with the pool
/// @return tickLower The lower end of the tick range for the position
/// @return tickUpper The higher end of the tick range for the position
/// @return liquidity The liquidity of the position
/// @return feeGrowthInside0LastX128 The fee growth of token0 as of the last
/// action on the individual position
/// @return feeGrowthInside1LastX128 The fee growth of token1 as of the last
/// action on the individual position
/// @return tokensOwed0 The uncollected amount of token0 owed to the
/// position as of the last computation
/// @return tokensOwed1 The uncollected amount of token1 owed to the
/// position as of the last computation
function positions(uint256 tokenId)
external
view
returns (
uint96 nonce,
address operator,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
uint256 veRamTokenId;
}
// details about the Ramses position
struct Position {
// the nonce for permits
uint96 nonce;
// the address that is approved for spending this token
address operator;
// the ID of the pool with which this token is connected
uint80 poolId;
// the tick range of the position
int24 tickLower;
int24 tickUpper;
// the liquidity of the position
uint128 liquidity;
// the fee growth of the aggregate position as of the last action on the
// individual position
uint256 feeGrowthInside0LastX128;
uint256 feeGrowthInside1LastX128;
// how many uncollected tokens are owed to the position, as of the last
// computation
uint128 tokensOwed0;
uint128 tokensOwed1;
// the veRam tokenId attached
uint256 veRamTokenId;
}
/// @notice Creates a new position wrapped in a NFT
/// @dev Call this when the pool does exist and is initialized. Note that if
/// the pool is created but not initialized
/// a method does not exist, i.e. the pool is assumed to be initialized.
/// @param params The params necessary to mint a position, encoded as
/// `MintParams` in calldata
/// @return tokenId The ID of the token that represents the minted position
/// @return liquidity The amount of liquidity for this position
/// @return amount0 The amount of token0
/// @return amount1 The amount of token1
function mint(MintParams calldata params)
external
payable
returns (
uint256 tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
struct IncreaseLiquidityParams {
uint256 tokenId;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
/// @notice Increases the amount of liquidity in a position, with tokens
/// paid by the `msg.sender`
/// @param params tokenId The ID of the token for which liquidity is being
/// increased,
/// amount0Desired The desired amount of token0 to be spent,
/// amount1Desired The desired amount of token1 to be spent,
/// amount0Min The minimum amount of token0 to spend, which serves as a
/// slippage check,
/// amount1Min The minimum amount of token1 to spend, which serves as a
/// slippage check,
/// deadline The time by which the transaction must be included to effect
/// the change
/// @return liquidity The new liquidity amount as a result of the increase
/// @return amount0 The amount of token0 to acheive resulting liquidity
/// @return amount1 The amount of token1 to acheive resulting liquidity
function increaseLiquidity(IncreaseLiquidityParams calldata params)
external
payable
returns (uint128 liquidity, uint256 amount0, uint256 amount1);
struct DecreaseLiquidityParams {
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
/// @notice Decreases the amount of liquidity in a position and accounts it
/// to the position
/// @param params tokenId The ID of the token for which liquidity is being
/// decreased,
/// amount The amount by which liquidity will be decreased,
/// amount0Min The minimum amount of token0 that should be accounted for the
/// burned liquidity,
/// amount1Min The minimum amount of token1 that should be accounted for the
/// burned liquidity,
/// deadline The time by which the transaction must be included to effect
/// the change
/// @return amount0 The amount of token0 accounted to the position's tokens
/// owed
/// @return amount1 The amount of token1 accounted to the position's tokens
/// owed
function decreaseLiquidity(DecreaseLiquidityParams calldata params)
external
payable
returns (uint256 amount0, uint256 amount1);
struct CollectParams {
uint256 tokenId;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
/// @notice Switches the attachment of a token to a different veRam NFT.
/// @param tokenId The identifier of the NFP to switch attachment.
/// @param veRamTokenId The identifier of the veRam NFT to attach.
function switchAttachment(uint256 tokenId, uint256 veRamTokenId) external;
/// @notice Collects up to a maximum amount of fees owed to a specific
/// position to the recipient
/// @param params tokenId The ID of the NFT for which tokens are being
/// collected,
/// recipient The account that should receive the tokens,
/// amount0Max The maximum amount of token0 to collect,
/// amount1Max The maximum amount of token1 to collect
/// @return amount0 The amount of fees collected in token0
/// @return amount1 The amount of fees collected in token1
function collect(CollectParams calldata params)
external
payable
returns (uint256 amount0, uint256 amount1);
/// @notice Burns a token ID, which deletes it from the NFT contract. The
/// token must have 0 liquidity and all tokens
/// must be collected first.
/// @param tokenId The ID of the token that is being burned
function burn(uint256 tokenId) external payable;
function getReward(uint256 tokenId, address[] memory tokens) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another
/// token
/// @param params The parameters necessary for the swap, encoded as
/// `ExactInputSingleParams` in calldata
/// @return amountOut The amount of the received token
function exactInputSingle(ExactInputSingleParams calldata params)
external
payable
returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
/// @notice Swaps `amountIn` of one token for as much as possible of another
/// along the specified path
/// @param params The parameters necessary for the multi-hop swap, encoded
/// as `ExactInputParams` in calldata
/// @return amountOut The amount of the received token
function exactInput(ExactInputParams calldata params)
external
payable
returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
/// @notice Swaps as little as possible of one token for `amountOut` of
/// another token
/// @param params The parameters necessary for the swap, encoded as
/// `ExactOutputSingleParams` in calldata
/// @return amountIn The amount of the input token
function exactOutputSingle(ExactOutputSingleParams calldata params)
external
payable
returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
/// @notice Swaps as little as possible of one token for `amountOut` of
/// another along the specified path (reversed)
/// @param params The parameters necessary for the multi-hop swap, encoded
/// as `ExactOutputParams` in calldata
/// @return amountIn The amount of the input token
function exactOutput(ExactOutputParams calldata params)
external
payable
returns (uint256 amountIn);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { INonfungiblePositionManager } from
"contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
import { ISwapRouter } from
"contracts/interfaces/external/uniswap/ISwapRouter.sol";
import { INftFarmConnector } from "contracts/interfaces/INftFarmConnector.sol";
import { INftLiquidityConnector } from
"contracts/interfaces/INftLiquidityConnector.sol";
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
import {
NftAddLiquidity,
NftRemoveLiquidity,
Pool
} from "contracts/structs/NftLiquidityStructs.sol";
import { Farm } from "contracts/structs/FarmStrategyStructs.sol";
import { NftPosition } from "contracts/structs/NftFarmStrategyStructs.sol";
struct UniswapV3SwapExtraData {
address pool;
bytes path;
}
contract UniswapV3Connector is INftLiquidityConnector, INftFarmConnector {
error InvalidParameters();
function addLiquidity(
NftAddLiquidity memory addLiquidityParams
) external payable override {
if (addLiquidityParams.tokenId == 0) {
_mint(addLiquidityParams);
} else {
_increase_liquidity(addLiquidityParams);
}
}
function removeLiquidity(
NftRemoveLiquidity memory removeLiquidityParams
) external override {
uint128 currentLiquidity;
if (removeLiquidityParams.liquidity == type(uint128).max) {
(,,,,,,, currentLiquidity,,,,) = removeLiquidityParams.nft.positions(
removeLiquidityParams.tokenId
);
removeLiquidityParams.liquidity = currentLiquidity;
}
if (removeLiquidityParams.liquidity == 0) {
revert InvalidParameters();
}
_decrease_liquidity(removeLiquidityParams);
_collect(removeLiquidityParams);
(,,,,,,, currentLiquidity,,,,) =
removeLiquidityParams.nft.positions(removeLiquidityParams.tokenId);
if (currentLiquidity == 0) {
removeLiquidityParams.nft.burn(removeLiquidityParams.tokenId);
}
}
function swapExactTokensForTokens(
SwapParams memory swap
) external payable virtual override {
UniswapV3SwapExtraData memory extraData =
abi.decode(swap.extraData, (UniswapV3SwapExtraData));
IERC20(swap.tokenIn).approve(address(extraData.pool), swap.amountIn);
ISwapRouter(swap.router).exactInput(
ISwapRouter.ExactInputParams({
path: extraData.path,
recipient: address(this),
deadline: block.timestamp + 1,
amountIn: swap.amountIn,
amountOutMinimum: swap.minAmountOut
})
);
}
function depositExistingNft(
NftPosition calldata, // position,
bytes calldata // extraData
) external payable virtual override { }
function withdrawNft(
NftPosition calldata, // position,
bytes calldata // extraData
) external payable virtual override { }
function claim(
NftPosition calldata position,
address[] memory, // rewardTokens
uint128 amount0Max,
uint128 amount1Max,
bytes calldata // extraData
) external payable virtual override {
_claim_fees(position, amount0Max, amount1Max);
}
function _claim_fees(
NftPosition calldata position,
uint128 amount0Max,
uint128 amount1Max
) internal virtual {
if (amount0Max > 0 || amount1Max > 0) {
INonfungiblePositionManager.CollectParams memory params =
INonfungiblePositionManager.CollectParams({
tokenId: position.tokenId,
recipient: address(this),
amount0Max: amount0Max,
amount1Max: amount1Max
});
INonfungiblePositionManager(address(position.nft)).collect(params);
}
}
function _mint(
NftAddLiquidity memory addLiquidityParams
) internal virtual {
addLiquidityParams.nft.mint(
INonfungiblePositionManager.MintParams({
token0: addLiquidityParams.pool.token0,
token1: addLiquidityParams.pool.token1,
fee: addLiquidityParams.pool.fee,
tickLower: addLiquidityParams.tickLower,
tickUpper: addLiquidityParams.tickUpper,
amount0Desired: addLiquidityParams.amount0Desired,
amount1Desired: addLiquidityParams.amount1Desired,
amount0Min: addLiquidityParams.amount0Min,
amount1Min: addLiquidityParams.amount1Min,
recipient: address(this),
deadline: block.timestamp + 1
})
);
}
function _increase_liquidity(
NftAddLiquidity memory addLiquidityParams
) internal {
addLiquidityParams.nft.increaseLiquidity(
INonfungiblePositionManager.IncreaseLiquidityParams({
tokenId: addLiquidityParams.tokenId,
amount0Desired: addLiquidityParams.amount0Desired,
amount1Desired: addLiquidityParams.amount1Desired,
amount0Min: addLiquidityParams.amount0Min,
amount1Min: addLiquidityParams.amount1Min,
deadline: block.timestamp + 1
})
);
}
function _decrease_liquidity(
NftRemoveLiquidity memory removeLiquidityParams
) internal {
removeLiquidityParams.nft.decreaseLiquidity(
INonfungiblePositionManager.DecreaseLiquidityParams({
tokenId: removeLiquidityParams.tokenId,
liquidity: removeLiquidityParams.liquidity,
amount0Min: removeLiquidityParams.amount0Min,
amount1Min: removeLiquidityParams.amount1Min,
deadline: block.timestamp + 1
})
);
}
function _collect(
NftRemoveLiquidity memory removeLiquidityParams
) internal {
removeLiquidityParams.nft.collect(
INonfungiblePositionManager.CollectParams({
tokenId: removeLiquidityParams.tokenId,
recipient: address(this),
amount0Max: removeLiquidityParams.amount0Max,
amount1Max: removeLiquidityParams.amount1Max
})
);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { ZapIn, ZapOut } from "contracts/libraries/ZapLib.sol";
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
struct Farm {
address stakingContract;
uint256 poolIndex;
}
struct DepositParams {
Farm farm;
address[] tokensIn;
uint256[] amountsIn;
ZapIn zap;
bytes extraData;
}
struct WithdrawParams {
bytes extraData;
ZapOut zap;
address[] tokensOut;
}
struct HarvestParams {
SwapParams[] swaps;
bytes extraData;
address[] tokensOut;
}
struct CompoundParams {
Farm claimFarm;
bytes claimExtraData;
address[] rewardTokens;
ZapIn zap;
Farm depositFarm;
bytes depositExtraData;
}
struct SimpleDepositParams {
Farm farm;
address lpToken;
uint256 amountIn;
bytes extraData;
}
struct SimpleHarvestParams {
address[] rewardTokens;
bytes extraData;
}
struct SimpleWithdrawParams {
address lpToken;
uint256 amountOut;
bytes extraData;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { IUniswapV3Pool } from
"contracts/interfaces/external/uniswap/IUniswapV3Pool.sol";
import { INonfungiblePositionManager } from
"contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
import { NftZapIn, NftZapOut } from "contracts/structs/NftZapStructs.sol";
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
import { Farm } from "contracts/structs/FarmStrategyStructs.sol";
struct NftPosition {
Farm farm;
INonfungiblePositionManager nft;
uint256 tokenId;
}
struct NftIncrease {
address[] tokensIn;
uint256[] amountsIn;
NftZapIn zap;
bytes extraData;
}
struct NftDeposit {
Farm farm;
INonfungiblePositionManager nft;
NftIncrease increase;
}
struct NftWithdraw {
NftZapOut zap;
address[] tokensOut;
bytes extraData;
}
struct SimpleNftHarvest {
address[] rewardTokens;
uint128 amount0Max;
uint128 amount1Max;
bytes extraData;
}
struct NftHarvest {
SimpleNftHarvest harvest;
SwapParams[] swaps;
address[] outputTokens;
address[] sweepTokens;
}
struct NftCompound {
SimpleNftHarvest harvest;
NftZapIn zap;
}
struct NftRebalance {
IUniswapV3Pool pool;
NftPosition position;
NftHarvest harvest;
NftWithdraw withdraw;
NftIncrease increase;
}
struct NftMove {
IUniswapV3Pool pool;
NftPosition position;
NftHarvest harvest;
NftWithdraw withdraw;
NftDeposit deposit;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
import {
NftAddLiquidity,
NftRemoveLiquidity
} from "contracts/structs/NftLiquidityStructs.sol";
interface INftLiquidityConnector {
function addLiquidity(
NftAddLiquidity memory addLiquidityParams
) external payable;
function removeLiquidity(
NftRemoveLiquidity memory removeLiquidityParams
) external;
function swapExactTokensForTokens(
SwapParams memory swap
) external payable;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import {
SwapParams,
AddLiquidityParams
} from "contracts/structs/LiquidityStructs.sol";
import { ILiquidityConnector } from
"contracts/interfaces/ILiquidityConnector.sol";
import { ConnectorRegistry } from "contracts/ConnectorRegistry.sol";
import { DelegateModule } from "contracts/modules/DelegateModule.sol";
import { ZapIn, ZapOut } from "contracts/structs/ZapStructs.sol";
import { IZapLib } from "contracts/interfaces/libraries/IZapLib.sol";
import { ISwapLib } from "contracts/interfaces/libraries/ISwapLib.sol";
contract ZapLib is DelegateModule, IZapLib {
error LiquidityAmountError(); // 0x4d0ab6b4
ISwapLib public immutable swapLib;
ConnectorRegistry public immutable connectorRegistry;
constructor(ConnectorRegistry connectorRegistry_, ISwapLib swapLib_) {
connectorRegistry = connectorRegistry_;
swapLib = swapLib_;
}
function zapIn(
ZapIn memory zap
) external payable {
uint256 swapDataLength = zap.swaps.length;
for (uint256 i; i < swapDataLength;) {
_delegateTo(
address(swapLib), abi.encodeCall(ISwapLib.swap, (zap.swaps[i]))
);
unchecked {
i++;
}
}
if (zap.addLiquidityParams.lpToken == address(0)) {
return;
}
bool atLeastOneNonZero = false;
AddLiquidityParams memory addLiquidityParams = zap.addLiquidityParams;
uint256 addLiquidityParamsTokensLength =
addLiquidityParams.tokens.length;
for (uint256 i; i < addLiquidityParamsTokensLength; i++) {
if (addLiquidityParams.tokens[i] == address(0)) {
continue;
}
if (addLiquidityParams.desiredAmounts[i] == 0) {
addLiquidityParams.desiredAmounts[i] = IERC20(
addLiquidityParams.tokens[i]
).balanceOf(address(this));
}
if (addLiquidityParams.desiredAmounts[i] > 0) {
atLeastOneNonZero = true;
// In case there is USDT or similar dust approval, revoke it
SafeTransferLib.safeApprove(
addLiquidityParams.tokens[i], addLiquidityParams.router, 0
);
SafeTransferLib.safeApprove(
addLiquidityParams.tokens[i],
addLiquidityParams.router,
addLiquidityParams.desiredAmounts[i]
);
}
}
if (!atLeastOneNonZero) {
revert LiquidityAmountError();
}
address routerConnector =
connectorRegistry.connectorOf(addLiquidityParams.router);
_delegateTo(
routerConnector,
abi.encodeCall(
ILiquidityConnector.addLiquidity, (addLiquidityParams)
)
);
for (uint256 i; i < addLiquidityParamsTokensLength;) {
if (addLiquidityParams.tokens[i] != address(0)) {
// Revoke any dust approval in case the amount was estimated
SafeTransferLib.safeApprove(
addLiquidityParams.tokens[i], addLiquidityParams.router, 0
);
}
unchecked {
i++;
}
}
}
function zapOut(
ZapOut memory zap
) external {
if (zap.removeLiquidityParams.lpToken != address(0)) {
if (zap.removeLiquidityParams.lpAmountIn > 0) {
SafeTransferLib.safeApprove(
zap.removeLiquidityParams.lpToken,
zap.removeLiquidityParams.router,
zap.removeLiquidityParams.lpAmountIn
);
}
address routerConnector =
connectorRegistry.connectorOf(zap.removeLiquidityParams.router);
_delegateTo(
address(routerConnector),
abi.encodeCall(
ILiquidityConnector.removeLiquidity,
zap.removeLiquidityParams
)
);
}
uint256 swapDataLength = zap.swaps.length;
for (uint256 i; i < swapDataLength;) {
_delegateTo(
address(swapLib), abi.encodeCall(ISwapLib.swap, (zap.swaps[i]))
);
unchecked {
i++;
}
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title Pool state that never changes
/// @notice These parameters are fixed for a pool forever, i.e., the methods
/// will always return the same values
interface IUniswapV3PoolImmutables {
/// @notice The contract that deployed the pool, which must adhere to the
/// IUniswapV3Factory interface
/// @return The contract address
function factory() external view returns (address);
/// @notice The first of the two tokens of the pool, sorted by address
/// @return The token contract address
function token0() external view returns (address);
/// @notice The second of the two tokens of the pool, sorted by address
/// @return The token contract address
function token1() external view returns (address);
/// @notice The pool's fee in hundredths of a bip, i.e. 1e-6
/// @return The fee
function fee() external view returns (uint24);
/// @notice The pool tick spacing
/// @dev Ticks can only be used at multiples of this value, minimum of 1 and
/// always positive
/// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick,
/// i.e., ..., -6, -3, 0, 3, 6, ...
/// This value is an int24 to avoid casting even though it is always
/// positive.
/// @return The tick spacing
function tickSpacing() external view returns (int24);
/// @notice The maximum amount of position liquidity that can use any tick
/// in the range
/// @dev This parameter is enforced per tick to prevent liquidity from
/// overflowing a uint128 at any point, and
/// also prevents out-of-range liquidity from being used to prevent adding
/// in-range liquidity to a pool
/// @return The max amount of liquidity per tick
function maxLiquidityPerTick() external view returns (uint128);
}
/// @title Pool state that can change
/// @notice These methods compose the pool's state, and can change with any
/// frequency including multiple times
/// per transaction
interface IUniswapV3PoolState {
/// @notice The 0th storage slot in the pool stores many values, and is
/// exposed as a single method to save gas
/// when accessed externally.
/// @return sqrtPriceX96 The current price of the pool as a
/// sqrt(token1/token0) Q64.96 value
/// @return tick The current tick of the pool, i.e. according to the last
/// tick transition that was run.
/// This value may not always be equal to
/// SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick
/// boundary.
/// @return observationIndex The index of the last oracle observation that
/// was written,
/// @return observationCardinality The current maximum number of
/// observations stored in the pool,
/// @return observationCardinalityNext The next maximum number of
/// observations, to be updated when the observation.
/// @return feeProtocol The protocol fee for both tokens of the pool.
/// Encoded as two 4 bit values, where the protocol fee of token1 is shifted
/// 4 bits and the protocol fee of token0
/// is the lower 4 bits. Used as the denominator of a fraction of the swap
/// fee, e.g. 4 means 1/4th of the swap fee.
/// unlocked Whether the pool is currently locked to reentrancy
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
/// @notice The fee growth as a Q128.128 fees of token0 collected per unit
/// of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal0X128() external view returns (uint256);
/// @notice The fee growth as a Q128.128 fees of token1 collected per unit
/// of liquidity for the entire life of the pool
/// @dev This value can overflow the uint256
function feeGrowthGlobal1X128() external view returns (uint256);
/// @notice The amounts of token0 and token1 that are owed to the protocol
/// @dev Protocol fees will never exceed uint128 max in either token
function protocolFees()
external
view
returns (uint128 token0, uint128 token1);
/// @notice The currently in range liquidity available to the pool
/// @dev This value has no relationship to the total liquidity across all
/// ticks
/// @return The liquidity at the current price of the pool
function liquidity() external view returns (uint128);
/// @notice Look up information about a specific tick in the pool
/// @param tick The tick to look up
/// @return liquidityGross the total amount of position liquidity that uses
/// the pool either as tick lower or
/// tick upper
/// @return liquidityNet how much liquidity changes when the pool price
/// crosses the tick,
/// @return feeGrowthOutside0X128 the fee growth on the other side of the
/// tick from the current tick in token0,
/// @return feeGrowthOutside1X128 the fee growth on the other side of the
/// tick from the current tick in token1,
/// @return tickCumulativeOutside the cumulative tick value on the other
/// side of the tick from the current tick
/// @return secondsPerLiquidityOutsideX128 the seconds spent per liquidity
/// on the other side of the tick from the current tick,
/// @return secondsOutside the seconds spent on the other side of the tick
/// from the current tick,
/// @return initialized Set to true if the tick is initialized, i.e.
/// liquidityGross is greater than 0, otherwise equal to false.
/// Outside values can only be used if the tick is initialized, i.e. if
/// liquidityGross is greater than 0.
/// In addition, these values are only relative and must be used only in
/// comparison to previous snapshots for
/// a specific position.
function ticks(int24 tick)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
uint256 feeGrowthOutside0X128,
uint256 feeGrowthOutside1X128,
int56 tickCumulativeOutside,
uint160 secondsPerLiquidityOutsideX128,
uint32 secondsOutside,
bool initialized
);
/// @notice Returns 256 packed tick initialized boolean values. See
/// TickBitmap for more information
function tickBitmap(int16 wordPosition) external view returns (uint256);
/// @notice Returns the information about a position by the position's key
/// @param key The position's key is a hash of a preimage composed by the
/// owner, tickLower and tickUpper
/// @return liquidity The amount of liquidity in the position,
/// @return feeGrowthInside0LastX128 fee growth of token0 inside the tick
/// range as of the last mint/burn/poke,
/// @return feeGrowthInside1LastX128 fee growth of token1 inside the tick
/// range as of the last mint/burn/poke,
/// @return tokensOwed0 the computed amount of token0 owed to the position
/// as of the last mint/burn/poke,
/// @return tokensOwed1 the computed amount of token1 owed to the position
/// as of the last mint/burn/poke
function positions(bytes32 key)
external
view
returns (
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
/// @notice Returns data about a specific observation index
/// @param index The element of the observations array to fetch
/// @dev You most likely want to use #observe() instead of this method to
/// get an observation as of some amount of time
/// ago, rather than at a specific index in the array.
/// @return blockTimestamp The timestamp of the observation,
/// @return tickCumulative the tick multiplied by seconds elapsed for the
/// life of the pool as of the observation timestamp,
/// @return secondsPerLiquidityCumulativeX128 the seconds per in range
/// liquidity for the life of the pool as of the observation timestamp,
/// @return initialized whether the observation has been initialized and the
/// values are safe to use
function observations(uint256 index)
external
view
returns (
uint32 blockTimestamp,
int56 tickCumulative,
uint160 secondsPerLiquidityCumulativeX128,
bool initialized
);
}
interface IUniswapV3Pool is IUniswapV3PoolImmutables, IUniswapV3PoolState {
function flash(
address recipient,
uint256 amount0,
uint256 amount1,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
import {
NftAddLiquidity,
NftRemoveLiquidity
} from "contracts/structs/NftLiquidityStructs.sol";
struct NftZapIn {
SwapParams[] swaps;
NftAddLiquidity addLiquidityParams;
}
struct NftZapOut {
NftRemoveLiquidity removeLiquidityParams;
SwapParams[] swaps;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @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);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error ETHTransferFailed();
error TransferFromFailed();
error TransferFailed();
error ApproveFailed();
/*//////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Transfer the ETH and store if it succeeded or not.
success := call(gas(), to, amount, 0, 0, 0, 0)
}
if (!success) revert ETHTransferFailed();
}
/*//////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
address token,
address from,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument.
mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
if (!success) revert TransferFromFailed();
}
function safeTransfer(
address token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
if (!success) revert TransferFailed();
}
function safeApprove(
address token,
address to,
uint256 amount
) internal {
bool success;
/// @solidity memory-safe-assembly
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.
success := and(
// Set success to whether the call reverted, if not we check it either
// returned exactly 1 (can't just be non-zero data), or had no return data.
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
// Counterintuitively, this call must be positioned second to the or() call in the
// surrounding and() call or else returndatasize() will be zero during the computation.
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
if (!success) revert ApproveFailed();
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {
AddLiquidityParams,
RemoveLiquidityParams,
SwapParams,
GetAmountOutParams
} from "contracts/structs/LiquidityStructs.sol";
interface ILiquidityConnector {
function addLiquidity(
AddLiquidityParams memory addLiquidityParams
) external payable;
function removeLiquidity(
RemoveLiquidityParams memory removeLiquidityParams
) external;
function swapExactTokensForTokens(
SwapParams memory swap
) external payable;
function getAmountOut(
GetAmountOutParams memory getAmountOutParams
) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { Admin } from "contracts/base/Admin.sol";
import { TimelockAdmin } from "contracts/base/TimelockAdmin.sol";
error ConnectorNotRegistered(address target);
interface ICustomConnectorRegistry {
function connectorOf(address target) external view returns (address);
}
contract ConnectorRegistry is Admin, TimelockAdmin {
event ConnectorChanged(address target, address connector);
event CustomRegistryAdded(address registry);
event CustomRegistryRemoved(address registry);
error ConnectorAlreadySet(address target);
error ConnectorNotSet(address target);
ICustomConnectorRegistry[] public customRegistries;
mapping(ICustomConnectorRegistry => bool) public isCustomRegistry;
mapping(address target => address connector) private connectors_;
constructor(
address admin_,
address timelockAdmin_
) Admin(admin_) TimelockAdmin(timelockAdmin_) { }
/// @notice Update connector addresses for a batch of targets.
/// @dev Controls which connector contracts are used for the specified
/// targets.
/// @custom:access Restricted to protocol admin.
function setConnectors(
address[] calldata targets,
address[] calldata connectors
) external onlyAdmin {
for (uint256 i; i != targets.length;) {
if (connectors_[targets[i]] != address(0)) {
revert ConnectorAlreadySet(targets[i]);
}
connectors_[targets[i]] = connectors[i];
emit ConnectorChanged(targets[i], connectors[i]);
unchecked {
++i;
}
}
}
function updateConnectors(
address[] calldata targets,
address[] calldata connectors
) external onlyTimelockAdmin {
for (uint256 i; i != targets.length;) {
if (connectors_[targets[i]] == address(0)) {
revert ConnectorNotSet(targets[i]);
}
connectors_[targets[i]] = connectors[i];
emit ConnectorChanged(targets[i], connectors[i]);
unchecked {
++i;
}
}
}
/// @notice Append an address to the custom registries list.
/// @custom:access Restricted to protocol admin.
function addCustomRegistry(ICustomConnectorRegistry registry)
external
onlyAdmin
{
customRegistries.push(registry);
isCustomRegistry[registry] = true;
emit CustomRegistryAdded(address(registry));
}
/// @notice Replace an address in the custom registries list.
/// @custom:access Restricted to protocol admin.
function updateCustomRegistry(
uint256 index,
ICustomConnectorRegistry newRegistry
) external onlyTimelockAdmin {
address oldRegistry = address(customRegistries[index]);
isCustomRegistry[customRegistries[index]] = false;
emit CustomRegistryRemoved(oldRegistry);
customRegistries[index] = newRegistry;
isCustomRegistry[newRegistry] = true;
if (address(newRegistry) != address(0)) {
emit CustomRegistryAdded(address(newRegistry));
}
}
function connectorOf(address target) external view returns (address) {
address connector = connectors_[target];
if (connector != address(0)) {
return connector;
}
uint256 length = customRegistries.length;
for (uint256 i; i != length;) {
if (address(customRegistries[i]) != address(0)) {
try customRegistries[i].connectorOf(target) returns (
address _connector
) {
if (_connector != address(0)) {
return _connector;
}
} catch {
// Ignore
}
}
unchecked {
++i;
}
}
revert ConnectorNotRegistered(target);
}
function hasConnector(address target) external view returns (bool) {
if (connectors_[target] != address(0)) {
return true;
}
uint256 length = customRegistries.length;
for (uint256 i; i != length;) {
if (address(customRegistries[i]) != address(0)) {
try customRegistries[i].connectorOf(target) returns (
address _connector
) {
if (_connector != address(0)) {
return true;
}
} catch {
// Ignore
}
unchecked {
++i;
}
}
}
return false;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract DelegateModule {
function _delegateTo(
address to,
bytes memory data
) internal returns (bytes memory) {
(bool success, bytes memory result) = to.delegatecall(data);
if (!success) {
if (result.length == 0) revert();
assembly {
revert(add(32, result), mload(result))
}
}
return result;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {
SwapParams,
AddLiquidityParams,
RemoveLiquidityParams
} from "contracts/structs/LiquidityStructs.sol";
struct ZapIn {
SwapParams[] swaps;
AddLiquidityParams addLiquidityParams;
}
struct ZapOut {
RemoveLiquidityParams removeLiquidityParams;
SwapParams[] swaps;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ZapIn, ZapOut } from "contracts/structs/ZapStructs.sol";
interface IZapLib {
function zapIn(
ZapIn memory zap
) external payable;
function zapOut(
ZapOut memory zap
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
interface ISwapLib {
function swap(
SwapParams memory swap
) external payable;
function swapMultiple(
SwapParams[] memory swaps
) external;
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/// @title Admin contract
/// @author vfat.tools
/// @notice Provides an administration mechanism allowing restricted functions
abstract contract Admin {
/// ERRORS ///
/// @notice Thrown when the caller is not the admin
error NotAdminError(); //0xb5c42b3b
/// EVENTS ///
/// @notice Emitted when a new admin is set
/// @param oldAdmin Address of the old admin
/// @param newAdmin Address of the new admin
event AdminSet(address oldAdmin, address newAdmin);
/// STORAGE ///
/// @notice Address of the current admin
address public admin;
/// MODIFIERS ///
/// @dev Restricts a function to the admin
modifier onlyAdmin() {
if (msg.sender != admin) revert NotAdminError();
_;
}
/// WRITE FUNCTIONS ///
/// @param admin_ Address of the admin
constructor(address admin_) {
emit AdminSet(admin, admin_);
admin = admin_;
}
/// @notice Sets a new admin
/// @param newAdmin Address of the new admin
/// @custom:access Restricted to protocol admin.
function setAdmin(address newAdmin) external onlyAdmin {
emit AdminSet(admin, newAdmin);
admin = newAdmin;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/// @title TimelockAdmin contract
/// @author vfat.tools
/// @notice Provides an timelockAdministration mechanism allowing restricted
/// functions
abstract contract TimelockAdmin {
/// ERRORS ///
/// @notice Thrown when the caller is not the timelockAdmin
error NotTimelockAdminError();
/// EVENTS ///
/// @notice Emitted when a new timelockAdmin is set
/// @param oldTimelockAdmin Address of the old timelockAdmin
/// @param newTimelockAdmin Address of the new timelockAdmin
event TimelockAdminSet(address oldTimelockAdmin, address newTimelockAdmin);
/// STORAGE ///
/// @notice Address of the current timelockAdmin
address public timelockAdmin;
/// MODIFIERS ///
/// @dev Restricts a function to the timelockAdmin
modifier onlyTimelockAdmin() {
if (msg.sender != timelockAdmin) revert NotTimelockAdminError();
_;
}
/// WRITE FUNCTIONS ///
/// @param timelockAdmin_ Address of the timelockAdmin
constructor(address timelockAdmin_) {
emit TimelockAdminSet(timelockAdmin, timelockAdmin_);
timelockAdmin = timelockAdmin_;
}
/// @notice Sets a new timelockAdmin
/// @dev Can only be called by the current timelockAdmin
/// @param newTimelockAdmin Address of the new timelockAdmin
function setTimelockAdmin(address newTimelockAdmin)
external
onlyTimelockAdmin
{
emit TimelockAdminSet(timelockAdmin, newTimelockAdmin);
timelockAdmin = newTimelockAdmin;
}
}{
"remappings": [
"solmate/=lib/solmate/src/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"@uniswap/v3-periphery/=lib/v3-periphery/",
"@uniswap/v3-core/=lib/v3-core/",
"@morpho-blue/=lib/morpho-blue/src/",
"ds-test/=lib/solmate/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"morpho-blue/=lib/morpho-blue/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"InvalidParameters","type":"error"},{"inputs":[{"components":[{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"components":[{"internalType":"address","name":"token0","type":"address"},{"internalType":"address","name":"token1","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"}],"internalType":"struct Pool","name":"pool","type":"tuple"},{"internalType":"int24","name":"tickLower","type":"int24"},{"internalType":"int24","name":"tickUpper","type":"int24"},{"internalType":"uint256","name":"amount0Desired","type":"uint256"},{"internalType":"uint256","name":"amount1Desired","type":"uint256"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct NftAddLiquidity","name":"addLiquidityParams","type":"tuple"}],"name":"addLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct NftPosition","name":"position","type":"tuple"},{"internalType":"address[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint128","name":"amount0Max","type":"uint128"},{"internalType":"uint128","name":"amount1Max","type":"uint128"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"claim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct NftPosition","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"depositExistingNft","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint128","name":"liquidity","type":"uint128"},{"internalType":"uint256","name":"amount0Min","type":"uint256"},{"internalType":"uint256","name":"amount1Min","type":"uint256"},{"internalType":"uint128","name":"amount0Max","type":"uint128"},{"internalType":"uint128","name":"amount1Max","type":"uint128"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct NftRemoveLiquidity","name":"removeLiquidityParams","type":"tuple"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct SwapParams","name":"swap","type":"tuple"}],"name":"swapExactTokensForTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"stakingContract","type":"address"},{"internalType":"uint256","name":"poolIndex","type":"uint256"}],"internalType":"struct Farm","name":"farm","type":"tuple"},{"internalType":"contract INonfungiblePositionManager","name":"nft","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct NftPosition","name":"","type":"tuple"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"withdrawNft","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50611455806100206000396000f3fe6080604052600436106100555760003560e01c806304caab471461005a5780632847ccf21461006f5780636f4621e314610082578063cce9480114610095578063ff781feb146100b5578063ff7b92661461006f575b600080fd5b61006d610068366004610b07565b6100c8565b005b61006d61007d366004610c51565b505050565b61006d610090366004610cc4565b6100e9565b3480156100a157600080fd5b5061006d6100b0366004610dd6565b61023a565b61006d6100c3366004610ea5565b61042f565b80602001516000036100e0576100dd81610585565b50565b6100dd816106a8565b6100f96060870160408801610f4d565b6001600160a01b031663f5f8d3658760600135876040518363ffffffff1660e01b815260040161012a929190610f71565b600060405180830381600087803b15801561014457600080fd5b505af1158015610158573d6000803e3d6000fd5b505050506000846001600160801b0316118061017d57506000836001600160801b0316115b1561023257604080516080810182526060808901803583523060208401526001600160801b038089168486015287169183019190915290916101c191908901610f4d565b6001600160a01b031663fc6f7865826040518263ffffffff1660e01b81526004016101ec9190610fc8565b60408051808303816000875af115801561020a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022e9190611012565b5050505b505050505050565b60006001600160801b03801682604001516001600160801b0316036102ee578151602083015160405163133f757160e31b81526001600160a01b03909216916399fbab889161028f9160040190815260200190565b61018060405180830381865afa1580156102ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d19190611062565b5050506001600160801b03821660408c0152509750505050505050505b81604001516001600160801b031660000361031c57604051630e52390960e41b815260040160405180910390fd5b6103258261079c565b61032e8261088d565b8151602083015160405163133f757160e31b81526001600160a01b03909216916399fbab88916103649160040190815260200190565b61018060405180830381865afa158015610382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a69190611062565b50929a5050506001600160801b038916600003975061042b96505050505050505781516020830151604051630852cd8d60e31b81526001600160a01b03909216916342966c68916103fd9160040190815260200190565b600060405180830381600087803b15801561041757600080fd5b505af1158015610232573d6000803e3d6000fd5b5050565b600081608001518060200190518101906104499190611167565b60608301518151602085015160405163095ea7b360e01b81526001600160a01b0392831660048201526024810191909152929350169063095ea7b3906044016020604051808303816000875af11580156104a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cb9190611224565b506040805160a0810182526020808401518252309082015260009181016104f3426001611246565b8152602001846020015181526020018460400151815250905082600001516001600160a01b031663c04b8d59826040518263ffffffff1660e01b815260040161053c9190611267565b6020604051808303816000875af115801561055b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057f91906112d6565b50505050565b60006040518061016001604052808360400151600001516001600160a01b031681526020018360400151602001516001600160a01b0316815260200183604001516040015162ffffff168152602001836060015160020b8152602001836080015160020b81526020018360a0015181526020018360c0015181526020018360e0015181526020018361010001518152602001306001600160a01b031681526020014260016106339190611246565b90528251604051634418b22b60e11b81529192506001600160a01b0316906388316456906106659084906004016112ef565b6080604051808303816000875af1158015610684573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023291906113b3565b80600001516001600160a01b031663219f5d176040518060c00160405280846020015181526020018460a0015181526020018460c0015181526020018460e00151815260200184610100015181526020014260016107069190611246565b9052604080516001600160e01b031960e085901b1681528251600482015260208301516024820152908201516044820152606082015160648201526080820151608482015260a09091015160a482015260c4016060604051808303816000875af1158015610778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057f91906113f1565b80600001516001600160a01b0316630c49ccbe6040518060a001604052808460200151815260200184604001516001600160801b0316815260200184606001518152602001846080015181526020014260016107f89190611246565b9052604080516001600160e01b031960e085901b1681528251600482015260208301516001600160801b0316602482015290820151604482015260608201516064820152608090910151608482015260a4015b60408051808303816000875af1158015610869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061007d9190611012565b8051604080516080810182526020808501518252309082015260a08401516001600160801b039081168284015260c0850151166060820152905163fc6f786560e01b81526001600160a01b039092169163fc6f78659161084b91600401610fc8565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b0381118282101715610928576109286108ef565b60405290565b60405161010081016001600160401b0381118282101715610928576109286108ef565b60405160a081016001600160401b0381118282101715610928576109286108ef565b604080519081016001600160401b0381118282101715610928576109286108ef565b604051601f8201601f191681016001600160401b03811182821017156109bd576109bd6108ef565b604052919050565b6001600160a01b03811681146100dd57600080fd5b80356109e5816109c5565b919050565b62ffffff811681146100dd57600080fd5b600060608284031215610a0d57600080fd5b604051606081018181106001600160401b0382111715610a2f57610a2f6108ef565b6040529050808235610a40816109c5565b81526020830135610a50816109c5565b60208201526040830135610a63816109ea565b6040919091015292915050565b8060020b81146100dd57600080fd5b80356109e581610a70565b60006001600160401b03821115610aa357610aa36108ef565b50601f01601f191660200190565b600082601f830112610ac257600080fd5b8135610ad5610ad082610a8a565b610995565b818152846020838601011115610aea57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215610b1957600080fd5b81356001600160401b0380821115610b3057600080fd5b908301906101808286031215610b4557600080fd5b610b4d610905565b610b56836109da565b815260208301356020820152610b6f86604085016109fb565b6040820152610b8060a08401610a7f565b6060820152610b9160c08401610a7f565b608082015260e083013560a08201526101008084013560c08301526101208085013560e084015261014085013582840152610160850135915083821115610bd757600080fd5b610be388838701610ab1565b908301525095945050505050565b600060808284031215610c0357600080fd5b50919050565b60008083601f840112610c1b57600080fd5b5081356001600160401b03811115610c3257600080fd5b602083019150836020828501011115610c4a57600080fd5b9250929050565b600080600060a08486031215610c6657600080fd5b610c708585610bf1565b925060808401356001600160401b03811115610c8b57600080fd5b610c9786828701610c09565b9497909650939450505050565b6001600160801b03811681146100dd57600080fd5b80356109e581610ca4565b6000806000806000806101008789031215610cde57600080fd5b610ce88888610bf1565b955060808701356001600160401b0380821115610d0457600080fd5b818901915089601f830112610d1857600080fd5b8135602082821115610d2c57610d2c6108ef565b8160051b610d3b828201610995565b928352848101820192828101908e851115610d5557600080fd5b958301955b84871015610d7f5786359250610d6f836109c5565b8282529583019590830190610d5a565b809b505050505050610d9360a08a01610cb9565b9550610da160c08a01610cb9565b945060e0890135915080821115610db757600080fd5b50610dc489828a01610c09565b979a9699509497509295939492505050565b600060208284031215610de857600080fd5b81356001600160401b0380821115610dff57600080fd5b908301906101008286031215610e1457600080fd5b610e1c61092e565b610e25836109da565b815260208301356020820152610e3d60408401610cb9565b60408201526060830135606082015260808301356080820152610e6260a08401610cb9565b60a0820152610e7360c08401610cb9565b60c082015260e083013582811115610e8a57600080fd5b610e9687828601610ab1565b60e08301525095945050505050565b600060208284031215610eb757600080fd5b81356001600160401b0380821115610ece57600080fd5b9083019060a08286031215610ee257600080fd5b610eea610951565b8235610ef5816109c5565b8082525060208301356020820152604083013560408201526060830135610f1b816109c5565b6060820152608083013582811115610f3257600080fd5b610f3e87828601610ab1565b60808301525095945050505050565b600060208284031215610f5f57600080fd5b8135610f6a816109c5565b9392505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b81811015610fbb5784516001600160a01b031683529383019391830191600101610f96565b5090979650505050505050565b6080810161100c8284805182526020808201516001600160a01b0316908301526040808201516001600160801b039081169184019190915260609182015116910152565b92915050565b6000806040838503121561102557600080fd5b505080516020909101519092909150565b80516109e5816109c5565b80516109e5816109ea565b80516109e581610a70565b80516109e581610ca4565b6000806000806000806000806000806000806101808d8f03121561108557600080fd5b8c516bffffffffffffffffffffffff811681146110a157600080fd5b9b506110af60208e01611036565b9a506110bd60408e01611036565b99506110cb60608e01611036565b98506110d960808e01611041565b97506110e760a08e0161104c565b96506110f560c08e0161104c565b955061110360e08e01611057565b94506101008d015193506101208d015192506111226101408e01611057565b91506111316101608e01611057565b90509295989b509295989b509295989b565b60005b8381101561115e578181015183820152602001611146565b50506000910152565b6000602080838503121561117a57600080fd5b82516001600160401b038082111561119157600080fd5b90840190604082870312156111a557600080fd5b6111ad610973565b82516111b8816109c5565b815282840151828111156111cb57600080fd5b80840193505086601f8401126111e057600080fd5b825191506111f0610ad083610a8a565b828152878584860101111561120457600080fd5b61121383868301878701611143565b938101939093525090949350505050565b60006020828403121561123657600080fd5b81518015158114610f6a57600080fd5b8082018082111561100c57634e487b7160e01b600052601160045260246000fd5b602081526000825160a0602084015280518060c085015261128f8160e0860160208501611143565b60018060a01b0360208601511660408501526040850151606085015260608501516080850152608085015160a085015260e0601f19601f8301168501019250505092915050565b6000602082840312156112e857600080fd5b5051919050565b81516001600160a01b031681526101608101602083015161131b60208401826001600160a01b03169052565b506040830151611332604084018262ffffff169052565b506060830151611347606084018260020b9052565b50608083015161135c608084018260020b9052565b5060a083015160a083015260c083015160c083015260e083015160e0830152610100808401518184015250610120808401516113a2828501826001600160a01b03169052565b505061014092830151919092015290565b600080600080608085870312156113c957600080fd5b8451935060208501516113db81610ca4565b6040860151606090960151949790965092505050565b60008060006060848603121561140657600080fd5b835192506020840151915060408401519050925092509256fea26469706673582212201eb37780a0683b015c273a0832f1bad1ec38ea655fb9f916af9b086555d8535d64736f6c63430008130033
Deployed Bytecode
0x6080604052600436106100555760003560e01c806304caab471461005a5780632847ccf21461006f5780636f4621e314610082578063cce9480114610095578063ff781feb146100b5578063ff7b92661461006f575b600080fd5b61006d610068366004610b07565b6100c8565b005b61006d61007d366004610c51565b505050565b61006d610090366004610cc4565b6100e9565b3480156100a157600080fd5b5061006d6100b0366004610dd6565b61023a565b61006d6100c3366004610ea5565b61042f565b80602001516000036100e0576100dd81610585565b50565b6100dd816106a8565b6100f96060870160408801610f4d565b6001600160a01b031663f5f8d3658760600135876040518363ffffffff1660e01b815260040161012a929190610f71565b600060405180830381600087803b15801561014457600080fd5b505af1158015610158573d6000803e3d6000fd5b505050506000846001600160801b0316118061017d57506000836001600160801b0316115b1561023257604080516080810182526060808901803583523060208401526001600160801b038089168486015287169183019190915290916101c191908901610f4d565b6001600160a01b031663fc6f7865826040518263ffffffff1660e01b81526004016101ec9190610fc8565b60408051808303816000875af115801561020a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061022e9190611012565b5050505b505050505050565b60006001600160801b03801682604001516001600160801b0316036102ee578151602083015160405163133f757160e31b81526001600160a01b03909216916399fbab889161028f9160040190815260200190565b61018060405180830381865afa1580156102ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d19190611062565b5050506001600160801b03821660408c0152509750505050505050505b81604001516001600160801b031660000361031c57604051630e52390960e41b815260040160405180910390fd5b6103258261079c565b61032e8261088d565b8151602083015160405163133f757160e31b81526001600160a01b03909216916399fbab88916103649160040190815260200190565b61018060405180830381865afa158015610382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a69190611062565b50929a5050506001600160801b038916600003975061042b96505050505050505781516020830151604051630852cd8d60e31b81526001600160a01b03909216916342966c68916103fd9160040190815260200190565b600060405180830381600087803b15801561041757600080fd5b505af1158015610232573d6000803e3d6000fd5b5050565b600081608001518060200190518101906104499190611167565b60608301518151602085015160405163095ea7b360e01b81526001600160a01b0392831660048201526024810191909152929350169063095ea7b3906044016020604051808303816000875af11580156104a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cb9190611224565b506040805160a0810182526020808401518252309082015260009181016104f3426001611246565b8152602001846020015181526020018460400151815250905082600001516001600160a01b031663c04b8d59826040518263ffffffff1660e01b815260040161053c9190611267565b6020604051808303816000875af115801561055b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057f91906112d6565b50505050565b60006040518061016001604052808360400151600001516001600160a01b031681526020018360400151602001516001600160a01b0316815260200183604001516040015162ffffff168152602001836060015160020b8152602001836080015160020b81526020018360a0015181526020018360c0015181526020018360e0015181526020018361010001518152602001306001600160a01b031681526020014260016106339190611246565b90528251604051634418b22b60e11b81529192506001600160a01b0316906388316456906106659084906004016112ef565b6080604051808303816000875af1158015610684573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061023291906113b3565b80600001516001600160a01b031663219f5d176040518060c00160405280846020015181526020018460a0015181526020018460c0015181526020018460e00151815260200184610100015181526020014260016107069190611246565b9052604080516001600160e01b031960e085901b1681528251600482015260208301516024820152908201516044820152606082015160648201526080820151608482015260a09091015160a482015260c4016060604051808303816000875af1158015610778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061057f91906113f1565b80600001516001600160a01b0316630c49ccbe6040518060a001604052808460200151815260200184604001516001600160801b0316815260200184606001518152602001846080015181526020014260016107f89190611246565b9052604080516001600160e01b031960e085901b1681528251600482015260208301516001600160801b0316602482015290820151604482015260608201516064820152608090910151608482015260a4015b60408051808303816000875af1158015610869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061007d9190611012565b8051604080516080810182526020808501518252309082015260a08401516001600160801b039081168284015260c0850151166060820152905163fc6f786560e01b81526001600160a01b039092169163fc6f78659161084b91600401610fc8565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b0381118282101715610928576109286108ef565b60405290565b60405161010081016001600160401b0381118282101715610928576109286108ef565b60405160a081016001600160401b0381118282101715610928576109286108ef565b604080519081016001600160401b0381118282101715610928576109286108ef565b604051601f8201601f191681016001600160401b03811182821017156109bd576109bd6108ef565b604052919050565b6001600160a01b03811681146100dd57600080fd5b80356109e5816109c5565b919050565b62ffffff811681146100dd57600080fd5b600060608284031215610a0d57600080fd5b604051606081018181106001600160401b0382111715610a2f57610a2f6108ef565b6040529050808235610a40816109c5565b81526020830135610a50816109c5565b60208201526040830135610a63816109ea565b6040919091015292915050565b8060020b81146100dd57600080fd5b80356109e581610a70565b60006001600160401b03821115610aa357610aa36108ef565b50601f01601f191660200190565b600082601f830112610ac257600080fd5b8135610ad5610ad082610a8a565b610995565b818152846020838601011115610aea57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208284031215610b1957600080fd5b81356001600160401b0380821115610b3057600080fd5b908301906101808286031215610b4557600080fd5b610b4d610905565b610b56836109da565b815260208301356020820152610b6f86604085016109fb565b6040820152610b8060a08401610a7f565b6060820152610b9160c08401610a7f565b608082015260e083013560a08201526101008084013560c08301526101208085013560e084015261014085013582840152610160850135915083821115610bd757600080fd5b610be388838701610ab1565b908301525095945050505050565b600060808284031215610c0357600080fd5b50919050565b60008083601f840112610c1b57600080fd5b5081356001600160401b03811115610c3257600080fd5b602083019150836020828501011115610c4a57600080fd5b9250929050565b600080600060a08486031215610c6657600080fd5b610c708585610bf1565b925060808401356001600160401b03811115610c8b57600080fd5b610c9786828701610c09565b9497909650939450505050565b6001600160801b03811681146100dd57600080fd5b80356109e581610ca4565b6000806000806000806101008789031215610cde57600080fd5b610ce88888610bf1565b955060808701356001600160401b0380821115610d0457600080fd5b818901915089601f830112610d1857600080fd5b8135602082821115610d2c57610d2c6108ef565b8160051b610d3b828201610995565b928352848101820192828101908e851115610d5557600080fd5b958301955b84871015610d7f5786359250610d6f836109c5565b8282529583019590830190610d5a565b809b505050505050610d9360a08a01610cb9565b9550610da160c08a01610cb9565b945060e0890135915080821115610db757600080fd5b50610dc489828a01610c09565b979a9699509497509295939492505050565b600060208284031215610de857600080fd5b81356001600160401b0380821115610dff57600080fd5b908301906101008286031215610e1457600080fd5b610e1c61092e565b610e25836109da565b815260208301356020820152610e3d60408401610cb9565b60408201526060830135606082015260808301356080820152610e6260a08401610cb9565b60a0820152610e7360c08401610cb9565b60c082015260e083013582811115610e8a57600080fd5b610e9687828601610ab1565b60e08301525095945050505050565b600060208284031215610eb757600080fd5b81356001600160401b0380821115610ece57600080fd5b9083019060a08286031215610ee257600080fd5b610eea610951565b8235610ef5816109c5565b8082525060208301356020820152604083013560408201526060830135610f1b816109c5565b6060820152608083013582811115610f3257600080fd5b610f3e87828601610ab1565b60808301525095945050505050565b600060208284031215610f5f57600080fd5b8135610f6a816109c5565b9392505050565b6000604082018483526020604081850152818551808452606086019150828701935060005b81811015610fbb5784516001600160a01b031683529383019391830191600101610f96565b5090979650505050505050565b6080810161100c8284805182526020808201516001600160a01b0316908301526040808201516001600160801b039081169184019190915260609182015116910152565b92915050565b6000806040838503121561102557600080fd5b505080516020909101519092909150565b80516109e5816109c5565b80516109e5816109ea565b80516109e581610a70565b80516109e581610ca4565b6000806000806000806000806000806000806101808d8f03121561108557600080fd5b8c516bffffffffffffffffffffffff811681146110a157600080fd5b9b506110af60208e01611036565b9a506110bd60408e01611036565b99506110cb60608e01611036565b98506110d960808e01611041565b97506110e760a08e0161104c565b96506110f560c08e0161104c565b955061110360e08e01611057565b94506101008d015193506101208d015192506111226101408e01611057565b91506111316101608e01611057565b90509295989b509295989b509295989b565b60005b8381101561115e578181015183820152602001611146565b50506000910152565b6000602080838503121561117a57600080fd5b82516001600160401b038082111561119157600080fd5b90840190604082870312156111a557600080fd5b6111ad610973565b82516111b8816109c5565b815282840151828111156111cb57600080fd5b80840193505086601f8401126111e057600080fd5b825191506111f0610ad083610a8a565b828152878584860101111561120457600080fd5b61121383868301878701611143565b938101939093525090949350505050565b60006020828403121561123657600080fd5b81518015158114610f6a57600080fd5b8082018082111561100c57634e487b7160e01b600052601160045260246000fd5b602081526000825160a0602084015280518060c085015261128f8160e0860160208501611143565b60018060a01b0360208601511660408501526040850151606085015260608501516080850152608085015160a085015260e0601f19601f8301168501019250505092915050565b6000602082840312156112e857600080fd5b5051919050565b81516001600160a01b031681526101608101602083015161131b60208401826001600160a01b03169052565b506040830151611332604084018262ffffff169052565b506060830151611347606084018260020b9052565b50608083015161135c608084018260020b9052565b5060a083015160a083015260c083015160c083015260e083015160e0830152610100808401518184015250610120808401516113a2828501826001600160a01b03169052565b505061014092830151919092015290565b600080600080608085870312156113c957600080fd5b8451935060208501516113db81610ca4565b6040860151606090960151949790965092505050565b60008060006060848603121561140657600080fd5b835192506020840151915060408401519050925092509256fea26469706673582212201eb37780a0683b015c273a0832f1bad1ec38ea655fb9f916af9b086555d8535d64736f6c63430008130033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.