Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers.
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | ||||
|---|---|---|---|---|---|---|---|
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31255039 | 2 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX | |||||
| 31254977 | 4 mins ago | 0 FRAX |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SuperchainGaugeRegistry
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 { VelodromeGaugeConnector } from
"contracts/connectors/velodrome/VelodromeGaugeConnector.sol";
import { SlipstreamGaugeConnector } from
"contracts/connectors/velodrome/SlipstreamGaugeConnector.sol";
import { IGaugeRegistryVoter } from "contracts/connectors/GaugeRegistry.sol";
interface IIsPool {
function isPool(
address pool
) external view returns (bool);
}
contract SuperchainGaugeRegistry is ICustomConnectorRegistry {
IGaugeRegistryVoter public immutable voter;
IIsPool public immutable v2PoolFactory;
IIsPool public immutable slipstreamPoolFactory;
VelodromeGaugeConnector public immutable v2GaugeConnector;
SlipstreamGaugeConnector public immutable slipstreamGaugeConnector;
constructor(
IGaugeRegistryVoter voter_,
IIsPool v2PoolFactory_,
IIsPool slipstreamPoolFactory_,
VelodromeGaugeConnector v2GaugeConnector_,
SlipstreamGaugeConnector slipstreamGaugeConnector_
) {
voter = voter_;
v2PoolFactory = v2PoolFactory_;
slipstreamPoolFactory = slipstreamPoolFactory_;
v2GaugeConnector = v2GaugeConnector_;
slipstreamGaugeConnector = slipstreamGaugeConnector_;
}
function connectorOf(
address target
) external view override returns (address) {
if (voter.isGauge(target)) {
address pool = voter.poolForGauge(target);
if (v2PoolFactory.isPool(pool)) {
return address(v2GaugeConnector);
}
if (slipstreamPoolFactory.isPool(pool)) {
return address(slipstreamGaugeConnector);
}
}
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 { IFarmConnector, Farm } from "contracts/interfaces/IFarmConnector.sol";
import { IGauge } from "contracts/interfaces/external/aerodrome/IGauge.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
contract VelodromeGaugeConnector is IFarmConnector {
function deposit(
Farm calldata farm,
address token,
bytes memory // extraData
) external override {
uint256 amount = IERC20(token).balanceOf(address(this));
SafeTransferLib.safeApprove(token, farm.stakingContract, amount);
IGauge(farm.stakingContract).deposit(amount);
}
function withdraw(
Farm calldata farm,
uint256 amount,
bytes memory // extraData
) external override {
IGauge(farm.stakingContract).withdraw(amount);
}
function claim(
Farm memory farm,
bytes memory // extraData
) external override {
IGauge(farm.stakingContract).getReward(address(this));
}
function balanceOf(
Farm calldata farm,
address user
) external view override returns (uint256) {
return IGauge(farm.stakingContract).balanceOf(user);
}
function earned(
Farm calldata farm,
address user,
address[] calldata // rewardTokens
) external view override returns (uint256[] memory) {
uint256[] memory rewards = new uint256[](1);
rewards[0] = IGauge(farm.stakingContract).earned(user);
return rewards;
}
function isStaked(
Farm calldata,
address // user
) external pure override returns (bool) {
return true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {
INftFarmConnector,
NftPosition
} from "contracts/interfaces/INftFarmConnector.sol";
import { ICLGauge } from "contracts/interfaces/external/aerodrome/ICLGauge.sol";
import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
contract SlipstreamGaugeConnector is INftFarmConnector {
function depositExistingNft(
NftPosition calldata position,
bytes calldata // extraData
) external {
IERC721(address(position.nft)).approve(
position.farm.stakingContract, position.tokenId
);
ICLGauge(position.farm.stakingContract).deposit(position.tokenId);
}
function withdrawNft(
NftPosition calldata position,
bytes calldata // extraData
) external {
ICLGauge(position.farm.stakingContract).withdraw(position.tokenId);
}
function claim(
NftPosition calldata position,
address[] memory, // rewardTokens
uint128, // maxAmount0,
uint128, // maxAmount1,
bytes calldata // extraData
) external {
ICLGauge(position.farm.stakingContract).getReward(position.tokenId);
}
function isStaked(
address user,
NftPosition calldata position
) external view virtual override returns (bool) {
return ICLGauge(position.farm.stakingContract).stakedContains(
user, position.tokenId
);
}
function earned(
address user,
NftPosition calldata position,
address[] memory // rewardTokens
) external view virtual override returns (uint256[] memory) {
uint256[] memory rewardAmounts = new uint256[](1);
rewardAmounts[0] = ICLGauge(position.farm.stakingContract).earned(
user, position.tokenId
) + ICLGauge(position.farm.stakingContract).rewards(position.tokenId);
return rewardAmounts;
}
}// 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: 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.0;
import { Farm } from "contracts/structs/FarmStrategyStructs.sol";
interface IFarmConnector {
function deposit(
Farm calldata farm,
address token,
bytes memory extraData
) external;
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.0;
interface IGauge {
error NotAlive();
error NotAuthorized();
error NotVoter();
error NotTeam();
error RewardRateTooHigh();
error ZeroAmount();
error ZeroRewardRate();
event Deposit(address indexed from, address indexed to, uint256 amount);
event Withdraw(address indexed from, uint256 amount);
event NotifyReward(address indexed from, uint256 amount);
event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);
event ClaimRewards(address indexed from, uint256 amount);
/// @notice Address of the pool LP token which is deposited (staked) for
/// rewards
function stakingToken() external view returns (address);
/// @notice Address of the token (AERO) rewarded to stakers
function rewardToken() external view returns (address);
/// @notice Address of the FeesVotingReward contract linked to the gauge
function feesVotingReward() external view returns (address);
/// @notice Address of Protocol Voter
function voter() external view returns (address);
/// @notice Address of Protocol Voting Escrow
function ve() external view returns (address);
/// @notice Returns if gauge is linked to a legitimate Protocol pool
function isPool() external view returns (bool);
/// @notice Timestamp end of current rewards period
function periodFinish() external view returns (uint256);
/// @notice Current reward rate of rewardToken to distribute per second
function rewardRate() external view returns (uint256);
/// @notice Most recent timestamp contract has updated state
function lastUpdateTime() external view returns (uint256);
/// @notice Most recent stored value of rewardPerToken
function rewardPerTokenStored() external view returns (uint256);
/// @notice Amount of stakingToken deposited for rewards
function totalSupply() external view returns (uint256);
/// @notice Get the amount of stakingToken deposited by an account
function balanceOf(
address
) external view returns (uint256);
/// @notice Cached rewardPerTokenStored for an account based on their most
/// recent action
function userRewardPerTokenPaid(
address
) external view returns (uint256);
/// @notice Cached amount of rewardToken earned for an account
function rewards(
address
) external view returns (uint256);
/// @notice View to see the rewardRate given the timestamp of the start of
/// the epoch
function rewardRateByEpoch(
uint256
) external view returns (uint256);
/// @notice Cached amount of fees generated from the Pool linked to the
/// Gauge of token0
function fees0() external view returns (uint256);
/// @notice Cached amount of fees generated from the Pool linked to the
/// Gauge of token1
function fees1() external view returns (uint256);
/// @notice Get the current reward rate per unit of stakingToken deposited
function rewardPerToken() external view returns (uint256 _rewardPerToken);
/// @notice Returns the last time the reward was modified or periodFinish if
/// the reward has ended
function lastTimeRewardApplicable() external view returns (uint256 _time);
/// @notice Returns accrued balance to date from last claim / first deposit.
function earned(
address _account
) external view returns (uint256 _earned);
/// @notice Total amount of rewardToken to distribute for the current
/// rewards period
function left() external view returns (uint256 _left);
/// @notice Retrieve rewards for an address.
/// @dev Throws if not called by same address or voter.
/// @param _account .
function getReward(
address _account
) external;
/// @notice Deposit LP tokens into gauge for msg.sender
/// @param _amount .
function deposit(
uint256 _amount
) external;
/// @notice Deposit LP tokens into gauge for any user
/// @param _amount .
/// @param _recipient Recipient to give balance to
function deposit(uint256 _amount, address _recipient) external;
/// @notice Withdraw LP tokens for user
/// @param _amount .
function withdraw(
uint256 _amount
) external;
/// @dev Notifies gauge of gauge rewards. Assumes gauge reward tokens is 18
/// decimals.
/// If not 18 decimals, rewardRate may have rounding issues.
function notifyRewardAmount(
uint256 amount
) external;
/// @dev Notifies gauge of gauge rewards without distributing its fees.
/// Assumes gauge reward tokens is 18 decimals.
/// If not 18 decimals, rewardRate may have rounding issues.
function notifyRewardWithoutClaim(
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 { NftPosition } from "contracts/structs/NftFarmStrategyStructs.sol";
interface INftFarmConnector {
function depositExistingNft(
NftPosition calldata position,
bytes calldata extraData
) external;
function withdrawNft(
NftPosition calldata position,
bytes calldata extraData
) external;
function claim(
NftPosition calldata position,
address[] memory rewardTokens,
uint128 maxAmount0, // For collecting
uint128 maxAmount1,
bytes calldata extraData
) external;
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: MIT
pragma solidity ^0.8.0;
interface ICLGauge {
event NotifyReward(address indexed from, uint256 amount);
event Deposit(
address indexed user,
uint256 indexed tokenId,
uint128 indexed liquidityToStake
);
event Withdraw(
address indexed user,
uint256 indexed tokenId,
uint128 indexed liquidityToStake
);
event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1);
event ClaimRewards(address indexed from, uint256 amount);
/// @notice NonfungiblePositionManager used to create nfts this gauge
/// accepts
function nft() external view returns (address);
/// @notice Voter contract gauge receives emissions from
function voter() external view returns (address);
/// @notice Address of the CL pool linked to the gauge
function pool() external view returns (address);
/// @notice Address of the factory that created this gauge
function gaugeFactory() external view returns (address);
/// @notice Address of the FeesVotingReward contract linked to the gauge
function feesVotingReward() external view returns (address);
/// @notice Timestamp end of current rewards period
function periodFinish() external view returns (uint256);
/// @notice Current reward rate of rewardToken to distribute per second
function rewardRate() external view returns (uint256);
/// @notice Claimable rewards by tokenId
function rewards(
uint256 tokenId
) external view returns (uint256);
/// @notice Most recent timestamp tokenId called updateRewards
function lastUpdateTime(
uint256 tokenId
) external view returns (uint256);
/// @notice View to see the rewardRate given the timestamp of the start of
/// the epoch
function rewardRateByEpoch(
uint256
) external view returns (uint256);
/// @notice Cached amount of fees generated from the Pool linked to the
/// Gauge of token0
function fees0() external view returns (uint256);
/// @notice Cached amount of fees generated from the Pool linked to the
/// Gauge of token1
function fees1() external view returns (uint256);
/// @notice Cached address of token0, corresponding to token0 of the pool
function token0() external view returns (address);
/// @notice Cached address of token1, corresponding to token1 of the pool
function token1() external view returns (address);
/// @notice Cached tick spacing of the pool.
function tickSpacing() external view returns (int24);
/// @notice Total amount of rewardToken to distribute for the current
/// rewards period
function left() external view returns (uint256 _left);
/// @notice Address of the emissions token
function rewardToken() external view returns (address);
/// @notice To provide compatibility support with the old voter
function isPool() external view returns (bool);
/// @notice Returns the rewardGrowthInside of the position at the last user
/// action (deposit, withdraw, getReward)
/// @param tokenId The tokenId of the position
/// @return The rewardGrowthInside for the position
function rewardGrowthInside(
uint256 tokenId
) external view returns (uint256);
/// @notice Called on gauge creation by CLGaugeFactory
/// @param _pool The address of the pool
/// @param _feesVotingReward The address of the feesVotingReward contract
/// @param _rewardToken The address of the reward token
/// @param _voter The address of the voter contract
/// @param _nft The address of the nft position manager contract
/// @param _token0 The address of token0 of the pool
/// @param _token1 The address of token1 of the pool
/// @param _tickSpacing The tick spacing of the pool
/// @param _isPool Whether the attached pool is a real pool or not
function initialize(
address _pool,
address _feesVotingReward,
address _rewardToken,
address _voter,
address _nft,
address _token0,
address _token1,
int24 _tickSpacing,
bool _isPool
) external;
/// @notice Returns the claimable rewards for a given account and tokenId
/// @dev Throws if account is not the position owner
/// @dev pool.updateRewardsGrowthGlobal() needs to be called first, to
/// return the correct claimable rewards
/// @param account The address of the user
/// @param tokenId The tokenId of the position
/// @return The amount of claimable reward
function earned(
address account,
uint256 tokenId
) external view returns (uint256);
/// @notice Retrieve rewards for all tokens owned by an account
/// @dev Throws if not called by the voter
/// @param account The account of the user
function getReward(
address account
) external;
/// @notice Retrieve rewards for a tokenId
/// @dev Throws if not called by the position owner
/// @param tokenId The tokenId of the position
function getReward(
uint256 tokenId
) external;
/// @notice Notifies gauge of gauge rewards.
/// @param amount Amount of gauge rewards (emissions) to notify. Must be
/// greater than 604_800.
function notifyRewardAmount(
uint256 amount
) external;
/// @dev Notifies gauge of gauge rewards without distributing its fees.
/// Assumes gauge reward tokens is 18 decimals.
/// If not 18 decimals, rewardRate may have rounding issues.
/// @param amount Amount of gauge rewards (emissions) to notify. Must be
/// greater than 604_800.
function notifyRewardWithoutClaim(
uint256 amount
) external;
/// @notice Used to deposit a CL position into the gauge
/// @notice Allows the user to receive emissions instead of fees
/// @param tokenId The tokenId of the position
function deposit(
uint256 tokenId
) external;
/// @notice Used to withdraw a CL position from the gauge
/// @notice Allows the user to receive fees instead of emissions
/// @notice Outstanding emissions will be collected on withdrawal
/// @param tokenId The tokenId of the position
function withdraw(
uint256 tokenId
) external;
/// @notice Used to increase liquidity of a staked position
/// @param tokenId The tokenId of the position
/// @param amount0Desired The desired amount of token0 to be staked,
/// @param amount1Desired The desired amount of token1 to be staked,
/// @param amount0Min The minimum amount of token0 to spend, which serves as
/// a slippage check,
/// @param amount1Min The minimum amount of token1 to spend, which serves as
/// a slippage check,
/// @param 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 required to obtain new liquidity
/// amount
/// @return amount1 The amount of token1 required to obtain new liquidity
/// amount
function increaseStakedLiquidity(
uint256 tokenId,
uint256 amount0Desired,
uint256 amount1Desired,
uint256 amount0Min,
uint256 amount1Min,
uint256 deadline
) external returns (uint128 liquidity, uint256 amount0, uint256 amount1);
/// @notice Used to decrease liquidity of a staked position
/// @param tokenId The tokenId of the position
/// @param liquidity The amount of liquidity to be unstaked from the gauge
/// @param amount0Min The minimum amount of token0 that should be accounted
/// for the burned liquidity,
/// @param amount1Min The minimum amount of token1 that should be accounted
/// for the burned liquidity,
/// @param deadline The time by which the transaction must be included to
/// effect the change
/// @return amount0 The amount of token0 decreased from position
/// @return amount1 The amount of token1 decreased from position
function decreaseStakedLiquidity(
uint256 tokenId,
uint128 liquidity,
uint256 amount0Min,
uint256 amount1Min,
uint256 deadline
) external returns (uint256 amount0, uint256 amount1);
/// @notice Fetch all tokenIds staked by a given account
/// @param depositor The address of the user
/// @return The tokenIds of the staked positions
function stakedValues(
address depositor
) external view returns (uint256[] memory);
/// @notice Fetch a staked tokenId by index
/// @param depositor The address of the user
/// @param index The index of the staked tokenId
/// @return The tokenId of the staked position
function stakedByIndex(
address depositor,
uint256 index
) external view returns (uint256);
/// @notice Check whether a position is staked in the gauge by a certain
/// user
/// @param depositor The address of the user
/// @param tokenId The tokenId of the position
/// @return Whether the position is staked in the gauge
function stakedContains(
address depositor,
uint256 tokenId
) external view returns (bool);
/// @notice The amount of positions staked in the gauge by a certain user
/// @param depositor The address of the user
/// @return The amount of positions staked in the gauge
function stakedLength(
address depositor
) external view returns (uint256);
}// 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 { ZapIn, ZapOut } from "contracts/structs/ZapStructs.sol";
import { SwapParams } from "contracts/structs/SwapStructs.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: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public immutable decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
// Cannot underflow because a user's balance
// will never be larger than the total supply.
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
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/SwapStructs.sol";
import { Farm } from "contracts/structs/FarmStrategyStructs.sol";
struct NftPosition {
Farm farm;
INonfungiblePositionManager nft;
uint256 tokenId;
}
struct NftIncrease {
address[] tokensIn;
uint256[] amountsIn;
NftZapIn zap;
bytes extraData;
}
struct NftDeposit {
Farm farm;
INonfungiblePositionManager nft;
NftIncrease increase;
}
struct NftWithdraw {
NftZapOut zap;
address[] tokensOut;
bytes extraData;
}
struct SimpleNftHarvest {
address[] rewardTokens;
uint128 amount0Max;
uint128 amount1Max;
bytes extraData;
}
struct NftHarvest {
SimpleNftHarvest harvest;
SwapParams[] swaps;
address[] outputTokens;
address[] sweepTokens;
}
struct NftCompound {
SimpleNftHarvest harvest;
NftZapIn zap;
}
struct NftRebalance {
IUniswapV3Pool pool;
NftPosition position;
NftHarvest harvest;
NftWithdraw withdraw;
NftIncrease increase;
}
struct NftMove {
IUniswapV3Pool pool;
NftPosition position;
NftHarvest harvest;
NftWithdraw withdraw;
NftDeposit deposit;
}// SPDX-License-Identifier: MIT
// 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;
import { SwapParams } from "contracts/structs/SwapStructs.sol";
import {
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;
struct SwapParams {
address tokenApproval;
address router;
uint256 amountIn;
uint256 desiredAmountOut;
uint256 minAmountOut;
address tokenIn;
address tokenOut;
bytes extraData;
}// 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.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.17;
import { SwapParams } from "contracts/structs/SwapStructs.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;
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;
}// 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 { 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
// 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);
}{
"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 IIsPool","name":"v2PoolFactory_","type":"address"},{"internalType":"contract IIsPool","name":"slipstreamPoolFactory_","type":"address"},{"internalType":"contract VelodromeGaugeConnector","name":"v2GaugeConnector_","type":"address"},{"internalType":"contract SlipstreamGaugeConnector","name":"slipstreamGaugeConnector_","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":"slipstreamGaugeConnector","outputs":[{"internalType":"contract SlipstreamGaugeConnector","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"slipstreamPoolFactory","outputs":[{"internalType":"contract IIsPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"v2GaugeConnector","outputs":[{"internalType":"contract VelodromeGaugeConnector","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"v2PoolFactory","outputs":[{"internalType":"contract IIsPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"contract IGaugeRegistryVoter","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
61012060405234801561001157600080fd5b506040516105f53803806105f583398101604081905261003091610071565b6001600160a01b0394851660805292841660a05290831660c052821660e05216610100526100e6565b6001600160a01b038116811461006e57600080fd5b50565b600080600080600060a0868803121561008957600080fd5b855161009481610059565b60208701519095506100a581610059565b60408701519094506100b681610059565b60608701519093506100c781610059565b60808701519092506100d881610059565b809150509295509295909350565b60805160a05160c05160e051610100516104a56101506000396000818161012401526103c5015260008181606c015261030e01526000818160d6015261035201526000818160fd015261029901526000818160af01528181610176015261020a01526104a56000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c80632a717cde1461006757806346c96aac146100aa57806386811bc7146100d1578063ab138846146100f8578063b5224a861461011f578063c79aeaae14610146575b600080fd5b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61008e61015436600461040c565b60405163aa79979b60e01b81526001600160a01b0382811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063aa79979b90602401602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e39190610430565b156103ec5760405163036b50d960e11b81526001600160a01b0383811660048301526000917f0000000000000000000000000000000000000000000000000000000000000000909116906306d6a1b290602401602060405180830381865afa158015610253573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102779190610452565b604051635b16ebb760e01b81526001600160a01b0380831660048301529192507f000000000000000000000000000000000000000000000000000000000000000090911690635b16ebb790602401602060405180830381865afa1580156102e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103069190610430565b1561033357507f000000000000000000000000000000000000000000000000000000000000000092915050565b604051635b16ebb760e01b81526001600160a01b0382811660048301527f00000000000000000000000000000000000000000000000000000000000000001690635b16ebb790602401602060405180830381865afa158015610399573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103bd9190610430565b156103ea57507f000000000000000000000000000000000000000000000000000000000000000092915050565b505b506000919050565b6001600160a01b038116811461040957600080fd5b50565b60006020828403121561041e57600080fd5b8135610429816103f4565b9392505050565b60006020828403121561044257600080fd5b8151801515811461042957600080fd5b60006020828403121561046457600080fd5b8151610429816103f456fea2646970667358221220d3a6a19680b8f248f1a9c3fc828a12629d85c2c11a1ec70e8e9c0d5a1fd0c73364736f6c6343000813003300000000000000000000000097cdbce21b6fd0585d29e539b1b99dad328a112300000000000000000000000031832f2a97fd20664d76cc421207669b55ce4bc000000000000000000000000004625b046c69577efc40e6c0bb83cdbafab5a55f0000000000000000000000003cb9ae71566a1bae8244fbbe812d436adc7dc83c0000000000000000000000005c2866b225d6e247c500b2907408e26a4b7e6407
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100625760003560e01c80632a717cde1461006757806346c96aac146100aa57806386811bc7146100d1578063ab138846146100f8578063b5224a861461011f578063c79aeaae14610146575b600080fd5b61008e7f0000000000000000000000003cb9ae71566a1bae8244fbbe812d436adc7dc83c81565b6040516001600160a01b03909116815260200160405180910390f35b61008e7f00000000000000000000000097cdbce21b6fd0585d29e539b1b99dad328a112381565b61008e7f00000000000000000000000004625b046c69577efc40e6c0bb83cdbafab5a55f81565b61008e7f00000000000000000000000031832f2a97fd20664d76cc421207669b55ce4bc081565b61008e7f0000000000000000000000005c2866b225d6e247c500b2907408e26a4b7e640781565b61008e61015436600461040c565b60405163aa79979b60e01b81526001600160a01b0382811660048301526000917f00000000000000000000000097cdbce21b6fd0585d29e539b1b99dad328a11239091169063aa79979b90602401602060405180830381865afa1580156101bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101e39190610430565b156103ec5760405163036b50d960e11b81526001600160a01b0383811660048301526000917f00000000000000000000000097cdbce21b6fd0585d29e539b1b99dad328a1123909116906306d6a1b290602401602060405180830381865afa158015610253573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102779190610452565b604051635b16ebb760e01b81526001600160a01b0380831660048301529192507f00000000000000000000000031832f2a97fd20664d76cc421207669b55ce4bc090911690635b16ebb790602401602060405180830381865afa1580156102e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103069190610430565b1561033357507f0000000000000000000000003cb9ae71566a1bae8244fbbe812d436adc7dc83c92915050565b604051635b16ebb760e01b81526001600160a01b0382811660048301527f00000000000000000000000004625b046c69577efc40e6c0bb83cdbafab5a55f1690635b16ebb790602401602060405180830381865afa158015610399573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103bd9190610430565b156103ea57507f0000000000000000000000005c2866b225d6e247c500b2907408e26a4b7e640792915050565b505b506000919050565b6001600160a01b038116811461040957600080fd5b50565b60006020828403121561041e57600080fd5b8135610429816103f4565b9392505050565b60006020828403121561044257600080fd5b8151801515811461042957600080fd5b60006020828403121561046457600080fd5b8151610429816103f456fea2646970667358221220d3a6a19680b8f248f1a9c3fc828a12629d85c2c11a1ec70e8e9c0d5a1fd0c73364736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000097cdbce21b6fd0585d29e539b1b99dad328a112300000000000000000000000031832f2a97fd20664d76cc421207669b55ce4bc000000000000000000000000004625b046c69577efc40e6c0bb83cdbafab5a55f0000000000000000000000003cb9ae71566a1bae8244fbbe812d436adc7dc83c0000000000000000000000005c2866b225d6e247c500b2907408e26a4b7e6407
-----Decoded View---------------
Arg [0] : voter_ (address): 0x97cDBCe21B6fd0585d29E539B1B99dAd328a1123
Arg [1] : v2PoolFactory_ (address): 0x31832f2a97Fd20664D76Cc421207669b55CE4BC0
Arg [2] : slipstreamPoolFactory_ (address): 0x04625B046C69577EfC40e6c0Bb83CDBAfab5a55F
Arg [3] : v2GaugeConnector_ (address): 0x3cB9ae71566a1bAE8244FbbE812D436AdC7Dc83C
Arg [4] : slipstreamGaugeConnector_ (address): 0x5C2866B225D6E247C500b2907408E26A4b7E6407
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000097cdbce21b6fd0585d29e539b1b99dad328a1123
Arg [1] : 00000000000000000000000031832f2a97fd20664d76cc421207669b55ce4bc0
Arg [2] : 00000000000000000000000004625b046c69577efc40e6c0bb83cdbafab5a55f
Arg [3] : 0000000000000000000000003cb9ae71566a1bae8244fbbe812d436adc7dc83c
Arg [4] : 0000000000000000000000005c2866b225d6e247c500b2907408e26a4b7e6407
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.