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:
NuriGaugeRegistry
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.17;
import { ICustomConnectorRegistry } from "contracts/ConnectorRegistry.sol";
import { NuriGaugeConnector } from
"contracts/connectors/nuri/NuriGaugeConnector.sol";
import { NuriV3Connector } from "contracts/connectors/nuri/NuriV3Connector.sol";
import { IGaugeRegistryVoter } from "contracts/connectors/GaugeRegistry.sol";
import { IRamsesV2Gauge } from
"contracts/interfaces/external/ramses/IRamsesV2Gauge.sol";
interface INuriPairFactory {
function isPair(
address pair
) external view returns (bool);
}
contract NuriGaugeRegistry is ICustomConnectorRegistry {
IGaugeRegistryVoter public immutable voter;
NuriGaugeConnector public immutable nuriGaugeConnector;
INuriPairFactory public immutable nuriPairFactory;
NuriV3Connector public immutable nuriV3Connector;
address public immutable nuriCLGaugeFactory;
constructor(
IGaugeRegistryVoter voter_,
NuriGaugeConnector nuriGaugeConnector_,
INuriPairFactory nuriPairFactory_,
NuriV3Connector nuriV3Connector_,
address nuriCLGaugeFactory_
) {
voter = voter_;
nuriGaugeConnector = nuriGaugeConnector_;
nuriPairFactory = nuriPairFactory_;
nuriV3Connector = nuriV3Connector_;
nuriCLGaugeFactory = nuriCLGaugeFactory_;
}
function connectorOf(
address target
) external view override returns (address) {
if (voter.isGauge(target)) {
if (nuriPairFactory.isPair(voter.poolForGauge(target))) {
return address(nuriGaugeConnector);
}
address gaugeFactory = IRamsesV2Gauge(target).gaugeFactory();
if (gaugeFactory == nuriCLGaugeFactory) {
return address(nuriV3Connector);
}
}
return address(0);
}
}// 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);
error CustomRegistryAlreadyRegistered();
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);
error ArrayLengthMismatch();
ICustomConnectorRegistry[] public customRegistries;
mapping(address target => address connector) private connectors_;
constructor(
address admin_,
address timelockAdmin_
) Admin(admin_) TimelockAdmin(timelockAdmin_) { }
/// Admin functions
/// @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 {
if (targets.length != connectors.length) {
revert ArrayLengthMismatch();
}
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 {
if (targets.length != connectors.length) {
revert ArrayLengthMismatch();
}
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 {
if (isCustomRegistry(registry)) {
revert CustomRegistryAlreadyRegistered();
}
customRegistries.push(registry);
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 {
ICustomConnectorRegistry oldRegistry = customRegistries[index];
emit CustomRegistryRemoved(address(oldRegistry));
customRegistries[index] = newRegistry;
if (address(newRegistry) != address(0)) {
emit CustomRegistryAdded(address(newRegistry));
}
}
/// Public functions
function connectorOf(
address target
) external view returns (address) {
address connector = _getConnector(target);
if (connector != address(0)) {
return connector;
}
revert ConnectorNotRegistered(target);
}
function hasConnector(
address target
) external view returns (bool) {
return _getConnector(target) != address(0);
}
function isCustomRegistry(
ICustomConnectorRegistry registry
) public view returns (bool) {
for (uint256 i; i != customRegistries.length;) {
if (address(customRegistries[i]) == address(registry)) {
return true;
}
unchecked {
++i;
}
}
return false;
}
/// Internal functions
function _getConnector(
address target
) internal 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)) {
(bool success, bytes memory data) = address(customRegistries[i])
.staticcall(
abi.encodeWithSelector(
ICustomConnectorRegistry.connectorOf.selector, target
)
);
if (success && data.length == 32) {
address _connector = abi.decode(data, (address));
if (_connector != address(0)) {
return _connector;
}
}
}
unchecked {
++i;
}
}
return address(0);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Farm } from "contracts/structs/FarmStrategyStructs.sol";
import { INuriGauge } from "contracts/interfaces/external/nuri/INuriGauge.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { RamsesGaugeConnector } from
"contracts/connectors/ramses/RamsesGaugeConnector.sol";
contract NuriGaugeConnector is RamsesGaugeConnector {
function deposit(
Farm calldata farm,
address token,
bytes memory // _extraData
) external payable override {
uint256 amount = IERC20(token).balanceOf(address(this));
SafeTransferLib.safeApprove(token, farm.stakingContract, amount);
INuriGauge(farm.stakingContract).deposit(amount);
}
}// 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";
import { IUniswapV3PoolState } from
"contracts/interfaces/external/uniswap/IUniswapV3Pool.sol";
import { IUniswapV3Pool } from
"contracts/interfaces/external/uniswap/IUniswapV3Pool.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
});
INuriNonfungiblePositionManager(address(addLiquidityParams.nft)).mint(
params
);
}
function _get_fee_growth_outside_tick(
address pool,
int24 tick
)
internal
view
virtual
override
returns (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128)
{
(, bytes memory result) = address(pool).staticcall(
abi.encodeCall(IUniswapV3PoolState.ticks, (tick))
);
assembly {
feeGrowthOutside0X128 := mload(add(result, 96))
feeGrowthOutside1X128 := mload(add(result, 128))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import { ICustomConnectorRegistry } from "contracts/ConnectorRegistry.sol";
interface IGaugeRegistryVoter {
function isGauge(
address target
) external view returns (bool);
function isClGauge(
address target
) external view returns (bool);
function isCLGauge(
address target
) external view returns (bool);
function poolForGauge(
address gauge
) external view returns (address);
}
contract GaugeRegistry is ICustomConnectorRegistry {
IGaugeRegistryVoter public immutable voter;
address public immutable connector;
constructor(IGaugeRegistryVoter voter_, address connector_) {
voter = voter_;
connector = connector_;
}
function connectorOf(
address target
) external view override returns (address) {
if (voter.isGauge(target)) {
return connector;
}
return address(0);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0 <0.9.0;
interface IRamsesV2Gauge {
/// @notice Emitted when a reward notification is made.
/// @param from The address from which the reward is notified.
/// @param reward The address of the reward token.
/// @param amount The amount of rewards notified.
/// @param period The period for which the rewards are notified.
event NotifyReward(
address indexed from,
address indexed reward,
uint256 amount,
uint256 period
);
/// @notice Emitted when a bribe is made.
/// @param from The address from which the bribe is made.
/// @param reward The address of the reward token.
/// @param amount The amount of tokens bribed.
/// @param period The period for which the bribe is made.
event Bribe(
address indexed from,
address indexed reward,
uint256 amount,
uint256 period
);
/// @notice Emitted when rewards are claimed.
/// @param period The period for which the rewards are claimed.
/// @param _positionHash The identifier of the NFP for which rewards are
/// claimed.
/// @param receiver The address of the receiver of the claimed rewards.
/// @param reward The address of the reward token.
/// @param amount The amount of rewards claimed.
event ClaimRewards(
uint256 period,
bytes32 _positionHash,
address receiver,
address reward,
uint256 amount
);
/// @notice Emitted when a new reward token was pushed to the rewards array
event RewardAdded(address reward);
/// @notice Emitted when a reward token was removed from the rewards array
event RewardRemoved(address reward);
/// @notice Initializes the contract with the provided gaugeFactory, voter,
/// and pool addresses.
/// @param _gaugeFactory The address of the gaugeFactory to set.
/// @param _voter The address of the voter to set.
/// @param _nfpManager The address of the NFP manager to set.
/// @param _feeCollector The address of the fee collector to set.
/// @param _pool The address of the pool to set.
function initialize(
address _gaugeFactory,
address _voter,
address _nfpManager,
address _feeCollector,
address _pool
) external;
/// @notice Retrieves the value of the firstPeriod variable.
/// @return The value of the firstPeriod variable.
function firstPeriod() external returns (uint256);
/// @notice Retrieves the total supply of a specific token for a given
/// period.
/// @param period The period for which to retrieve the total supply.
/// @param token The address of the token for which to retrieve the total
/// supply.
/// @return The total supply of the specified token for the given period.
function tokenTotalSupplyByPeriod(
uint256 period,
address token
) external view returns (uint256);
/// @notice Retrieves the total boosted seconds for a specific period.
/// @param period The period for which to retrieve the total boosted
/// seconds.
/// @return The total boosted seconds for the specified period.
function periodTotalBoostedSeconds(
uint256 period
) external view returns (uint256);
/// @notice Retrieves the getTokenTotalSupplyByPeriod of the current period.
/// @dev included to support voter's left() check during distribute().
/// @param token The address of the token for which to retrieve the
/// remaining amount.
/// @return The amount of tokens left to distribute in this period.
function left(
address token
) external view returns (uint256);
/// @notice Retrieves the reward rate for a specific reward address.
/// @dev this method returns the base rate without boost
/// @param token The address of the reward for which to retrieve the reward
/// rate.
/// @return The reward rate for the specified reward address.
function rewardRate(
address token
) external view returns (uint256);
/// @notice Retrieves the claimed amount for a specific period, position
/// hash, and user address.
/// @param period The period for which to retrieve the claimed amount.
/// @param _positionHash The identifier of the NFP for which to retrieve the
/// claimed amount.
/// @param reward The address of the token for the claimed amount.
/// @return The claimed amount for the specified period, token ID, and user
/// address.
function periodClaimedAmount(
uint256 period,
bytes32 _positionHash,
address reward
) external view returns (uint256);
/// @notice Retrieves the last claimed period for a specific token, token ID
/// combination.
/// @param token The address of the reward token for which to retrieve the
/// last claimed period.
/// @param _positionHash The identifier of the NFP for which to retrieve the
/// last claimed period.
/// @return The last claimed period for the specified token and token ID.
function lastClaimByToken(
address token,
bytes32 _positionHash
) external view returns (uint256);
/// @notice Retrieves the reward address at the specified index in the
/// rewards array.
/// @param index The index of the reward address to retrieve.
/// @return The reward address at the specified index.
function rewards(
uint256 index
) external view returns (address);
/// @notice Checks if a given address is a valid reward.
/// @param reward The address to check.
/// @return A boolean indicating whether the address is a valid reward.
function isReward(
address reward
) external view returns (bool);
/// @notice Returns an array of reward token addresses.
/// @return An array of reward token addresses.
function getRewardTokens() external view returns (address[] memory);
/// @notice Returns the hash used to store positions in a mapping
/// @param owner The address of the position owner
/// @param index The index of the position
/// @param tickLower The lower tick boundary of the position
/// @param tickUpper The upper tick boundary of the position
/// @return _hash The hash used to store positions in a mapping
function positionHash(
address owner,
uint256 index,
int24 tickLower,
int24 tickUpper
) external pure returns (bytes32);
/// @notice Retrieves the liquidity and boosted liquidity for a specific
/// NFP.
/// @param tokenId The identifier of the NFP.
/// @return liquidity The liquidity of the position token.
/// @return boostedLiquidity The boosted liquidity of the position token.
/// @return veRamTokenId The attached veRam token
function positionInfo(
uint256 tokenId
)
external
view
returns (
uint128 liquidity,
uint128 boostedLiquidity,
uint256 veRamTokenId
);
/// @notice Returns the amount of rewards earned for an NFP.
/// @param token The address of the token for which to retrieve the earned
/// rewards.
/// @param tokenId The identifier of the specific NFP for which to retrieve
/// the earned rewards.
/// @return reward The amount of rewards earned for the specified NFP and
/// tokens.
function earned(
address token,
uint256 tokenId
) external view returns (uint256 reward);
/// @notice Returns the amount of rewards earned during a period for an NFP.
/// @param period The period for which to retrieve the earned rewards.
/// @param token The address of the token for which to retrieve the earned
/// rewards.
/// @param tokenId The identifier of the specific NFP for which to retrieve
/// the earned rewards.
/// @return reward The amount of rewards earned for the specified NFP and
/// tokens.
function periodEarned(
uint256 period,
address token,
uint256 tokenId
) external view returns (uint256);
/// @notice Retrieves the earned rewards for a specific period, token,
/// owner, index, tickLower, and tickUpper.
/// @param period The period for which to retrieve the earned rewards.
/// @param token The address of the token for which to retrieve the earned
/// rewards.
/// @param owner The address of the owner for which to retrieve the earned
/// rewards.
/// @param index The index for which to retrieve the earned rewards.
/// @param tickLower The tick lower bound for which to retrieve the earned
/// rewards.
/// @param tickUpper The tick upper bound for which to retrieve the earned
/// rewards.
/// @return The earned rewards for the specified period, token, owner,
/// index, tickLower, and tickUpper.
function periodEarned(
uint256 period,
address token,
address owner,
uint256 index,
int24 tickLower,
int24 tickUpper
) external view returns (uint256);
/// @notice Retrieves the earned rewards for a specific period, token,
/// owner, index, tickLower, and tickUpper.
/// @dev used by getReward() and saves gas by saving states
/// @param period The period for which to retrieve the earned rewards.
/// @param token The address of the token for which to retrieve the earned
/// rewards.
/// @param owner The address of the owner for which to retrieve the earned
/// rewards.
/// @param index The index for which to retrieve the earned rewards.
/// @param tickLower The tick lower bound for which to retrieve the earned
/// rewards.
/// @param tickUpper The tick upper bound for which to retrieve the earned
/// rewards.
/// @param caching Whether to cache the results or not.
/// @return The earned rewards for the specified period, token, owner,
/// index, tickLower, and tickUpper.
function cachePeriodEarned(
uint256 period,
address token,
address owner,
uint256 index,
int24 tickLower,
int24 tickUpper,
bool caching
) external returns (uint256);
/// @notice Notifies the contract about the amount of rewards to be
/// distributed for a specific token.
/// @param token The address of the token for which to notify the reward
/// amount.
/// @param amount The amount of rewards to be distributed.
function notifyRewardAmount(address token, uint256 amount) external;
/// @notice Retrieves the reward amount for a specific period, NFP, and
/// token addresses.
/// @param period The period for which to retrieve the reward amount.
/// @param tokens The addresses of the tokens for which to retrieve the
/// reward amount.
/// @param tokenId The identifier of the specific NFP for which to retrieve
/// the reward amount.
/// @param receiver The address of the receiver of the reward amount.
function getPeriodReward(
uint256 period,
address[] calldata tokens,
uint256 tokenId,
address receiver
) external;
/// @notice Retrieves the rewards for a specific period, set of tokens,
/// owner, index, tickLower, tickUpper, and receiver.
/// @param period The period for which to retrieve the rewards.
/// @param tokens An array of token addresses for which to retrieve the
/// rewards.
/// @param owner The address of the owner for which to retrieve the rewards.
/// @param index The index for which to retrieve the rewards.
/// @param tickLower The tick lower bound for which to retrieve the rewards.
/// @param tickUpper The tick upper bound for which to retrieve the rewards.
/// @param receiver The address of the receiver of the rewards.
function getPeriodReward(
uint256 period,
address[] calldata tokens,
address owner,
uint256 index,
int24 tickLower,
int24 tickUpper,
address receiver
) external;
function addRewards(
address reward
) external;
function removeRewards(
address reward
) external;
function getRewardForOwner(
uint256 tokenId,
address[] memory tokens
) external;
function getReward(uint256 tokenId, address[] memory tokens) external;
/// @notice Notifies rewards for periods greater than current period
/// @dev does not push fees
/// @dev requires reward token to be whitelisted
function notifyRewardAmountForPeriod(
address token,
uint256 amount,
uint256 period
) external;
/// @notice Notifies rewards for the next period
/// @dev does not push fees
/// @dev requires reward token to be whitelisted
function notifyRewardAmountNextPeriod(
address token,
uint256 amount
) external;
function gaugeFactory() external view returns (address);
}// 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(address(0), 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;
}
}// 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.13;
interface INuriGauge {
function initialize(
address _stake,
address _feeDist,
address _voter,
bool _forPair
) external;
function getReward(address account, address[] calldata tokens) external;
function claimFees()
external
returns (uint256 claimed0, uint256 claimed1);
function left(
address token
) external view returns (uint256);
function rewardsListLength() external view returns (uint256);
function rewardsList() external view returns (address[] memory);
function earned(
address token,
address account
) external view returns (uint256);
function balanceOf(
address
) external view returns (uint256);
function notifyRewardAmount(address token, uint256 amount) external;
struct Reward {
uint256 rewardRate;
uint256 periodFinish;
uint256 lastUpdateTime;
uint256 rewardPerTokenStored;
}
function rewardData(
address token
) external view returns (Reward memory);
function deposit(
uint256 amount
) external;
function withdraw(
uint256 amount
) external;
}// 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: 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 { IFarmConnector, Farm } from "contracts/interfaces/IFarmConnector.sol";
import { IRamsesGauge } from
"contracts/interfaces/external/ramses/IRamsesGauge.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
struct RamsesClaimExtraData {
address[] rewardTokens;
}
contract RamsesGaugeConnector is IFarmConnector {
function deposit(
Farm calldata farm,
address token,
bytes memory // _extraData
) external payable virtual override {
uint256 amount = IERC20(token).balanceOf(address(this));
SafeTransferLib.safeApprove(token, farm.stakingContract, amount);
IRamsesGauge(farm.stakingContract).deposit(amount, 0);
}
function withdraw(
Farm calldata farm,
uint256 amount,
bytes memory // _extraData
) external override {
IRamsesGauge(farm.stakingContract).withdraw(amount);
}
function claim(
Farm calldata farm,
bytes memory _extraData
) external virtual override {
RamsesClaimExtraData memory extraData =
abi.decode(_extraData, (RamsesClaimExtraData));
IRamsesGauge(farm.stakingContract).claimFees();
IRamsesGauge(farm.stakingContract).getReward(
address(this), extraData.rewardTokens
);
}
function balanceOf(
Farm calldata farm,
address user
) external view override returns (uint256) {
return IRamsesGauge(farm.stakingContract).balanceOf(user);
}
function earned(
Farm calldata farm,
address user,
address[] calldata rewardTokens
) external view virtual override returns (uint256[] memory) {
uint256[] memory rewards = new uint256[](rewardTokens.length);
for (uint256 i = 0; i < rewardTokens.length; i++) {
rewards[i] =
IRamsesGauge(farm.stakingContract).earned(rewardTokens[i], user);
}
return rewards;
}
function isStaked(
Farm calldata,
address // user
) external pure override returns (bool) {
return true;
}
}// 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 NftPoolKey {
address poolAddress;
bytes32 poolId;
}
struct NftPoolInfo {
address token0;
address token1;
uint24 fee;
uint24 tickSpacing;
uint160 sqrtPriceX96;
int24 tick;
uint128 liquidity;
uint256 feeGrowthGlobal0X128;
uint256 feeGrowthGlobal1X128;
}
// Maintained for backwards compatibility with NftSettingsRegistry
struct NftPositionInfo {
uint128 liquidity;
int24 tickLower;
int24 tickUpper;
}
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 { IRamsesV2Pool } from
"contracts/interfaces/external/ramses/IRamsesV2Pool.sol";
import { ISwapRouter } from
"contracts/interfaces/external/uniswap/ISwapRouter.sol";
import {
UniswapV3Connector,
NftAddLiquidity
} from "contracts/connectors/uniswap/UniswapV3Connector.sol";
import { INonfungiblePositionManager } from
"contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
import { IVoter } from "contracts/interfaces/external/aerodrome/IVoter.sol";
import { IUniswapV3Factory } from
"contracts/interfaces/external/uniswap/IUniswapV3Factory.sol";
import { IRamsesV2Gauge } from
"contracts/interfaces/external/ramses/IRamsesV2Gauge.sol";
struct RamsesV3SwapExtraData {
address pool;
bytes path;
}
struct RamsesV3ClaimExtraData {
bool isPool;
}
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,
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 {
bool isPool = false;
if (extraData.length == 32) {
isPool = abi.decode(extraData, (RamsesV3ClaimExtraData)).isPool;
}
if (!isPool) {
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,
veRamTokenId: 0
});
IRamsesNonfungiblePositionManager(address(addLiquidityParams.nft)).mint(
params
);
}
function isStaked(
address, // user
NftPosition calldata
) external view virtual override returns (bool) {
return false; // Ramses positions stay in the Sickle while earning
// rewards
}
function earned(
address, // user
NftPosition calldata position,
address[] memory rewardTokens
) external view virtual override returns (uint256[] memory) {
IRamsesNonfungiblePositionManager nft =
IRamsesNonfungiblePositionManager(address(position.nft));
IVoter voter = IVoter(nft.voter());
(,, address token0, address token1, uint24 fee_,,,,,,,) =
nft.positions(position.tokenId);
IUniswapV3Factory factory = IUniswapV3Factory(nft.factory());
address pool = factory.getPool(token0, token1, fee_);
IRamsesV2Gauge gauge = IRamsesV2Gauge(voter.gauges(pool));
if (address(gauge) == address(0)) {
return new uint256[](rewardTokens.length);
}
uint256[] memory rewards = new uint256[](rewardTokens.length);
for (uint256 i = 0; i < rewardTokens.length; i++) {
rewards[i] = gauge.earned(rewardTokens[i], position.tokenId);
}
return rewards;
}
function _get_fee_growth_outside_tick(
address pool,
int24 tick_
)
internal
view
virtual
override
returns (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128)
{
(,,,, feeGrowthOutside0X128, feeGrowthOutside1X128,,,,) =
IRamsesV2Pool(pool).ticks(tick_);
}
}// 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 { 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: 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;
}// 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.0;
import { Farm } from "contracts/structs/FarmStrategyStructs.sol";
interface IFarmConnector {
function deposit(
Farm calldata farm,
address token,
bytes memory extraData
) external payable;
function withdraw(
Farm calldata farm,
uint256 amount,
bytes memory extraData
) external;
function claim(Farm calldata farm, bytes memory extraData) external;
function balanceOf(
Farm calldata farm,
address user
) external view returns (uint256);
function earned(
Farm calldata farm,
address user,
address[] calldata rewardTokens
) external view returns (uint256[] memory);
function isStaked(
Farm calldata farm,
address user
) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IRamsesGauge {
function notifyRewardAmount(address token, uint256 amount) external;
function getReward(address account, address[] memory tokens) external;
function claimFees()
external
returns (uint256 claimed0, uint256 claimed1);
function left(address token) external view returns (uint256);
function isForPair() external view returns (bool);
function whitelistNotifiedRewards(address token) external;
function removeRewardWhitelist(address token) external;
function rewardsListLength() external view returns (uint256);
function rewards(uint256 index) external view returns (address);
function earned(
address token,
address account
) external view returns (uint256);
function balanceOf(address) external view returns (uint256);
function derivedBalances(address) external view returns (uint256);
function rewardRate(address) external view returns (uint256);
function deposit(uint256 amount, uint256 tokenId) external;
function withdraw(uint256 amount) external;
}// 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
);
function factory() external view returns (address);
}// 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;
function earned(
address user,
NftPosition calldata position,
address[] memory rewardTokens
) external view returns (uint256[] memory);
function isStaked(
address user,
NftPosition calldata position
) external view returns (bool);
}// 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;
function voter() external view returns (address);
function factory() external view returns (address);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
import { IRamsesV2PoolImmutables } from
"contracts/interfaces/external/ramses/IRamsesV2PoolImmutables.sol";
import { IRamsesV2PoolState } from
"contracts/interfaces/external/ramses/IRamsesV2PoolState.sol";
/// @title The interface for a Ramses V2 Pool
/// @notice A Ramses pool facilitates swapping and automated market making
/// between any two assets that strictly conform
/// to the ERC20 specification
/// @dev The pool interface is broken up into many smaller pieces
interface IRamsesV2Pool is IRamsesV2PoolImmutables, IRamsesV2PoolState {
/// @notice Initializes a pool with parameters provided
function initialize(
address _factory,
address _nfpManager,
address _veRam,
address _voter,
address _token0,
address _token1,
uint24 _fee,
int24 _tickSpacing
) external;
function _advancePeriod() 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 { IERC721Enumerable } from
"@openzeppelin/contracts/interfaces/IERC721Enumerable.sol";
import { INonfungiblePositionManager } from
"contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
import { PositionValue } from
"contracts/interfaces/external/uniswap/v3/PositionValue.sol";
import { ISwapRouter } from
"contracts/interfaces/external/uniswap/ISwapRouter.sol";
import {
IUniswapV3Pool,
IUniswapV3PoolState
} from "contracts/interfaces/external/uniswap/IUniswapV3Pool.sol";
import { IUniswapV3Factory } from
"contracts/interfaces/external/uniswap/IUniswapV3Factory.sol";
import { INftFarmConnector } from "contracts/interfaces/INftFarmConnector.sol";
import { INftLiquidityConnector } from
"contracts/interfaces/INftLiquidityConnector.sol";
import {
NftPoolInfo,
NftPoolKey,
NftPositionInfo
} from "contracts/structs/NftLiquidityStructs.sol";
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
import {
NftAddLiquidity,
NftRemoveLiquidity,
Pool
} from "contracts/structs/NftLiquidityStructs.sol";
import { NftPosition } from "contracts/structs/NftFarmStrategyStructs.sol";
struct UniswapV3SwapExtraData {
bytes path;
}
contract UniswapV3Connector is
INftLiquidityConnector,
INftFarmConnector,
PositionValue
{
error InvalidParameters();
error NotSupported();
function addLiquidity(
NftAddLiquidity memory addLiquidityParams
) external payable override {
if (addLiquidityParams.tokenId == 0) {
_mint(addLiquidityParams);
} else {
_increaseLiquidity(addLiquidityParams);
}
}
function removeLiquidity(
NftRemoveLiquidity memory removeLiquidityParams
) external override {
uint128 currentLiquidity;
if (removeLiquidityParams.liquidity == type(uint128).max) {
(,, currentLiquidity) = positionLiquidity(
address(removeLiquidityParams.nft),
removeLiquidityParams.tokenId
);
removeLiquidityParams.liquidity = currentLiquidity;
}
if (removeLiquidityParams.liquidity == 0) {
revert InvalidParameters();
}
_decreaseLiquidity(removeLiquidityParams);
_collect(
removeLiquidityParams.nft,
removeLiquidityParams.tokenId,
removeLiquidityParams.amount0Max,
removeLiquidityParams.amount1Max
);
(,, currentLiquidity) = positionLiquidity(
address(removeLiquidityParams.nft), 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));
ISwapRouter(swap.router).exactInput(
ISwapRouter.ExactInputParams({
path: extraData.path,
recipient: address(this),
deadline: block.timestamp,
amountIn: swap.amountIn,
amountOutMinimum: swap.minAmountOut
})
);
}
function swapExactETHForTokens(
SwapParams memory
) external payable virtual override {
revert NotSupported();
}
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 {
if (amount0Max > 0 || amount1Max > 0) {
_collect(position.nft, position.tokenId, amount0Max, amount1Max);
}
}
function poolInfo(
address pool,
bytes32 // poolId
) external view virtual override returns (NftPoolInfo memory) {
(uint160 sqrtPriceX96, int24 tick,,,,,) = IUniswapV3Pool(pool).slot0();
return NftPoolInfo({
token0: IUniswapV3Pool(pool).token0(),
token1: IUniswapV3Pool(pool).token1(),
fee: IUniswapV3Pool(pool).fee(),
tickSpacing: uint24(IUniswapV3Pool(pool).tickSpacing()),
sqrtPriceX96: sqrtPriceX96,
tick: tick,
liquidity: IUniswapV3Pool(pool).liquidity(),
feeGrowthGlobal0X128: IUniswapV3Pool(pool).feeGrowthGlobal0X128(),
feeGrowthGlobal1X128: IUniswapV3Pool(pool).feeGrowthGlobal1X128()
});
}
function fee(
address pool,
uint256 // tokenId
) external view virtual override returns (uint24) {
return IUniswapV3Pool(pool).fee();
}
function positionPoolKey(
address poolFactory,
address nftManager,
uint256 tokenId
) external view virtual override returns (NftPoolKey memory) {
(,, address token0, address token1, uint24 fee_,,,,,,,) =
INonfungiblePositionManager(nftManager).positions(tokenId);
return NftPoolKey({
poolAddress: IUniswapV3Factory(poolFactory).getPool(
token0, token1, fee_
),
poolId: bytes32(0) // Uniswap V4 only
});
}
function getTokenId(
address nft,
address owner
) external view virtual returns (uint256) {
return IERC721Enumerable(nft).tokenOfOwnerByIndex(
address(owner), IERC721Enumerable(nft).balanceOf(address(owner)) - 1
);
}
function totalSupply(
address nftManager
) external view virtual override returns (uint256) {
return INonfungiblePositionManager(nftManager).totalSupply();
}
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
})
);
}
function _increaseLiquidity(
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
})
);
}
function _decreaseLiquidity(
NftRemoveLiquidity memory removeLiquidityParams
) internal {
removeLiquidityParams.nft.decreaseLiquidity(
INonfungiblePositionManager.DecreaseLiquidityParams({
tokenId: removeLiquidityParams.tokenId,
liquidity: removeLiquidityParams.liquidity,
amount0Min: removeLiquidityParams.amount0Min,
amount1Min: removeLiquidityParams.amount1Min,
deadline: block.timestamp
})
);
}
function _collect(
INonfungiblePositionManager nft,
uint256 tokenId,
uint128 amount0Max,
uint128 amount1Max
) internal {
nft.collect(
INonfungiblePositionManager.CollectParams({
tokenId: tokenId,
recipient: address(this),
amount0Max: amount0Max,
amount1Max: amount1Max
})
);
}
function isStaked(
address,
NftPosition calldata
) external view virtual override returns (bool) {
return false; // Uniswap V3 does not support staking
}
function earned(
address, // user
NftPosition calldata,
address[] memory rewardTokens
) external view virtual override returns (uint256[] memory) {
// Uniswap V3 does not support token incentives
return new uint256[](rewardTokens.length);
}
function earnedFees(
address nftManager,
address pool,
uint256 tokenId
) external view virtual override returns (uint256 fees0, uint256 fees1) {
(fees0, fees1) = fees(nftManager, pool, tokenId);
}
function positionLiquidity(
address nftManager,
uint256 tokenId
)
public
view
virtual
returns (int24 tickLower, int24 tickUpper, uint128 liquidity)
{
(,,,,, tickLower, tickUpper, liquidity,,,,) =
INonfungiblePositionManager(nftManager).positions(tokenId);
}
function positionInfo(
address nftManager,
uint256 tokenId
) external view virtual override returns (NftPositionInfo memory) {
(int24 tickLower, int24 tickUpper, uint128 liquidity) =
positionLiquidity(nftManager, tokenId);
return NftPositionInfo({
liquidity: liquidity,
tickLower: tickLower,
tickUpper: tickUpper
});
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IVoter {
error AlreadyVotedOrDeposited();
error DistributeWindow();
error FactoryPathNotApproved();
error GaugeAlreadyKilled();
error GaugeAlreadyRevived();
error GaugeExists();
error GaugeDoesNotExist(address _pool);
error GaugeNotAlive(address _gauge);
error InactiveManagedNFT();
error MaximumVotingNumberTooLow();
error NonZeroVotes();
error NotAPool();
error NotApprovedOrOwner();
error NotGovernor();
error NotEmergencyCouncil();
error NotMinter();
error NotWhitelistedNFT();
error NotWhitelistedToken();
error SameValue();
error SpecialVotingWindow();
error TooManyPools();
error UnequalLengths();
error ZeroBalance();
error ZeroAddress();
event GaugeCreated(
address indexed poolFactory,
address indexed votingRewardsFactory,
address indexed gaugeFactory,
address pool,
address bribeVotingReward,
address feeVotingReward,
address gauge,
address creator
);
event GaugeKilled(address indexed gauge);
event GaugeRevived(address indexed gauge);
event Voted(
address indexed voter,
address indexed pool,
uint256 indexed tokenId,
uint256 weight,
uint256 totalWeight,
uint256 timestamp
);
event Abstained(
address indexed voter,
address indexed pool,
uint256 indexed tokenId,
uint256 weight,
uint256 totalWeight,
uint256 timestamp
);
event NotifyReward(
address indexed sender, address indexed reward, uint256 amount
);
event DistributeReward(
address indexed sender, address indexed gauge, uint256 amount
);
event WhitelistToken(
address indexed whitelister, address indexed token, bool indexed _bool
);
event WhitelistNFT(
address indexed whitelister, uint256 indexed tokenId, bool indexed _bool
);
function pools(uint256 i) external view returns (address);
/// @notice Store trusted forwarder address to pass into factories
function forwarder() external view returns (address);
/// @notice The ve token that governs these contracts
function ve() external view returns (address);
/// @notice Factory registry for valid pool / gauge / rewards factories
function factoryRegistry() external view returns (address);
/// @notice Address of Minter.sol
function minter() external view returns (address);
/// @notice Standard OZ IGovernor using ve for vote weights.
function governor() external view returns (address);
/// @notice Custom Epoch Governor using ve for vote weights.
function epochGovernor() external view returns (address);
/// @notice credibly neutral party similar to Curve's Emergency DAO
function emergencyCouncil() external view returns (address);
/// @dev Total Voting Weights
function totalWeight() external view returns (uint256);
/// @dev Most number of pools one voter can vote for at once
function maxVotingNum() external view returns (uint256);
// mappings
/// @dev Pool => Gauge
function gauges(address pool) external view returns (address);
/// @dev Gauge => Pool
function poolForGauge(address gauge) external view returns (address);
/// @dev Gauge => Fees Voting Reward
function gaugeToFees(address gauge) external view returns (address);
/// @dev Gauge => Bribes Voting Reward
function gaugeToBribe(address gauge) external view returns (address);
/// @dev Pool => Weights
function weights(address pool) external view returns (uint256);
/// @dev NFT => Pool => Votes
function votes(
uint256 tokenId,
address pool
) external view returns (uint256);
/// @dev NFT => Total voting weight of NFT
function usedWeights(uint256 tokenId) external view returns (uint256);
/// @dev Nft => Timestamp of last vote (ensures single vote per epoch)
function lastVoted(uint256 tokenId) external view returns (uint256);
/// @dev Address => Gauge
function isGauge(address) external view returns (bool);
/// @dev Token => Whitelisted status
function isWhitelistedToken(address token) external view returns (bool);
/// @dev TokenId => Whitelisted status
function isWhitelistedNFT(uint256 tokenId) external view returns (bool);
/// @dev Gauge => Liveness status
function isAlive(address gauge) external view returns (bool);
/// @dev Gauge => Amount claimable
function claimable(address gauge) external view returns (uint256);
/// @notice Number of pools with a Gauge
function length() external view returns (uint256);
/// @notice Called by Minter to distribute weekly emissions rewards for
/// disbursement amongst gauges.
/// @dev Assumes totalWeight != 0 (Will never be zero as long as users are
/// voting).
/// Throws if not called by minter.
/// @param _amount Amount of rewards to distribute.
function notifyRewardAmount(uint256 _amount) external;
/// @dev Utility to distribute to gauges of pools in range _start to
/// _finish.
/// @param _start Starting index of gauges to distribute to.
/// @param _finish Ending index of gauges to distribute to.
function distribute(uint256 _start, uint256 _finish) external;
/// @dev Utility to distribute to gauges of pools in array.
/// @param _gauges Array of gauges to distribute to.
function distribute(address[] memory _gauges) external;
/// @notice Called by users to update voting balances in voting rewards
/// contracts.
/// @param _tokenId Id of veNFT whose balance you wish to update.
function poke(uint256 _tokenId) external;
/// @notice Called by users to vote for pools. Votes distributed
/// proportionally based on weights.
/// Can only vote or deposit into a managed NFT once per epoch.
/// Can only vote for gauges that have not been killed.
/// @dev Weights are distributed proportional to the sum of the weights in
/// the array.
/// Throws if length of _poolVote and _weights do not match.
/// @param _tokenId Id of veNFT you are voting with.
/// @param _poolVote Array of pools you are voting for.
/// @param _weights Weights of pools.
function vote(
uint256 _tokenId,
address[] calldata _poolVote,
uint256[] calldata _weights
) external;
/// @notice Called by users to reset voting state. Required if you wish to
/// make changes to
/// veNFT state (e.g. merge, split, deposit into managed etc).
/// Cannot reset in the same epoch that you voted in.
/// Can vote or deposit into a managed NFT again after reset.
/// @param _tokenId Id of veNFT you are reseting.
function reset(uint256 _tokenId) external;
/// @notice Called by users to deposit into a managed NFT.
/// Can only vote or deposit into a managed NFT once per epoch.
/// Note that NFTs deposited into a managed NFT will be re-locked
/// to the maximum lock time on withdrawal.
/// @dev Throws if not approved or owner.
/// Throws if managed NFT is inactive.
/// Throws if depositing within privileged window (one hour prior to
/// epoch flip).
function depositManaged(uint256 _tokenId, uint256 _mTokenId) external;
/// @notice Called by users to withdraw from a managed NFT.
/// Cannot do it in the same epoch that you deposited into a managed
/// NFT.
/// Can vote or deposit into a managed NFT again after withdrawing.
/// Note that the NFT withdrawn is re-locked to the maximum lock
/// time.
function withdrawManaged(uint256 _tokenId) external;
/// @notice Claim emissions from gauges.
/// @param _gauges Array of gauges to collect emissions from.
function claimRewards(address[] memory _gauges) external;
/// @notice Claim bribes for a given NFT.
/// @dev Utility to help batch bribe claims.
/// @param _bribes Array of BribeVotingReward contracts to collect from.
/// @param _tokens Array of tokens that are used as bribes.
/// @param _tokenId Id of veNFT that you wish to claim bribes for.
function claimBribes(
address[] memory _bribes,
address[][] memory _tokens,
uint256 _tokenId
) external;
/// @notice Claim fees for a given NFT.
/// @dev Utility to help batch fee claims.
/// @param _fees Array of FeesVotingReward contracts to collect from.
/// @param _tokens Array of tokens that are used as fees.
/// @param _tokenId Id of veNFT that you wish to claim fees for.
function claimFees(
address[] memory _fees,
address[][] memory _tokens,
uint256 _tokenId
) external;
/// @notice Set new governor.
/// @dev Throws if not called by governor.
/// @param _governor .
function setGovernor(address _governor) external;
/// @notice Set new epoch based governor.
/// @dev Throws if not called by governor.
/// @param _epochGovernor .
function setEpochGovernor(address _epochGovernor) external;
/// @notice Set new emergency council.
/// @dev Throws if not called by emergency council.
/// @param _emergencyCouncil .
function setEmergencyCouncil(address _emergencyCouncil) external;
/// @notice Set maximum number of gauges that can be voted for.
/// @dev Throws if not called by governor.
/// Throws if _maxVotingNum is too low.
/// Throws if the values are the same.
/// @param _maxVotingNum .
function setMaxVotingNum(uint256 _maxVotingNum) external;
/// @notice Whitelist (or unwhitelist) token for use in bribes.
/// @dev Throws if not called by governor.
/// @param _token .
/// @param _bool .
function whitelistToken(address _token, bool _bool) external;
/// @notice Whitelist (or unwhitelist) token id for voting in last hour
/// prior to epoch flip.
/// @dev Throws if not called by governor.
/// Throws if already whitelisted.
/// @param _tokenId .
/// @param _bool .
function whitelistNFT(uint256 _tokenId, bool _bool) external;
/// @notice Create a new gauge (unpermissioned).
/// @dev Governor can create a new gauge for a pool with any address.
/// @param _poolFactory .
/// @param _pool .
function createGauge(
address _poolFactory,
address _pool
) external returns (address);
/// @notice Kills a gauge. The gauge will not receive any new emissions and
/// cannot be deposited into.
/// Can still withdraw from gauge.
/// @dev Throws if not called by emergency council.
/// Throws if gauge already killed.
/// @param _gauge .
function killGauge(address _gauge) external;
/// @notice Revives a killed gauge. Gauge will can receive emissions and
/// deposits again.
/// @dev Throws if not called by emergency council.
/// Throws if gauge is not killed.
/// @param _gauge .
function reviveGauge(address _gauge) external;
/// @dev Update claims to emissions for an array of gauges.
/// @param _gauges Array of gauges to update emissions for.
function updateFor(address[] memory _gauges) external;
/// @dev Update claims to emissions for gauges based on their pool id as
/// stored in Voter.
/// @param _start Starting index of pools.
/// @param _end Ending index of pools.
function updateFor(uint256 _start, uint256 _end) external;
/// @dev Update claims to emissions for single gauge
/// @param _gauge .
function updateFor(address _gauge) external;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @title The interface for the Uniswap V3 Factory
/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and
/// control over the protocol fees
interface IUniswapV3Factory {
/// @notice Emitted when the owner of the factory is changed
/// @param oldOwner The owner before the owner was changed
/// @param newOwner The owner after the owner was changed
event OwnerChanged(address indexed oldOwner, address indexed newOwner);
/// @notice Emitted when a pool is created
/// @param token0 The first token of the pool by address sort order
/// @param token1 The second token of the pool by address sort order
/// @param fee The fee collected upon every swap in the pool, denominated in
/// hundredths of a bip
/// @param tickSpacing The minimum number of ticks between initialized ticks
/// @param pool The address of the created pool
event PoolCreated(
address indexed token0,
address indexed token1,
uint24 indexed fee,
int24 tickSpacing,
address pool
);
/// @notice Emitted when a new fee amount is enabled for pool creation via
/// the factory
/// @param fee The enabled fee, denominated in hundredths of a bip
/// @param tickSpacing The minimum number of ticks between initialized ticks
/// for pools created with the given fee
event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);
/// @notice Returns the current owner of the factory
/// @dev Can be changed by the current owner via setOwner
/// @return The address of the factory owner
function owner() external view returns (address);
/// @notice Returns the tick spacing for a given fee amount, if enabled, or
/// 0 if not enabled
/// @dev A fee amount can never be removed, so this value should be hard
/// coded or cached in the calling context
/// @param fee The enabled fee, denominated in hundredths of a bip. Returns
/// 0 in case of unenabled fee
/// @return The tick spacing
function feeAmountTickSpacing(uint24 fee) external view returns (int24);
/// @notice Returns the pool address for a given pair of tokens and a fee,
/// or address 0 if it does not exist
/// @dev tokenA and tokenB may be passed in either token0/token1 or
/// token1/token0 order
/// @param tokenA The contract address of either token0 or token1
/// @param tokenB The contract address of the other token
/// @param fee The fee collected upon every swap in the pool, denominated in
/// hundredths of a bip
/// @return pool The pool address
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address pool);
/// @notice Creates a pool for the given two tokens and fee
/// @param tokenA One of the two tokens in the desired pool
/// @param tokenB The other of the two tokens in the desired pool
/// @param fee The desired fee for the pool
/// @dev tokenA and tokenB may be passed in either order: token0/token1 or
/// token1/token0. tickSpacing is retrieved
/// from the fee. The call will revert if the pool already exists, the fee
/// is invalid, or the token arguments
/// are invalid.
/// @return pool The address of the newly created pool
function createPool(
address tokenA,
address tokenB,
uint24 fee
) external returns (address pool);
/// @notice Updates the owner of the factory
/// @dev Must be called by the current owner
/// @param _owner The new owner of the factory
function setOwner(address _owner) external;
/// @notice Enables a fee amount with the given tickSpacing
/// @dev Fee amounts may never be removed once enabled
/// @param fee The fee amount to enable, denominated in hundredths of a bip
/// (i.e. 1e-6)
/// @param tickSpacing The spacing between ticks to be enforced for all
/// pools created with the given fee amount
function enableFeeAmount(uint24 fee, int24 tickSpacing) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {
AddLiquidityParams,
RemoveLiquidityParams,
SwapParams
} from "contracts/structs/LiquidityStructs.sol";
interface ILiquidityConnector {
error InvalidPrice();
function addLiquidity(
AddLiquidityParams memory addLiquidityParams
) external payable;
function removeLiquidity(
RemoveLiquidityParams memory removeLiquidityParams
) external;
function swapExactTokensForTokens(
SwapParams memory swap
) external payable;
function swapExactETHForTokens(
SwapParams memory swap
) external payable;
function getPoolPrice(
address lpToken,
uint256 baseTokenIndex,
uint256 quoteTokenIndex
) external view returns (uint256);
function getReserves(
address lpToken
) external view returns (uint256[] memory reserves);
function getTokens(
address lpToken
) external view returns (address[] memory tokens);
}// 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 payable;
}// 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 { 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: 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 IRamsesV2PoolImmutables {
/// @notice The contract that deployed the pool, which must adhere to the
/// IRamsesV2Factory interface
/// @return The contract address
function factory() external view returns (address);
/// @notice The contract that manages RamsesV2 NFPs, which must adhere to
/// the INonfungiblePositionManager interface
/// @return The contract address
function nfpManager() external view returns (address);
/// @notice The contract that manages veRamses NFTs, which must adhere to
/// the IVotinEscrow interface
/// @return The contract address
function veRam() external view returns (address);
/// @notice The contract that manages Ramses votes, which must adhere to the
/// IVoter interface
/// @return The contract address
function voter() 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 the pool was initialized with
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);
/// @notice returns the current fee set for the pool
function currentFee() external view returns (uint24);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
/// @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 IRamsesV2PoolState {
/// @notice reads arbitrary storage slots and returns the bytes
/// @param slots The slots to read from
/// @return returnData The data read from the slots
function readStorage(
bytes32[] calldata slots
) external view returns (bytes32[] memory returnData);
/// @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
/// 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.
/// observationIndex The index of the last oracle observation that was
/// written,
/// observationCardinality The current maximum number of observations stored
/// in the pool,
/// observationCardinalityNext The next maximum number of observations, to
/// be updated when the observation.
/// 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 Returns the last tick of a given period
/// @param period The period in question
/// @return previousPeriod The period before current period
/// @dev this is because there might be periods without trades
/// startTick The start tick of the period
/// lastTick The last tick of the period, if the period is finished
/// endSecondsPerLiquidityPeriodX128 Seconds per liquidity at period's end
/// endSecondsPerBoostedLiquidityPeriodX128 Seconds per boosted liquidity
/// at period's end
function periods(
uint256 period
)
external
view
returns (
uint32 previousPeriod,
int24 startTick,
int24 lastTick,
uint160 endSecondsPerLiquidityCumulativeX128,
uint160 endSecondsPerBoostedLiquidityCumulativeX128,
uint32 boostedInRange
);
/// @notice The last period where a trade or liquidity change happened
function lastPeriod() external view returns (uint256);
/// @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
function liquidity() external view returns (uint128);
/// @notice The currently in range derived liquidity available to the pool
/// @dev This value has no relationship to the total liquidity across all
/// ticks
function boostedLiquidity() external view returns (uint128);
/// @notice Get the boost information for a specific position at a period
/// @return boostAmount the amount of boost this position has for this
/// period,
/// veRamAmount the amount of veRam attached to this position for this
/// period,
/// secondsDebtX96 used to account for changes in the deposit amount during
/// the period
/// boostedSecondsDebtX96 used to account for changes in the boostAmount and
/// veRam locked during the period,
function boostInfos(
uint256 period,
bytes32 key
)
external
view
returns (
uint128 boostAmount,
int128 veRamAmount,
int256 secondsDebtX96,
int256 boostedSecondsDebtX96
);
/// @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,
/// liquidityNet how much liquidity changes when the pool price crosses the
/// tick,
/// feeGrowthOutside0X128 the fee growth on the other side of the tick from
/// the current tick in token0,
/// feeGrowthOutside1X128 the fee growth on the other side of the tick from
/// the current tick in token1,
/// tickCumulativeOutside the cumulative tick value on the other side of the
/// tick from the current tick
/// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the
/// other side of the tick from the current tick,
/// secondsOutside the seconds spent on the other side of the tick from the
/// current tick,
/// 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,
uint128 boostedLiquidityGross,
int128 boostedLiquidityNet,
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,
/// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick
/// range as of the last mint/burn/poke,
/// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick
/// range as of the last mint/burn/poke,
/// Returns tokensOwed0 the computed amount of token0 owed to the position
/// as of the last mint/burn/poke,
/// Returns tokensOwed1 the computed amount of token1 owed to the position
/// as of the last mint/burn/poke
/// Returns attachedVeRamId the veRam tokenId attached to the position
function positions(
bytes32 key
)
external
view
returns (
uint128 _liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1,
uint256 attachedVeRamId
);
/// @notice Returns a period's total boost amount and total veRam attached
/// @param period Period timestamp
/// @return totalBoostAmount The total amount of boost this period has,
/// Returns totalVeRamAmount The total amount of veRam attached to this
/// period
function boostInfos(
uint256 period
)
external
view
returns (uint128 totalBoostAmount, int128 totalVeRamAmount);
/// @notice Get the period seconds debt of a specific position
/// @param period the period number
/// @param recipient recipient address
/// @param index position index
/// @param tickLower lower bound of range
/// @param tickUpper upper bound of range
/// @return secondsDebtX96 seconds the position was not in range for the
/// period
/// @return boostedSecondsDebtX96 boosted seconds the period
function positionPeriodDebt(
uint256 period,
address recipient,
uint256 index,
int24 tickLower,
int24 tickUpper
)
external
view
returns (int256 secondsDebtX96, int256 boostedSecondsDebtX96);
/// @notice get the period seconds in range of a specific position
/// @param period the period number
/// @param owner owner address
/// @param index position index
/// @param tickLower lower bound of range
/// @param tickUpper upper bound of range
/// @return periodSecondsInsideX96 seconds the position was not in range for
/// the period
/// @return periodBoostedSecondsInsideX96 boosted seconds the period
function positionPeriodSecondsInRange(
uint256 period,
address owner,
uint256 index,
int24 tickLower,
int24 tickUpper
)
external
view
returns (
uint256 periodSecondsInsideX96,
uint256 periodBoostedSecondsInsideX96
);
/// @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,
/// Returns tickCumulative the tick multiplied by seconds elapsed for the
/// life of the pool as of the observation timestamp,
/// Returns secondsPerLiquidityCumulativeX128 the seconds per in range
/// liquidity for the life of the pool as of the observation timestamp,
/// Returns 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,
uint160 secondsPerBoostedLiquidityPeriodX128
);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
import "contracts/interfaces/external/uniswap/IUniswapV3Pool.sol";
import "contracts/interfaces/external/uniswap/INonfungiblePositionManager.sol";
import "contracts/interfaces/external/uniswap/v3/libraries/FixedPoint128.sol";
import "contracts/interfaces/external/uniswap/v3/libraries/TickMath.sol";
import "contracts/interfaces/external/uniswap/v3/libraries/LiquidityAmounts.sol";
/// @title Returns information about the token value held in a Uniswap V3 NFT
contract PositionValue {
/// @notice Returns the total amounts of token0 and token1, i.e. the sum of
/// fees and principal
/// that a given nonfungible position manager token is worth
/// @param positionManager The Uniswap V3 NonfungiblePositionManager
/// @param tokenId The tokenId of the token for which to get the total value
/// @param sqrtRatioX96 The square root price X96 for which to calculate the
/// principal amounts
/// @return amount0 The total amount of token0 including principal and fees
/// @return amount1 The total amount of token1 including principal and fees
function total(
address positionManager,
address pool,
uint256 tokenId,
uint160 sqrtRatioX96
) internal view returns (uint256 amount0, uint256 amount1) {
(uint256 amount0Principal, uint256 amount1Principal) =
principal(positionManager, tokenId, sqrtRatioX96);
(uint256 amount0Fee, uint256 amount1Fee) =
fees(positionManager, pool, tokenId);
return (amount0Principal + amount0Fee, amount1Principal + amount1Fee);
}
/// @notice Calculates the principal (currently acting as liquidity) owed to
/// the token owner in the event
/// that the position is burned
/// @param positionManager The Uniswap V3 NonfungiblePositionManager
/// @param tokenId The tokenId of the token for which to get the total
/// principal owed
/// @param sqrtRatioX96 The square root price X96 for which to calculate the
/// principal amounts
/// @return amount0 The principal amount of token0
/// @return amount1 The principal amount of token1
function principal(
address positionManager,
uint256 tokenId,
uint160 sqrtRatioX96
) internal view returns (uint256 amount0, uint256 amount1) {
(,,,,, int24 tickLower, int24 tickUpper, uint128 liquidity,,,,) =
INonfungiblePositionManager(positionManager).positions(tokenId);
return LiquidityAmounts.getAmountsForLiquidity(
sqrtRatioX96,
TickMath.getSqrtRatioAtTick(tickLower),
TickMath.getSqrtRatioAtTick(tickUpper),
liquidity
);
}
/// @notice Calculates the total fees owed to the token owner
/// @param positionManager The Uniswap V3 NonfungiblePositionManager
/// @param pool The Uniswap V3 Pool
/// @param tokenId The tokenId of the token for which to get the total fees
/// owed
/// @return amount0 The amount of fees owed in token0
/// @return amount1 The amount of fees owed in token1
function fees(
address positionManager,
address pool,
uint256 tokenId
) internal view returns (uint256 amount0, uint256 amount1) {
return _fees(pool, _get_fee_params(positionManager, tokenId));
}
struct FeeParams {
int24 tickLower;
int24 tickUpper;
uint128 liquidity;
uint256 positionFeeGrowthInside0LastX128;
uint256 positionFeeGrowthInside1LastX128;
uint256 tokensOwed0;
uint256 tokensOwed1;
}
function _get_fee_params(
address positionManager,
uint256 tokenId
) internal view virtual returns (FeeParams memory) {
(
,
,
,
,
,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 positionFeeGrowthInside0LastX128,
uint256 positionFeeGrowthInside1LastX128,
uint256 tokensOwed0,
uint256 tokensOwed1
) = INonfungiblePositionManager(positionManager).positions(tokenId);
return FeeParams({
tickLower: tickLower,
tickUpper: tickUpper,
liquidity: liquidity,
positionFeeGrowthInside0LastX128: positionFeeGrowthInside0LastX128,
positionFeeGrowthInside1LastX128: positionFeeGrowthInside1LastX128,
tokensOwed0: tokensOwed0,
tokensOwed1: tokensOwed1
});
}
function _fees(
address pool,
FeeParams memory feeParams
) private view returns (uint256 amount0, uint256 amount1) {
(
uint256 poolFeeGrowthInside0LastX128,
uint256 poolFeeGrowthInside1LastX128
) = _get_fee_growth_inside(
pool, feeParams.tickLower, feeParams.tickUpper
);
unchecked {
amount0 = feeParams.tokensOwed0
+ FullMath.mulDiv(
poolFeeGrowthInside0LastX128
- feeParams.positionFeeGrowthInside0LastX128,
feeParams.liquidity,
FixedPoint128.Q128
);
amount1 = feeParams.tokensOwed1
+ FullMath.mulDiv(
poolFeeGrowthInside1LastX128
- feeParams.positionFeeGrowthInside1LastX128,
feeParams.liquidity,
FixedPoint128.Q128
);
}
}
function _get_fee_growth_outside_tick(
address pool,
int24 tick
)
internal
view
virtual
returns (uint256 feeGrowthOutside0X128, uint256 feeGrowthOutside1X128)
{
(,, feeGrowthOutside0X128, feeGrowthOutside1X128,,,,) =
IUniswapV3Pool(pool).ticks(tick);
}
function _get_fee_growth_global(
address pool
)
internal
view
virtual
returns (uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128)
{
feeGrowthGlobal0X128 = IUniswapV3Pool(pool).feeGrowthGlobal0X128();
feeGrowthGlobal1X128 = IUniswapV3Pool(pool).feeGrowthGlobal1X128();
}
function _get_current_tick(
address pool
) internal view virtual returns (int24 tickCurrent) {
(, tickCurrent,,,,,) = IUniswapV3Pool(pool).slot0();
}
function _get_fee_growth_inside(
address pool,
int24 tickLower,
int24 tickUpper
)
internal
view
virtual
returns (uint256 feeGrowthInside0X128, uint256 feeGrowthInside1X128)
{
int24 tickCurrent = _get_current_tick(pool);
(uint256 lowerFeeGrowthOutside0X128, uint256 lowerFeeGrowthOutside1X128)
= _get_fee_growth_outside_tick(pool, tickLower);
(uint256 upperFeeGrowthOutside0X128, uint256 upperFeeGrowthOutside1X128)
= _get_fee_growth_outside_tick(pool, tickUpper);
if (tickCurrent < tickLower) {
unchecked {
feeGrowthInside0X128 =
lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128;
feeGrowthInside1X128 =
lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128;
}
} else if (tickCurrent < tickUpper) {
(uint256 feeGrowthGlobal0X128, uint256 feeGrowthGlobal1X128) =
_get_fee_growth_global(pool);
unchecked {
feeGrowthInside0X128 = feeGrowthGlobal0X128
- lowerFeeGrowthOutside0X128 - upperFeeGrowthOutside0X128;
feeGrowthInside1X128 = feeGrowthGlobal1X128
- lowerFeeGrowthOutside1X128 - upperFeeGrowthOutside1X128;
}
} else {
unchecked {
feeGrowthInside0X128 =
upperFeeGrowthOutside0X128 - lowerFeeGrowthOutside0X128;
feeGrowthInside1X128 =
upperFeeGrowthOutside1X128 - lowerFeeGrowthOutside1X128;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SwapParams } from "contracts/structs/LiquidityStructs.sol";
import {
NftAddLiquidity,
NftRemoveLiquidity,
NftPoolKey,
NftPoolInfo,
NftPositionInfo
} 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;
function swapExactETHForTokens(
SwapParams memory swap
) external payable;
function fee(
address pool,
uint256 tokenId // Used by UniswapV4
) external view returns (uint24);
function totalSupply(
address nftManager
) external view returns (uint256);
function getTokenId(
address nftManager,
address owner
) external view returns (uint256);
function earnedFees(
address nftManager,
address pool,
uint256 tokenId
) external view returns (uint256 fees0, uint256 fees1);
function positionLiquidity(
address nftManager,
uint256 tokenId
)
external
view
returns (int24 tickLower, int24 tickUpper, uint128 liquidity);
function positionPoolKey(
address poolFactory,
address nftManager,
uint256 tokenId
) external view returns (NftPoolKey memory);
function poolInfo(
address pool,
bytes32 poolId
) external view returns (NftPoolInfo memory);
// Maintained for backwards compatibility with NftSettingsRegistry
function positionInfo(
address nftManager,
uint256 tokenId
) external view returns (NftPositionInfo memory);
}// 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 { 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
pragma solidity ^0.8.0;
/// @title FixedPoint128
/// @notice A library for handling binary fixed point numbers, see
/// https://en.wikipedia.org/wiki/Q_(number_format)
library FixedPoint128 {
uint256 internal constant Q128 = 0x100000000000000000000000000000000;
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;
/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick)
/// as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
library TickMath {
/// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed
/// from log base 1.0001 of 2**-128
int24 internal constant MIN_TICK = -887_272;
/// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed
/// from log base 1.0001 of 2**128
int24 internal constant MAX_TICK = -MIN_TICK;
/// @dev The minimum value that can be returned from #getSqrtRatioAtTick.
/// Equivalent to getSqrtRatioAtTick(MIN_TICK)
uint160 internal constant MIN_SQRT_RATIO = 4_295_128_739;
/// @dev The maximum value that can be returned from #getSqrtRatioAtTick.
/// Equivalent to getSqrtRatioAtTick(MAX_TICK)
uint160 internal constant MAX_SQRT_RATIO =
1_461_446_703_485_210_103_287_273_052_203_988_822_378_723_970_342;
/// @notice Calculates sqrt(1.0001^tick) * 2^96
/// @dev Throws if |tick| > max tick
/// @param tick The input tick for the above formula
/// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt
/// of the ratio of the two assets (token1/token0)
/// at the given tick
function getSqrtRatioAtTick(
int24 tick
) internal pure returns (uint160 sqrtPriceX96) {
uint256 absTick =
tick < 0 ? uint256(uint24(-tick)) : uint256(uint24(tick));
require(absTick <= uint256(int256(MAX_TICK)), "T");
uint256 ratio = absTick & 0x1 != 0
? 0xfffcb933bd6fad37aa2d162d1a594001
: 0x100000000000000000000000000000000;
if (absTick & 0x2 != 0) {
ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
}
if (absTick & 0x4 != 0) {
ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
}
if (absTick & 0x8 != 0) {
ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
}
if (absTick & 0x10 != 0) {
ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
}
if (absTick & 0x20 != 0) {
ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
}
if (absTick & 0x40 != 0) {
ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
}
if (absTick & 0x80 != 0) {
ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
}
if (absTick & 0x100 != 0) {
ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
}
if (absTick & 0x200 != 0) {
ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
}
if (absTick & 0x400 != 0) {
ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
}
if (absTick & 0x800 != 0) {
ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
}
if (absTick & 0x1000 != 0) {
ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
}
if (absTick & 0x2000 != 0) {
ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
}
if (absTick & 0x4000 != 0) {
ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
}
if (absTick & 0x8000 != 0) {
ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
}
if (absTick & 0x10000 != 0) {
ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
}
if (absTick & 0x20000 != 0) {
ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
}
if (absTick & 0x40000 != 0) {
ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
}
if (absTick & 0x80000 != 0) {
ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;
}
if (tick > 0) ratio = type(uint256).max / ratio;
// this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
// we then downcast because we know the result always fits within 160
// bits due to our tick input constraint
// we round up in the division so getTickAtSqrtRatio of the output price
// is always consistent
sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
}
/// @notice Calculates the greatest tick value such that
/// getRatioAtTick(tick) <= ratio
/// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is
/// the lowest value getRatioAtTick may
/// ever return.
/// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a
/// Q64.96
/// @return tick The greatest tick for which the ratio is less than or equal
/// to the input ratio
function getTickAtSqrtRatio(
uint160 sqrtPriceX96
) internal pure returns (int24 tick) {
// second inequality must be < because the price can never reach the
// price at the max tick
require(
sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, "R"
);
uint256 ratio = uint256(sqrtPriceX96) << 32;
uint256 r = ratio;
uint256 msb = 0;
assembly {
let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(5, gt(r, 0xFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(4, gt(r, 0xFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(3, gt(r, 0xFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(2, gt(r, 0xF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(1, gt(r, 0x3))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := gt(r, 0x1)
msb := or(msb, f)
}
if (msb >= 128) r = ratio >> (msb - 127);
else r = ratio << (127 - msb);
int256 log_2 = (int256(msb) - 128) << 64;
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(63, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(62, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(61, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(60, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(59, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(58, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(57, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(56, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(55, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(54, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(53, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(52, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(51, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(50, f))
}
int256 log_sqrt10001 = log_2 * 255_738_958_999_603_826_347_141; // 128.128
// number
int24 tickLow = int24(
(log_sqrt10001 - 3_402_992_956_809_132_418_596_140_100_660_247_210)
>> 128
);
int24 tickHi = int24(
(
log_sqrt10001
+ 291_339_464_771_989_622_907_027_621_153_398_088_495
) >> 128
);
tick = tickLow == tickHi
? tickLow
: getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;
import "contracts/interfaces/external/uniswap/v3/libraries/FullMath.sol";
import "contracts/interfaces/external/uniswap/v3/libraries/FixedPoint96.sol";
/// @title Liquidity amount functions
/// @notice Provides functions for computing liquidity amounts from token
/// amounts and prices
library LiquidityAmounts {
/// @notice Downcasts uint256 to uint128
/// @param x The uint258 to be downcasted
/// @return y The passed value, downcasted to uint128
function toUint128(
uint256 x
) private pure returns (uint128 y) {
require((y = uint128(x)) == x);
}
/// @notice Computes the amount of liquidity received for a given amount of
/// token0 and price range
/// @dev Calculates amount0 * (sqrt(upper) * sqrt(lower)) / (sqrt(upper) -
/// sqrt(lower))
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param amount0 The amount0 being sent in
/// @return liquidity The amount of returned liquidity
function getLiquidityForAmount0(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint256 amount0
) internal pure returns (uint128 liquidity) {
if (sqrtRatioAX96 > sqrtRatioBX96) {
(sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
}
uint256 intermediate =
FullMath.mulDiv(sqrtRatioAX96, sqrtRatioBX96, FixedPoint96.Q96);
return toUint128(
FullMath.mulDiv(
amount0, intermediate, sqrtRatioBX96 - sqrtRatioAX96
)
);
}
/// @notice Computes the amount of liquidity received for a given amount of
/// token1 and price range
/// @dev Calculates amount1 / (sqrt(upper) - sqrt(lower)).
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param amount1 The amount1 being sent in
/// @return liquidity The amount of returned liquidity
function getLiquidityForAmount1(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint256 amount1
) internal pure returns (uint128 liquidity) {
if (sqrtRatioAX96 > sqrtRatioBX96) {
(sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
}
return toUint128(
FullMath.mulDiv(
amount1, FixedPoint96.Q96, sqrtRatioBX96 - sqrtRatioAX96
)
);
}
/// @notice Computes the maximum amount of liquidity received for a given
/// amount of token0, token1, the current
/// pool prices and the prices at the tick boundaries
/// @param sqrtRatioX96 A sqrt price representing the current pool prices
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param amount0 The amount of token0 being sent in
/// @param amount1 The amount of token1 being sent in
/// @return liquidity The maximum amount of liquidity received
function getLiquidityForAmounts(
uint160 sqrtRatioX96,
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint256 amount0,
uint256 amount1
) internal pure returns (uint128 liquidity) {
if (sqrtRatioAX96 > sqrtRatioBX96) {
(sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
}
if (sqrtRatioX96 <= sqrtRatioAX96) {
liquidity =
getLiquidityForAmount0(sqrtRatioAX96, sqrtRatioBX96, amount0);
} else if (sqrtRatioX96 < sqrtRatioBX96) {
uint128 liquidity0 =
getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, amount0);
uint128 liquidity1 =
getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, amount1);
liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;
} else {
liquidity =
getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioBX96, amount1);
}
}
/// @notice Computes the amount of token0 for a given amount of liquidity
/// and a price range
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param liquidity The liquidity being valued
/// @return amount0 The amount of token0
function getAmount0ForLiquidity(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint128 liquidity
) internal pure returns (uint256 amount0) {
if (sqrtRatioAX96 > sqrtRatioBX96) {
(sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
}
return FullMath.mulDiv(
uint256(liquidity) << FixedPoint96.RESOLUTION,
sqrtRatioBX96 - sqrtRatioAX96,
sqrtRatioBX96
) / sqrtRatioAX96;
}
/// @notice Computes the amount of token1 for a given amount of liquidity
/// and a price range
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param liquidity The liquidity being valued
/// @return amount1 The amount of token1
function getAmount1ForLiquidity(
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint128 liquidity
) internal pure returns (uint256 amount1) {
if (sqrtRatioAX96 > sqrtRatioBX96) {
(sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
}
return FullMath.mulDiv(
liquidity, sqrtRatioBX96 - sqrtRatioAX96, FixedPoint96.Q96
);
}
/// @notice Computes the token0 and token1 value for a given amount of
/// liquidity, the current
/// pool prices and the prices at the tick boundaries
/// @param sqrtRatioX96 A sqrt price representing the current pool prices
/// @param sqrtRatioAX96 A sqrt price representing the first tick boundary
/// @param sqrtRatioBX96 A sqrt price representing the second tick boundary
/// @param liquidity The liquidity being valued
/// @return amount0 The amount of token0
/// @return amount1 The amount of token1
function getAmountsForLiquidity(
uint160 sqrtRatioX96,
uint160 sqrtRatioAX96,
uint160 sqrtRatioBX96,
uint128 liquidity
) internal pure returns (uint256 amount0, uint256 amount1) {
if (sqrtRatioAX96 > sqrtRatioBX96) {
(sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);
}
if (sqrtRatioX96 <= sqrtRatioAX96) {
amount0 =
getAmount0ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);
} else if (sqrtRatioX96 < sqrtRatioBX96) {
amount0 =
getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, liquidity);
amount1 =
getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, liquidity);
} else {
amount1 =
getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioBX96, liquidity);
}
}
}// 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: MIT
pragma solidity ^0.8.0;
/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an
/// intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division
/// where an intermediate value overflows 256 bits
library FullMath {
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws
/// if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
/// @dev Credit to Remco Bloemen under MIT license
/// https://xn--2-umb.com/21/muldiv
function mulDiv(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2**256 + prod0
uint256 prod0 = a * b; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
require(denominator > prod1);
// Handle non-overflow cases, 256 by 256 division
if (prod1 == 0) {
assembly ("memory-safe") {
result := div(prod0, denominator)
}
return result;
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1
// prod0]
// Compute remainder using mulmod
uint256 remainder;
assembly ("memory-safe") {
remainder := mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit number
assembly ("memory-safe") {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
uint256 twos = (0 - denominator) & denominator;
// Divide denominator by power of two
assembly ("memory-safe") {
denominator := div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of two
assembly ("memory-safe") {
prod0 := div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need
// to flip `twos` such that it is 2**256 / twos.
// If twos is zero, then it becomes one
assembly ("memory-safe") {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
// Invert denominator mod 2**256
// Now that denominator is an odd number, it has an inverse
// modulo 2**256 such that denominator * inv = 1 mod 2**256.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, denominator * inv = 1 mod 2**4
uint256 inv = (3 * denominator) ^ 2;
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv *= 2 - denominator * inv; // inverse mod 2**8
inv *= 2 - denominator * inv; // inverse mod 2**16
inv *= 2 - denominator * inv; // inverse mod 2**32
inv *= 2 - denominator * inv; // inverse mod 2**64
inv *= 2 - denominator * inv; // inverse mod 2**128
inv *= 2 - denominator * inv; // inverse mod 2**256
// Because the division is now exact we can divide by multiplying
// with the modular inverse of denominator. This will give us the
// correct result modulo 2**256. Since the preconditions guarantee
// that the outcome is less than 2**256, this is the final result.
// We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inv;
return result;
}
}
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws
/// if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
function mulDivRoundingUp(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) != 0) {
require(++result > 0);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title FixedPoint96
/// @notice A library for handling binary fixed point numbers, see https://en.wikipedia.org/wiki/Q_(number_format)
/// @dev Used in SqrtPriceMath.sol
library FixedPoint96 {
uint8 internal constant RESOLUTION = 96;
uint256 internal constant Q96 = 0x1000000000000000000000000;
}{
"remappings": [
"solmate/=lib/solmate/src/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"@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
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IGaugeRegistryVoter","name":"voter_","type":"address"},{"internalType":"contract NuriGaugeConnector","name":"nuriGaugeConnector_","type":"address"},{"internalType":"contract INuriPairFactory","name":"nuriPairFactory_","type":"address"},{"internalType":"contract NuriV3Connector","name":"nuriV3Connector_","type":"address"},{"internalType":"address","name":"nuriCLGaugeFactory_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"connectorOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nuriCLGaugeFactory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nuriGaugeConnector","outputs":[{"internalType":"contract NuriGaugeConnector","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nuriPairFactory","outputs":[{"internalType":"contract INuriPairFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nuriV3Connector","outputs":[{"internalType":"contract NuriV3Connector","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"contract IGaugeRegistryVoter","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
61012060405234801561001157600080fd5b5060405161060238038061060283398101604081905261003091610071565b6001600160a01b0394851660805292841660a05290831660c052821660e05216610100526100e6565b6001600160a01b038116811461006e57600080fd5b50565b600080600080600060a0868803121561008957600080fd5b855161009481610059565b60208701519095506100a581610059565b60408701519094506100b681610059565b60608701519093506100c781610059565b60808701519092506100d881610059565b809150509295509295909350565b60805160a05160c05160e051610100516104b261015060003960008181610124015261039801526000818160d601526103d201526000818160af015261020701526000818160fd015261030c015260008181606c01528181610176015261023101526104b26000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806346c96aac1461006757806354aa59ce146100aa57806357fa5bf4146100d15780637ca7f843146100f85780638b0465241461011f578063c79aeaae14610146575b600080fd5b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61008e610154366004610419565b60405163aa79979b60e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063aa79979b90602401602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e3919061043d565b156103f95760405163036b50d960e11b81526001600160a01b0383811660048301527f000000000000000000000000000000000000000000000000000000000000000081169163e5e31b13917f000000000000000000000000000000000000000000000000000000000000000016906306d6a1b290602401602060405180830381865afa158015610278573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061029c919061045f565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156102e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610304919061043d565b1561033057507f0000000000000000000000000000000000000000000000000000000000000000919050565b6000826001600160a01b0316630d52333c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610370573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610394919061045f565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316036103f757507f000000000000000000000000000000000000000000000000000000000000000092915050565b505b506000919050565b6001600160a01b038116811461041657600080fd5b50565b60006020828403121561042b57600080fd5b813561043681610401565b9392505050565b60006020828403121561044f57600080fd5b8151801515811461043657600080fd5b60006020828403121561047157600080fd5b81516104368161040156fea264697066735822122038c569962b52d9934fc0c7fc5316c4a4be0b7b687369cae9afbc0ec3b925461464736f6c63430008130033000000000000000000000000aaaf3d9cdd3602d117c67d80eec37a160c8d98690000000000000000000000004b7c6f757b6a62c9359eeaef9a7097e0b70cb202000000000000000000000000aaa16c016bf556fcd620328f0759252e29b1ab570000000000000000000000008bc1824b5fea1cc95fe221a9fe4e9878d360466e000000000000000000000000aaa2d4987eed427ba5e2c933eefcd75c84b446b7
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100625760003560e01c806346c96aac1461006757806354aa59ce146100aa57806357fa5bf4146100d15780637ca7f843146100f85780638b0465241461011f578063c79aeaae14610146575b600080fd5b61008e7f000000000000000000000000aaaf3d9cdd3602d117c67d80eec37a160c8d986981565b6040516001600160a01b03909116815260200160405180910390f35b61008e7f000000000000000000000000aaa16c016bf556fcd620328f0759252e29b1ab5781565b61008e7f0000000000000000000000008bc1824b5fea1cc95fe221a9fe4e9878d360466e81565b61008e7f0000000000000000000000004b7c6f757b6a62c9359eeaef9a7097e0b70cb20281565b61008e7f000000000000000000000000aaa2d4987eed427ba5e2c933eefcd75c84b446b781565b61008e610154366004610419565b60405163aa79979b60e01b81526001600160a01b0382811660048301526000917f000000000000000000000000aaaf3d9cdd3602d117c67d80eec37a160c8d98699091169063aa79979b90602401602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e3919061043d565b156103f95760405163036b50d960e11b81526001600160a01b0383811660048301527f000000000000000000000000aaa16c016bf556fcd620328f0759252e29b1ab5781169163e5e31b13917f000000000000000000000000aaaf3d9cdd3602d117c67d80eec37a160c8d986916906306d6a1b290602401602060405180830381865afa158015610278573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061029c919061045f565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156102e0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610304919061043d565b1561033057507f0000000000000000000000004b7c6f757b6a62c9359eeaef9a7097e0b70cb202919050565b6000826001600160a01b0316630d52333c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610370573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610394919061045f565b90507f000000000000000000000000aaa2d4987eed427ba5e2c933eefcd75c84b446b76001600160a01b0316816001600160a01b0316036103f757507f0000000000000000000000008bc1824b5fea1cc95fe221a9fe4e9878d360466e92915050565b505b506000919050565b6001600160a01b038116811461041657600080fd5b50565b60006020828403121561042b57600080fd5b813561043681610401565b9392505050565b60006020828403121561044f57600080fd5b8151801515811461043657600080fd5b60006020828403121561047157600080fd5b81516104368161040156fea264697066735822122038c569962b52d9934fc0c7fc5316c4a4be0b7b687369cae9afbc0ec3b925461464736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000aaaf3d9cdd3602d117c67d80eec37a160c8d98690000000000000000000000004b7c6f757b6a62c9359eeaef9a7097e0b70cb202000000000000000000000000aaa16c016bf556fcd620328f0759252e29b1ab570000000000000000000000008bc1824b5fea1cc95fe221a9fe4e9878d360466e000000000000000000000000aaa2d4987eed427ba5e2c933eefcd75c84b446b7
-----Decoded View---------------
Arg [0] : voter_ (address): 0xAAAf3D9CDD3602d117c67D80eEC37a160C8d9869
Arg [1] : nuriGaugeConnector_ (address): 0x4b7C6f757b6A62c9359eeaef9a7097e0B70cb202
Arg [2] : nuriPairFactory_ (address): 0xAAA16c016BF556fcD620328f0759252E29b1AB57
Arg [3] : nuriV3Connector_ (address): 0x8bc1824B5FEa1CC95fE221a9fE4e9878D360466E
Arg [4] : nuriCLGaugeFactory_ (address): 0xAAA2D4987EEd427Ba5E2c933EeFCD75C84b446B7
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000aaaf3d9cdd3602d117c67d80eec37a160c8d9869
Arg [1] : 0000000000000000000000004b7c6f757b6a62c9359eeaef9a7097e0b70cb202
Arg [2] : 000000000000000000000000aaa16c016bf556fcd620328f0759252e29b1ab57
Arg [3] : 0000000000000000000000008bc1824b5fea1cc95fe221a9fe4e9878d360466e
Arg [4] : 000000000000000000000000aaa2d4987eed427ba5e2c933eefcd75c84b446b7
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.