Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ConvexSidecar
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
/// Interfaces
import {IBooster} from "@interfaces/convex/IBooster.sol";
import {IBaseRewardPool} from "@interfaces/convex/IBaseRewardPool.sol";
import {IStashTokenWrapper} from "@interfaces/convex/IStashTokenWrapper.sol";
/// OpenZeppelin
import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/// Project Contracts
import {Sidecar} from "src/Sidecar.sol";
import {ImmutableArgsParser} from "src/libraries/ImmutableArgsParser.sol";
/// @title ConvexSidecar.
/// @author Stake DAO
/// @custom:github @stake-dao
/// @custom:contact [email protected]
/// @notice Sidecar for managing Convex rewards and deposits.
contract ConvexSidecar is Sidecar {
using SafeERC20 for IERC20;
using ImmutableArgsParser for address;
/// @notice The bytes4 ID of the Curve protocol
/// @dev Used to identify the Curve protocol in the registry
bytes4 private constant CURVE_PROTOCOL_ID = bytes4(keccak256("CURVE"));
//////////////////////////////////////////////////////
// --- IMPLEMENTATION CONSTANTS
//////////////////////////////////////////////////////
/// @notice Convex Reward Token address.
IERC20 public immutable CVX;
/// @notice Convex Booster address.
address public immutable BOOSTER;
/// @notice Thrown when the reward receiver is not set in the protocol controller.
error RewardReceiverNotSet();
//////////////////////////////////////////////////////
// --- ISIDECAR CLONE IMMUTABLES
//////////////////////////////////////////////////////
/// @notice Staking token address.
function asset() public view override returns (IERC20 _asset) {
return IERC20(address(this).readAddress(0));
}
/// @notice Curve gauge associated with the sidecar.
function gauge() public view returns (address _gauge) {
return address(this).readAddress(20);
}
function rewardReceiver() public view override returns (address _rewardReceiver) {
_rewardReceiver = PROTOCOL_CONTROLLER.rewardReceiver(gauge());
if (_rewardReceiver == address(0)) revert RewardReceiverNotSet();
}
//////////////////////////////////////////////////////
// --- CONVEX CLONE IMMUTABLES
//////////////////////////////////////////////////////
/// @notice Staking Convex LP contract address.
function baseRewardPool() public view returns (IBaseRewardPool _baseRewardPool) {
return IBaseRewardPool(address(this).readAddress(40));
}
/// @notice Identifier of the pool on Convex.
function pid() public view returns (uint256 _pid) {
return address(this).readUint256(60);
}
//////////////////////////////////////////////////////
// --- CONSTRUCTOR
//////////////////////////////////////////////////////
constructor(address _accountant, address _protocolController, address _cvx, address _booster)
Sidecar(CURVE_PROTOCOL_ID, _accountant, _protocolController)
{
CVX = IERC20(_cvx);
BOOSTER = _booster;
}
//////////////////////////////////////////////////////
// --- INITIALIZATION
//////////////////////////////////////////////////////
/// @notice Initialize the contract by approving the ConvexCurve booster to spend the LP token.
function _initialize() internal override {
require(asset().allowance(address(this), address(BOOSTER)) == 0, AlreadyInitialized());
asset().forceApprove(address(BOOSTER), type(uint256).max);
}
//////////////////////////////////////////////////////
// --- ISIDECAR OPERATIONS OVERRIDE
//////////////////////////////////////////////////////
/// @notice Deposit LP token into Convex.
/// @param amount Amount of LP token to deposit.
/// @dev The reason there's an empty address parameter is to keep flexibility for future implementations.
/// Not all fallbacks will be minimal proxies, so we need to keep the same function signature.
/// Only callable by the strategy.
function _deposit(uint256 amount) internal override {
/// Deposit the LP token into Convex and stake it (true) to receive rewards.
IBooster(BOOSTER).deposit(pid(), amount, true);
}
/// @notice Withdraw LP token from Convex.
/// @param amount Amount of LP token to withdraw.
/// @param receiver Address to receive the LP token.
function _withdraw(uint256 amount, address receiver) internal override {
/// Withdraw from Convex gauge without claiming rewards (false).
baseRewardPool().withdrawAndUnwrap(amount, false);
/// Send the LP token to the receiver.
asset().safeTransfer(receiver, amount);
}
/// @notice Claim rewards from Convex.
/// @return rewardTokenAmount Amount of reward token claimed.
function _claim() internal override returns (uint256 rewardTokenAmount) {
/// Claim rewardToken.
baseRewardPool().getReward(address(this), false);
rewardTokenAmount = REWARD_TOKEN.balanceOf(address(this));
if (rewardTokenAmount > 0) {
/// Send the reward token to the accountant.
REWARD_TOKEN.safeTransfer(ACCOUNTANT, rewardTokenAmount);
}
}
/// @notice Get the balance of the LP token on Convex held by this contract.
function balanceOf() public view override returns (uint256) {
return baseRewardPool().balanceOf(address(this));
}
/// @notice Get the reward tokens from the base reward pool.
/// @return Array of all extra reward tokens.
function getRewardTokens() public view override returns (address[] memory) {
// Check if there is extra rewards
uint256 extraRewardsLength = baseRewardPool().extraRewardsLength();
address[] memory tokens = new address[](extraRewardsLength);
address _token;
for (uint256 i; i < extraRewardsLength;) {
/// Get the address of the virtual balance pool.
_token = baseRewardPool().extraRewards(i);
tokens[i] = IBaseRewardPool(_token).rewardToken();
/// For PIDs greater than 150, the virtual balance pool also has a wrapper.
/// So we need to get the token from the wrapper.
/// Try catch because pid 151 case is only on Mainnet, not on L2s.
/// More: https://docs.convexfinance.com/convexfinanceintegration/baserewardpool
try IStashTokenWrapper(tokens[i]).token() returns (address _t) {
tokens[i] = _t;
} catch {}
unchecked {
++i;
}
}
return tokens;
}
/// @notice Get the amount of reward token earned by the strategy.
/// @return The amount of reward token earned by the strategy.
function getPendingRewards() public view override returns (uint256) {
return baseRewardPool().earned(address(this)) + REWARD_TOKEN.balanceOf(address(this));
}
//////////////////////////////////////////////////////
// --- EXTRA CONVEX OPERATIONS
//////////////////////////////////////////////////////
function claimExtraRewards() external {
address[] memory extraRewardTokens = getRewardTokens();
/// It'll claim rewardToken but we'll leave it here for clarity until the claim() function is called by the strategy.
baseRewardPool().getReward(address(this), true);
/// Send the reward token to the reward receiver.
address receiver = rewardReceiver();
uint256 balance = CVX.balanceOf(address(this));
if (balance > 0) {
CVX.safeTransfer(receiver, balance);
}
/// Handle the extra reward tokens.
for (uint256 i = 0; i < extraRewardTokens.length;) {
uint256 _balance = IERC20(extraRewardTokens[i]).balanceOf(address(this));
if (_balance > 0) {
/// Send the whole balance to the reward receiver.
IERC20(extraRewardTokens[i]).safeTransfer(receiver, _balance);
}
unchecked {
++i;
}
}
}
}/// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.19;
interface IBooster {
function poolLength() external view returns (uint256);
function poolInfo(uint256 pid)
external
view
returns (address lpToken, address token, address gauge, address crvRewards, address stash, bool shutdown);
function deposit(uint256 _pid, uint256 _amount, bool _stake) external returns (bool);
function earmarkRewards(uint256 _pid) external returns (bool);
function depositAll(uint256 _pid, bool _stake) external returns (bool);
function withdraw(uint256 _pid, uint256 _amount) external returns (bool);
function claimRewards(uint256 _pid, address gauge) external returns (bool);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.19;
interface IBaseRewardPool {
function rewardToken() external view returns (address);
function extraRewardsLength() external view returns (uint256);
function extraRewards(uint256 index) external view returns (address);
function withdrawAndUnwrap(uint256 amount, bool claim) external returns (bool);
function getReward(address _account, bool _claimExtras) external returns (bool);
function balanceOf(address _account) external view returns (uint256);
function earned(address _account) external view returns (uint256);
function rewardRate() external view returns (uint256);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.19;
interface IStashTokenWrapper {
function token() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ISidecar} from "src/interfaces/ISidecar.sol";
import {IAccountant} from "src/interfaces/IAccountant.sol";
import {IProtocolController} from "src/interfaces/IProtocolController.sol";
/// @title Sidecar.
/// @author Stake DAO
/// @custom:github @stake-dao
/// @custom:contact [email protected]
/// @notice Sidecar is an abstract base contract for protocol-specific yield sources that complement the main locker strategy.
/// It enables yield diversification beyond the main protocol locker (e.g., Convex alongside veCRV) and provides
/// a protocol-agnostic base that can be extended for any yield source. Sidecars are managed by the Strategy
/// for unified deposit/withdraw/harvest operations, with rewards flowing through the Accountant for consistent distribution.
abstract contract Sidecar is ISidecar {
using SafeERC20 for IERC20;
//////////////////////////////////////////////////////
// --- IMMUTABLES
//////////////////////////////////////////////////////
/// @notice Protocol identifier matching the Strategy that manages this sidecar
bytes4 public immutable PROTOCOL_ID;
/// @notice Accountant that receives and distributes rewards from this sidecar
address public immutable ACCOUNTANT;
/// @notice Main protocol reward token claimed by this sidecar (e.g., CRV)
IERC20 public immutable REWARD_TOKEN;
/// @notice Registry used to verify the authorized strategy for this protocol
IProtocolController public immutable PROTOCOL_CONTROLLER;
//////////////////////////////////////////////////////
// --- STORAGE
//////////////////////////////////////////////////////
/// @notice Prevents double initialization in factory deployment pattern
bool private _initialized;
//////////////////////////////////////////////////////
// --- ERRORS
//////////////////////////////////////////////////////
error ZeroAddress();
error OnlyStrategy();
error OnlyAccountant();
error AlreadyInitialized();
error NotInitialized();
error InvalidProtocolId();
//////////////////////////////////////////////////////
// --- MODIFIERS
//////////////////////////////////////////////////////
/// @notice Restricts access to the authorized strategy for this protocol
/// @dev Prevents unauthorized manipulation of user funds
modifier onlyStrategy() {
require(PROTOCOL_CONTROLLER.strategy(PROTOCOL_ID) == msg.sender, OnlyStrategy());
_;
}
//////////////////////////////////////////////////////
// --- CONSTRUCTOR
//////////////////////////////////////////////////////
/// @notice Sets up immutable protocol connections
/// @dev Called by factory during deployment. Reward token fetched from accountant
/// @param _protocolId Protocol identifier for strategy verification
/// @param _accountant Where to send claimed rewards for distribution
/// @param _protocolController Registry for strategy lookup and validation
constructor(bytes4 _protocolId, address _accountant, address _protocolController) {
require(_protocolId != bytes4(0), InvalidProtocolId());
require(_accountant != address(0) && _protocolController != address(0), ZeroAddress());
PROTOCOL_ID = _protocolId;
ACCOUNTANT = _accountant;
PROTOCOL_CONTROLLER = IProtocolController(_protocolController);
REWARD_TOKEN = IERC20(IAccountant(_accountant).REWARD_TOKEN());
_initialized = true;
}
//////////////////////////////////////////////////////
// --- EXTERNAL FUNCTIONS
//////////////////////////////////////////////////////
/// @notice One-time setup for protocol-specific configuration
/// @dev Factory pattern: minimal proxy clones need post-deployment init
/// Base constructor sets _initialized=true, clones must call this
function initialize() external {
if (_initialized) revert AlreadyInitialized();
_initialized = true;
_initialize();
}
/// @notice Stakes LP tokens into the protocol-specific yield source
/// @dev Strategy transfers tokens here first, then calls deposit
/// @param amount LP tokens to stake (must already be transferred)
function deposit(uint256 amount) external onlyStrategy {
_deposit(amount);
}
/// @notice Unstakes LP tokens and sends directly to receiver
/// @dev Used during user withdrawals and emergency shutdowns
/// @param amount LP tokens to unstake from yield source
/// @param receiver Where to send the unstaked tokens (vault or user)
function withdraw(uint256 amount, address receiver) external onlyStrategy {
_withdraw(amount, receiver);
}
/// @notice Harvests rewards and transfers to accountant
/// @dev Part of Strategy's harvest flow. Returns amount for accounting
/// @return Amount of reward tokens sent to accountant
function claim() external onlyStrategy returns (uint256) {
return _claim();
}
//////////////////////////////////////////////////////
// --- IMMUTABLES
//////////////////////////////////////////////////////
/// @notice LP token this sidecar manages (e.g., CRV/ETH LP)
/// @dev Must match the asset used by the associated Strategy
function asset() public view virtual returns (IERC20);
/// @notice Where extra rewards (not main protocol rewards) should be sent
/// @dev Typically the RewardVault for the gauge this sidecar supports
function rewardReceiver() public view virtual returns (address);
//////////////////////////////////////////////////////
// --- INTERNAL VIRTUAL FUNCTIONS
//////////////////////////////////////////////////////
/// @dev Protocol-specific setup (approvals, staking contracts, etc.)
function _initialize() internal virtual;
/// @dev Stakes tokens in protocol-specific way (e.g., Convex deposit)
/// @param amount Tokens to stake (already transferred to this contract)
function _deposit(uint256 amount) internal virtual;
/// @dev Claims all available rewards and transfers to accountant
/// @return Total rewards claimed and transferred
function _claim() internal virtual returns (uint256);
/// @dev Unstakes from protocol and sends tokens to receiver
/// @param amount Tokens to unstake
/// @param receiver Destination for unstaked tokens
function _withdraw(uint256 amount, address receiver) internal virtual;
/// @notice Total LP tokens staked in this sidecar
/// @dev Used by Strategy to calculate total assets across all sources
/// @return Current staked balance
function balanceOf() public view virtual returns (uint256);
/// @notice Unclaimed rewards available for harvest
/// @dev May perform view-only simulation or on-chain checkpoint
/// @return Claimable reward token amount
function getPendingRewards() public virtual returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
/// @title ImmutableArgsParser
/// @notice A library for reading immutable arguments from a clone.
library ImmutableArgsParser {
/// @dev Safely read an `address` from `clone`'s immutable args at `offset`.
function readAddress(address clone, uint256 offset) internal view returns (address result) {
bytes memory args = Clones.fetchCloneArgs(clone);
assembly {
// Load 32 bytes starting at `args + offset + 32`. Then shift right
// by 96 bits (12 bytes) so that the address is right‐aligned and
// the high bits are cleared.
result := shr(96, mload(add(add(args, 0x20), offset)))
}
}
/// @dev Safely read a `uint256` from `clone`'s immutable args at `offset`.
function readUint256(address clone, uint256 offset) internal view returns (uint256 result) {
bytes memory args = Clones.fetchCloneArgs(clone);
assembly {
// Load the entire 32‐byte word directly.
result := mload(add(add(args, 0x20), offset))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
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 value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` 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 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}/// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface ISidecar {
function balanceOf() external view returns (uint256);
function deposit(uint256 amount) external;
function withdraw(uint256 amount, address receiver) external;
function getPendingRewards() external returns (uint256);
function getRewardTokens() external view returns (address[] memory);
function claim() external returns (uint256);
function asset() external view returns (IERC20);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import {IStrategy} from "src/interfaces/IStrategy.sol";
interface IAccountant {
function checkpoint(
address gauge,
address from,
address to,
uint128 amount,
IStrategy.PendingRewards calldata pendingRewards,
IStrategy.HarvestPolicy policy
) external;
function checkpoint(
address gauge,
address from,
address to,
uint128 amount,
IStrategy.PendingRewards calldata pendingRewards,
IStrategy.HarvestPolicy policy,
address referrer
) external;
function totalSupply(address asset) external view returns (uint128);
function balanceOf(address asset, address account) external view returns (uint128);
function claim(address[] calldata _gauges, bytes[] calldata harvestData) external;
function claim(address[] calldata _gauges, bytes[] calldata harvestData, address receiver) external;
function claim(address[] calldata _gauges, address account, bytes[] calldata harvestData, address receiver) external;
function claimProtocolFees() external;
function harvest(address[] calldata _gauges, bytes[] calldata _harvestData, address _receiver) external;
function REWARD_TOKEN() external view returns (address);
function getPendingRewards(address vault) external view returns (uint128);
function getPendingRewards(address vault, address account) external view returns (uint256);
function SCALING_FACTOR() external view returns (uint128);
}/// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
interface IProtocolController {
function vault(address) external view returns (address);
function asset(address) external view returns (address);
function rewardReceiver(address) external view returns (address);
function allowed(address, address, bytes4 selector) external view returns (bool);
function permissionSetters(address) external view returns (bool);
function isRegistrar(address) external view returns (bool);
function locker(bytes4 protocolId) external view returns (address);
function gateway(bytes4 protocolId) external view returns (address);
function strategy(bytes4 protocolId) external view returns (address);
function allocator(bytes4 protocolId) external view returns (address);
function accountant(bytes4 protocolId) external view returns (address);
function feeReceiver(bytes4 protocolId) external view returns (address);
function factory(bytes4 protocolId) external view returns (address);
function isPaused(bytes4) external view returns (bool);
function isShutdown(address) external view returns (bool);
function registerVault(address _gauge, address _vault, address _asset, address _rewardReceiver, bytes4 _protocolId)
external;
function setValidAllocationTarget(address _gauge, address _target) external;
function removeValidAllocationTarget(address _gauge, address _target) external;
function isValidAllocationTarget(address _gauge, address _target) external view returns (bool);
function pause(bytes4 protocolId) external;
function unpause(bytes4 protocolId) external;
function shutdown(address _gauge) external;
function unshutdown(address _gauge) external;
function setPermissionSetter(address _setter, bool _allowed) external;
function setPermission(address _contract, address _caller, bytes4 _selector, bool _allowed) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (proxy/Clones.sol)
pragma solidity ^0.8.20;
import {Create2} from "../utils/Create2.sol";
import {Errors} from "../utils/Errors.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-1167[ERC-1167] is a standard for
* deploying minimal proxy contracts, also known as "clones".
*
* > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
* > a minimal bytecode implementation that delegates all calls to a known, fixed address.
*
* The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
* (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
* deterministic method.
*/
library Clones {
error CloneArgumentsTooLong();
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create opcode, which should never revert.
*/
function clone(address implementation) internal returns (address instance) {
return clone(implementation, 0);
}
/**
* @dev Same as {xref-Clones-clone-address-}[clone], but with a `value` parameter to send native currency
* to the new contract.
*
* NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
* to always have enough balance for new deployments. Consider exposing this function under a payable method.
*/
function clone(address implementation, uint256 value) internal returns (address instance) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
assembly ("memory-safe") {
// Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
// of the `implementation` address with the bytecode before the address.
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
// Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create(value, 0x09, 0x37)
}
if (instance == address(0)) {
revert Errors.FailedDeployment();
}
}
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy
* the clone. Using the same `implementation` and `salt` multiple times will revert, since
* the clones cannot be deployed twice at the same address.
*/
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
return cloneDeterministic(implementation, salt, 0);
}
/**
* @dev Same as {xref-Clones-cloneDeterministic-address-bytes32-}[cloneDeterministic], but with
* a `value` parameter to send native currency to the new contract.
*
* NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
* to always have enough balance for new deployments. Consider exposing this function under a payable method.
*/
function cloneDeterministic(
address implementation,
bytes32 salt,
uint256 value
) internal returns (address instance) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
assembly ("memory-safe") {
// Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
// of the `implementation` address with the bytecode before the address.
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
// Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create2(value, 0x09, 0x37, salt)
}
if (instance == address(0)) {
revert Errors.FailedDeployment();
}
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(add(ptr, 0x38), deployer)
mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
mstore(add(ptr, 0x14), implementation)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
mstore(add(ptr, 0x58), salt)
mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
predicted := and(keccak256(add(ptr, 0x43), 0x55), 0xffffffffffffffffffffffffffffffffffffffff)
}
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(
address implementation,
bytes32 salt
) internal view returns (address predicted) {
return predictDeterministicAddress(implementation, salt, address(this));
}
/**
* @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom
* immutable arguments. These are provided through `args` and cannot be changed after deployment. To
* access the arguments within the implementation, use {fetchCloneArgs}.
*
* This function uses the create opcode, which should never revert.
*/
function cloneWithImmutableArgs(address implementation, bytes memory args) internal returns (address instance) {
return cloneWithImmutableArgs(implementation, args, 0);
}
/**
* @dev Same as {xref-Clones-cloneWithImmutableArgs-address-bytes-}[cloneWithImmutableArgs], but with a `value`
* parameter to send native currency to the new contract.
*
* NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
* to always have enough balance for new deployments. Consider exposing this function under a payable method.
*/
function cloneWithImmutableArgs(
address implementation,
bytes memory args,
uint256 value
) internal returns (address instance) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
assembly ("memory-safe") {
instance := create(value, add(bytecode, 0x20), mload(bytecode))
}
if (instance == address(0)) {
revert Errors.FailedDeployment();
}
}
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation` with custom
* immutable arguments. These are provided through `args` and cannot be changed after deployment. To
* access the arguments within the implementation, use {fetchCloneArgs}.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy the clone. Using the same
* `implementation`, `args` and `salt` multiple times will revert, since the clones cannot be deployed twice
* at the same address.
*/
function cloneDeterministicWithImmutableArgs(
address implementation,
bytes memory args,
bytes32 salt
) internal returns (address instance) {
return cloneDeterministicWithImmutableArgs(implementation, args, salt, 0);
}
/**
* @dev Same as {xref-Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-}[cloneDeterministicWithImmutableArgs],
* but with a `value` parameter to send native currency to the new contract.
*
* NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
* to always have enough balance for new deployments. Consider exposing this function under a payable method.
*/
function cloneDeterministicWithImmutableArgs(
address implementation,
bytes memory args,
bytes32 salt,
uint256 value
) internal returns (address instance) {
bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
return Create2.deploy(value, salt, bytecode);
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.
*/
function predictDeterministicAddressWithImmutableArgs(
address implementation,
bytes memory args,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
return Create2.computeAddress(salt, keccak256(bytecode), deployer);
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.
*/
function predictDeterministicAddressWithImmutableArgs(
address implementation,
bytes memory args,
bytes32 salt
) internal view returns (address predicted) {
return predictDeterministicAddressWithImmutableArgs(implementation, args, salt, address(this));
}
/**
* @dev Get the immutable args attached to a clone.
*
* - If `instance` is a clone that was deployed using `clone` or `cloneDeterministic`, this
* function will return an empty array.
* - If `instance` is a clone that was deployed using `cloneWithImmutableArgs` or
* `cloneDeterministicWithImmutableArgs`, this function will return the args array used at
* creation.
* - If `instance` is NOT a clone deployed using this library, the behavior is undefined. This
* function should only be used to check addresses that are known to be clones.
*/
function fetchCloneArgs(address instance) internal view returns (bytes memory) {
bytes memory result = new bytes(instance.code.length - 45); // revert if length is too short
assembly ("memory-safe") {
extcodecopy(instance, add(result, 32), 45, mload(result))
}
return result;
}
/**
* @dev Helper that prepares the initcode of the proxy with immutable args.
*
* An assembly variant of this function requires copying the `args` array, which can be efficiently done using
* `mcopy`. Unfortunately, that opcode is not available before cancun. A pure solidity implementation using
* abi.encodePacked is more expensive but also more portable and easier to review.
*
* NOTE: https://eips.ethereum.org/EIPS/eip-170[EIP-170] limits the length of the contract code to 24576 bytes.
* With the proxy code taking 45 bytes, that limits the length of the immutable args to 24531 bytes.
*/
function _cloneCodeWithImmutableArgs(
address implementation,
bytes memory args
) private pure returns (bytes memory) {
if (args.length > 24531) revert CloneArgumentsTooLong();
return
abi.encodePacked(
hex"61",
uint16(args.length + 45),
hex"3d81600a3d39f3363d3d373d3d3d363d73",
implementation,
hex"5af43d82803e903d91602b57fd5bf3",
args
);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import "src/interfaces/IAllocator.sol";
interface IStrategy {
/// @notice The policy for harvesting rewards.
enum HarvestPolicy {
CHECKPOINT,
HARVEST
}
struct PendingRewards {
uint128 feeSubjectAmount;
uint128 totalAmount;
}
function deposit(IAllocator.Allocation calldata allocation, HarvestPolicy policy)
external
returns (PendingRewards memory pendingRewards);
function withdraw(IAllocator.Allocation calldata allocation, HarvestPolicy policy, address receiver)
external
returns (PendingRewards memory pendingRewards);
function balanceOf(address gauge) external view returns (uint256 balance);
function harvest(address gauge, bytes calldata extraData) external returns (PendingRewards memory pendingRewards);
function flush() external;
function shutdown(address gauge) external;
function rebalance(address gauge) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
* `CREATE2` can be used to compute in advance the address where a smart
* contract will be deployed, which allows for interesting new mechanisms known
* as 'counterfactual interactions'.
*
* See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
* information.
*/
library Create2 {
/**
* @dev There's no code to deploy.
*/
error Create2EmptyBytecode();
/**
* @dev Deploys a contract using `CREATE2`. The address where the contract
* will be deployed can be known in advance via {computeAddress}.
*
* The bytecode for a contract can be obtained from Solidity with
* `type(contractName).creationCode`.
*
* Requirements:
*
* - `bytecode` must not be empty.
* - `salt` must have not been used for `bytecode` already.
* - the factory must have a balance of at least `amount`.
* - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
*/
function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
if (bytecode.length == 0) {
revert Create2EmptyBytecode();
}
assembly ("memory-safe") {
addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
// if no address was created, and returndata is not empty, bubble revert
if and(iszero(addr), not(iszero(returndatasize()))) {
let p := mload(0x40)
returndatacopy(p, 0, returndatasize())
revert(p, returndatasize())
}
}
if (addr == address(0)) {
revert Errors.FailedDeployment();
}
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
* `bytecodeHash` or `salt` will result in a new destination address.
*/
function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
return computeAddress(salt, bytecodeHash, address(this));
}
/**
* @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
* `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
*/
function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {
assembly ("memory-safe") {
let ptr := mload(0x40) // Get free memory pointer
// | | ↓ ptr ... ↓ ptr + 0x0B (start) ... ↓ ptr + 0x20 ... ↓ ptr + 0x40 ... |
// |-------------------|---------------------------------------------------------------------------|
// | bytecodeHash | CCCCCCCCCCCCC...CC |
// | salt | BBBBBBBBBBBBB...BB |
// | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA |
// | 0xFF | FF |
// |-------------------|---------------------------------------------------------------------------|
// | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
// | keccak(start, 85) | ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |
mstore(add(ptr, 0x40), bytecodeHash)
mstore(add(ptr, 0x20), salt)
mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes
let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff
mstore8(start, 0xff)
addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of common custom errors used in multiple contracts
*
* IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
* It is recommended to avoid relying on the error API for critical functionality.
*
* _Available since v5.1._
*/
library Errors {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedCall();
/**
* @dev The deployment failed.
*/
error FailedDeployment();
/**
* @dev A necessary precompile is missing.
*/
error MissingPrecompile(address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* 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[ERC 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: BUSL-1.1
pragma solidity 0.8.28;
interface IAllocator {
struct Allocation {
address asset;
address gauge;
address[] targets;
uint256[] amounts;
}
function getDepositAllocation(address asset, address gauge, uint256 amount)
external
view
returns (Allocation memory);
function getWithdrawalAllocation(address asset, address gauge, uint256 amount)
external
view
returns (Allocation memory);
function getRebalancedAllocation(address asset, address gauge, uint256 amount)
external
view
returns (Allocation memory);
function getAllocationTargets(address gauge) external view returns (address[] memory);
}{
"remappings": [
"forge-std/=node_modules/forge-std/",
"layerzerolabs/oft-evm/=node_modules/@layerzerolabs/oft-evm/",
"@safe/=node_modules/@safe-global/safe-smart-account/",
"@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
"@interfaces/=node_modules/@stake-dao/interfaces/src/interfaces/",
"@address-book/=node_modules/@stake-dao/address-book/",
"@shared/=node_modules/@stake-dao/shared/",
"@layerzerolabs/=node_modules/@layerzerolabs/",
"@safe-global/=node_modules/@safe-global/",
"@solady/=node_modules/@solady/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_accountant","type":"address"},{"internalType":"address","name":"_protocolController","type":"address"},{"internalType":"address","name":"_cvx","type":"address"},{"internalType":"address","name":"_booster","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"InvalidProtocolId","type":"error"},{"inputs":[],"name":"NotInitialized","type":"error"},{"inputs":[],"name":"OnlyAccountant","type":"error"},{"inputs":[],"name":"OnlyStrategy","type":"error"},{"inputs":[],"name":"RewardReceiverNotSet","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ACCOUNTANT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BOOSTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CVX","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROTOCOL_CONTROLLER","outputs":[{"internalType":"contract IProtocolController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROTOCOL_ID","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_TOKEN","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract IERC20","name":"_asset","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseRewardPool","outputs":[{"internalType":"contract IBaseRewardPool","name":"_baseRewardPool","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimExtraRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gauge","outputs":[{"internalType":"address","name":"_gauge","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRewardTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pid","outputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardReceiver","outputs":[{"internalType":"address","name":"_rewardReceiver","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
610140604052348015610010575f5ffd5b506040516116d33803806116d383398101604081905261002f9161015c565b7fc715e3736a8cb018f630cb9a1df908ad1629e9c2da4cd190b2dc83d6687ba16984846001600160a01b0382161580159061007257506001600160a01b03811615155b61008f5760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031983166080526001600160a01b0380831660a081905290821660e052604080516399248ea760e01b815290516399248ea7916004808201926020929091908290030181865afa1580156100ec573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061011091906101ad565b6001600160a01b0390811660c0525f805460ff19166001179055948516610100525050501661012052506101cd9050565b80516001600160a01b0381168114610157575f5ffd5b919050565b5f5f5f5f6080858703121561016f575f5ffd5b61017885610141565b935061018660208601610141565b925061019460408601610141565b91506101a260608601610141565b905092959194509250565b5f602082840312156101bd575f5ffd5b6101c682610141565b9392505050565b60805160a05160c05160e051610100516101205161144f6102845f395f81816101f301528181610f1801528181610fad0152610fe801525f81816101cc015281816107d3015261085101525f818161021a01528181610323015281816103c4015281816104f2015261068801525f818161027001528181610bf001528181610e260152610eac01525f81816102490152610ece01525f8181610139015281816102f2015281816104bf0152610657015261144f5ff3fe608060405234801561000f575f5ffd5b506004361061011b575f3560e01c80637aaf53e6116100a9578063b6b55f251161006e578063b6b55f251461029a578063c0e1c59e146102ad578063c4f59f9b146102b5578063d9621f9e146102ca578063f1068454146102d2575f5ffd5b80637aaf53e6146102155780638129fc1c1461023c5780638b9d29401461024457806399248ea71461026b578063a6f19c8414610292575f5ffd5b8063475a91d1116100ef578063475a91d1146101a15780634e71d92d146101a9578063722713f7146101bf578063759cb53b146101c757806375b0ffd1146101ee575f5ffd5b8062f714ce1461011f5780630db41f31146101345780631dac30b01461017957806338d52e0f14610199575b5f5ffd5b61013261012d3660046112cf565b6102da565b005b61015b7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160e01b031990911681526020015b60405180910390f35b6101816103c1565b6040516001600160a01b039091168152602001610170565b61018161048b565b61018161049b565b6101b16104a7565b604051908152602001610170565b6101b161058a565b6101817f000000000000000000000000000000000000000000000000000000000000000081565b6101817f000000000000000000000000000000000000000000000000000000000000000081565b6101817f000000000000000000000000000000000000000000000000000000000000000081565b6101326105fb565b6101817f000000000000000000000000000000000000000000000000000000000000000081565b6101817f000000000000000000000000000000000000000000000000000000000000000081565b610181610633565b6101326102a83660046112fd565b61063f565b610132610724565b6102bd610956565b6040516101709190611314565b6101b1610bd9565b6101b1610cd9565b604051630165699560e21b81526001600160e01b03197f000000000000000000000000000000000000000000000000000000000000000016600482015233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630595a65490602401602060405180830381865afa158015610368573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038c919061135f565b6001600160a01b0316146103b35760405163ade5da5f60e01b815260040160405180910390fd5b6103bd8282610ce5565b5050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636720a1206103f9610633565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561043b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061045f919061135f565b90506001600160a01b03811661048857604051631cf92da960e11b815260040160405180910390fd5b90565b5f6104963082610d7b565b905090565b5f610496306028610d7b565b604051630165699560e21b81526001600160e01b03197f00000000000000000000000000000000000000000000000000000000000000001660048201525f9033906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630595a65490602401602060405180830381865afa158015610537573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061055b919061135f565b6001600160a01b0316146105825760405163ade5da5f60e01b815260040160405180910390fd5b610496610d98565b5f61059361049b565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa1580156105d7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104969190611381565b5f5460ff161561061d5760405162dc149f60e41b815260040160405180910390fd5b5f805460ff19166001179055610631610ef3565b565b5f610496306014610d7b565b604051630165699560e21b81526001600160e01b03197f000000000000000000000000000000000000000000000000000000000000000016600482015233906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630595a65490602401602060405180830381865afa1580156106cd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f1919061135f565b6001600160a01b0316146107185760405163ade5da5f60e01b815260040160405180910390fd5b61072181610fe6565b50565b5f61072d610956565b905061073761049b565b604051637050ccd960e01b8152306004820152600160248201526001600160a01b039190911690637050ccd9906044016020604051808303815f875af1158015610783573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107a79190611398565b505f6107b16103c1565b6040516370a0823160e01b81523060048201529091505f906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610818573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061083c9190611381565b90508015610878576108786001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016838361108a565b5f5b8351811015610950575f848281518110610896576108966113b7565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156108e4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109089190611381565b90508015610947576109478482878581518110610927576109276113b7565b60200260200101516001600160a01b031661108a9092919063ffffffff16565b5060010161087a565b50505050565b60605f61096161049b565b6001600160a01b031663d55a23f46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561099c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109c09190611381565b90505f8167ffffffffffffffff8111156109dc576109dc6113cb565b604051908082528060200260200182016040528015610a05578160200160208202803683370190505b5090505f5f5b83811015610bd057610a1b61049b565b6001600160a01b03166340c35446826040518263ffffffff1660e01b8152600401610a4891815260200190565b602060405180830381865afa158015610a63573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a87919061135f565b9150816001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae9919061135f565b838281518110610afb57610afb6113b7565b60200260200101906001600160a01b031690816001600160a01b031681525050828181518110610b2d57610b2d6113b7565b60200260200101516001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610b8e575060408051601f3d908101601f19168201909252610b8b9181019061135f565b60015b15610bc85780848381518110610ba657610ba66113b7565b60200260200101906001600160a01b031690816001600160a01b031681525050505b600101610a0b565b50909392505050565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610c3d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c619190611381565b610c6961049b565b6040516246613160e11b81523060048201526001600160a01b039190911690628cc26290602401602060405180830381865afa158015610cab573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ccf9190611381565b61049691906113f3565b5f61049630603c6110ee565b610ced61049b565b604051636197390160e11b8152600481018490525f60248201526001600160a01b03919091169063c32e7202906044016020604051808303815f875af1158015610d39573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d5d9190611398565b506103bd8183610d6b61048b565b6001600160a01b0316919061108a565b5f5f610d8684611108565b929092016020015160601c9392505050565b5f610da161049b565b604051637050ccd960e01b81523060048201525f60248201526001600160a01b039190911690637050ccd9906044016020604051808303815f875af1158015610dec573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e109190611398565b506040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610e73573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e979190611381565b90508015610488576104886001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f00000000000000000000000000000000000000000000000000000000000000008361108a565b610efb61048b565b604051636eb1769f60e11b81523060048201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166024830152919091169063dd62ed3e90604401602060405180830381865afa158015610f67573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8b9190611381565b15610fa85760405162dc149f60e41b815260040160405180910390fd5b6106317f00000000000000000000000000000000000000000000000000000000000000005f19610fd661048b565b6001600160a01b03169190611175565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a0d06661101d610cd9565b6040516001600160e01b031960e084901b168152600481019190915260248101849052600160448201526064016020604051808303815f875af1158015611066573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103bd9190611398565b6040516001600160a01b038381166024830152604482018390526110e991859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611200565b505050565b5f5f6110f984611108565b92909201602001519392505050565b60605f611120602d6001600160a01b0385163b611406565b67ffffffffffffffff811115611138576111386113cb565b6040519080825280601f01601f191660200182016040528015611162576020820181803683370190505b5090508051602d60208301853c92915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526111c68482611270565b610950576040516001600160a01b0384811660248301525f60448301526111fa91869182169063095ea7b3906064016110b7565b61095084825b5f5f60205f8451602086015f885af18061121f576040513d5f823e3d81fd5b50505f513d91508115611236578060011415611243565b6001600160a01b0384163b155b1561095057604051635274afe760e01b81526001600160a01b038516600482015260240160405180910390fd5b5f5f5f5f60205f8651602088015f8a5af192503d91505f5190508280156112af575081156112a157806001146112af565b5f866001600160a01b03163b115b93505050505b92915050565b6001600160a01b0381168114610721575f5ffd5b5f5f604083850312156112e0575f5ffd5b8235915060208301356112f2816112bb565b809150509250929050565b5f6020828403121561130d575f5ffd5b5035919050565b602080825282518282018190525f918401906040840190835b818110156113545783516001600160a01b031683526020938401939092019160010161132d565b509095945050505050565b5f6020828403121561136f575f5ffd5b815161137a816112bb565b9392505050565b5f60208284031215611391575f5ffd5b5051919050565b5f602082840312156113a8575f5ffd5b8151801515811461137a575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156112b5576112b56113df565b818103818111156112b5576112b56113df56fea26469706673582212203e75911f8acdc87fed9d6c3b5fd06632aefd7c920bf2a2a04229a7ddade7040b64736f6c634300081c003300000000000000000000000093b4b9bd266ffa8af68e39edfa8cfe2a62011ce00000000000000000000000002d8bce1fae00a959354acd9ebf9174337a64d4fb0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b000000000000000000000000f403c135812408bfbe8713b5a23a04b3d48aae31
Deployed Bytecode
0x608060405234801561000f575f5ffd5b506004361061011b575f3560e01c80637aaf53e6116100a9578063b6b55f251161006e578063b6b55f251461029a578063c0e1c59e146102ad578063c4f59f9b146102b5578063d9621f9e146102ca578063f1068454146102d2575f5ffd5b80637aaf53e6146102155780638129fc1c1461023c5780638b9d29401461024457806399248ea71461026b578063a6f19c8414610292575f5ffd5b8063475a91d1116100ef578063475a91d1146101a15780634e71d92d146101a9578063722713f7146101bf578063759cb53b146101c757806375b0ffd1146101ee575f5ffd5b8062f714ce1461011f5780630db41f31146101345780631dac30b01461017957806338d52e0f14610199575b5f5ffd5b61013261012d3660046112cf565b6102da565b005b61015b7fc715e3730000000000000000000000000000000000000000000000000000000081565b6040516001600160e01b031990911681526020015b60405180910390f35b6101816103c1565b6040516001600160a01b039091168152602001610170565b61018161048b565b61018161049b565b6101b16104a7565b604051908152602001610170565b6101b161058a565b6101817f0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b81565b6101817f000000000000000000000000f403c135812408bfbe8713b5a23a04b3d48aae3181565b6101817f0000000000000000000000002d8bce1fae00a959354acd9ebf9174337a64d4fb81565b6101326105fb565b6101817f00000000000000000000000093b4b9bd266ffa8af68e39edfa8cfe2a62011ce081565b6101817f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd5281565b610181610633565b6101326102a83660046112fd565b61063f565b610132610724565b6102bd610956565b6040516101709190611314565b6101b1610bd9565b6101b1610cd9565b604051630165699560e21b81526001600160e01b03197fc715e3730000000000000000000000000000000000000000000000000000000016600482015233906001600160a01b037f0000000000000000000000002d8bce1fae00a959354acd9ebf9174337a64d4fb1690630595a65490602401602060405180830381865afa158015610368573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038c919061135f565b6001600160a01b0316146103b35760405163ade5da5f60e01b815260040160405180910390fd5b6103bd8282610ce5565b5050565b5f7f0000000000000000000000002d8bce1fae00a959354acd9ebf9174337a64d4fb6001600160a01b0316636720a1206103f9610633565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561043b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061045f919061135f565b90506001600160a01b03811661048857604051631cf92da960e11b815260040160405180910390fd5b90565b5f6104963082610d7b565b905090565b5f610496306028610d7b565b604051630165699560e21b81526001600160e01b03197fc715e373000000000000000000000000000000000000000000000000000000001660048201525f9033906001600160a01b037f0000000000000000000000002d8bce1fae00a959354acd9ebf9174337a64d4fb1690630595a65490602401602060405180830381865afa158015610537573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061055b919061135f565b6001600160a01b0316146105825760405163ade5da5f60e01b815260040160405180910390fd5b610496610d98565b5f61059361049b565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa1580156105d7573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104969190611381565b5f5460ff161561061d5760405162dc149f60e41b815260040160405180910390fd5b5f805460ff19166001179055610631610ef3565b565b5f610496306014610d7b565b604051630165699560e21b81526001600160e01b03197fc715e3730000000000000000000000000000000000000000000000000000000016600482015233906001600160a01b037f0000000000000000000000002d8bce1fae00a959354acd9ebf9174337a64d4fb1690630595a65490602401602060405180830381865afa1580156106cd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f1919061135f565b6001600160a01b0316146107185760405163ade5da5f60e01b815260040160405180910390fd5b61072181610fe6565b50565b5f61072d610956565b905061073761049b565b604051637050ccd960e01b8152306004820152600160248201526001600160a01b039190911690637050ccd9906044016020604051808303815f875af1158015610783573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107a79190611398565b505f6107b16103c1565b6040516370a0823160e01b81523060048201529091505f906001600160a01b037f0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b16906370a0823190602401602060405180830381865afa158015610818573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061083c9190611381565b90508015610878576108786001600160a01b037f0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b16838361108a565b5f5b8351811015610950575f848281518110610896576108966113b7565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156108e4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109089190611381565b90508015610947576109478482878581518110610927576109276113b7565b60200260200101516001600160a01b031661108a9092919063ffffffff16565b5060010161087a565b50505050565b60605f61096161049b565b6001600160a01b031663d55a23f46040518163ffffffff1660e01b8152600401602060405180830381865afa15801561099c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109c09190611381565b90505f8167ffffffffffffffff8111156109dc576109dc6113cb565b604051908082528060200260200182016040528015610a05578160200160208202803683370190505b5090505f5f5b83811015610bd057610a1b61049b565b6001600160a01b03166340c35446826040518263ffffffff1660e01b8152600401610a4891815260200190565b602060405180830381865afa158015610a63573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a87919061135f565b9150816001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae9919061135f565b838281518110610afb57610afb6113b7565b60200260200101906001600160a01b031690816001600160a01b031681525050828181518110610b2d57610b2d6113b7565b60200260200101516001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610b8e575060408051601f3d908101601f19168201909252610b8b9181019061135f565b60015b15610bc85780848381518110610ba657610ba66113b7565b60200260200101906001600160a01b031690816001600160a01b031681525050505b600101610a0b565b50909392505050565b6040516370a0823160e01b81523060048201525f907f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd526001600160a01b0316906370a0823190602401602060405180830381865afa158015610c3d573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c619190611381565b610c6961049b565b6040516246613160e11b81523060048201526001600160a01b039190911690628cc26290602401602060405180830381865afa158015610cab573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ccf9190611381565b61049691906113f3565b5f61049630603c6110ee565b610ced61049b565b604051636197390160e11b8152600481018490525f60248201526001600160a01b03919091169063c32e7202906044016020604051808303815f875af1158015610d39573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d5d9190611398565b506103bd8183610d6b61048b565b6001600160a01b0316919061108a565b5f5f610d8684611108565b929092016020015160601c9392505050565b5f610da161049b565b604051637050ccd960e01b81523060048201525f60248201526001600160a01b039190911690637050ccd9906044016020604051808303815f875af1158015610dec573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e109190611398565b506040516370a0823160e01b81523060048201527f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd526001600160a01b0316906370a0823190602401602060405180830381865afa158015610e73573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e979190611381565b90508015610488576104886001600160a01b037f000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd52167f00000000000000000000000093b4b9bd266ffa8af68e39edfa8cfe2a62011ce08361108a565b610efb61048b565b604051636eb1769f60e11b81523060048201526001600160a01b037f000000000000000000000000f403c135812408bfbe8713b5a23a04b3d48aae3181166024830152919091169063dd62ed3e90604401602060405180830381865afa158015610f67573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8b9190611381565b15610fa85760405162dc149f60e41b815260040160405180910390fd5b6106317f000000000000000000000000f403c135812408bfbe8713b5a23a04b3d48aae315f19610fd661048b565b6001600160a01b03169190611175565b7f000000000000000000000000f403c135812408bfbe8713b5a23a04b3d48aae316001600160a01b03166343a0d06661101d610cd9565b6040516001600160e01b031960e084901b168152600481019190915260248101849052600160448201526064016020604051808303815f875af1158015611066573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103bd9190611398565b6040516001600160a01b038381166024830152604482018390526110e991859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611200565b505050565b5f5f6110f984611108565b92909201602001519392505050565b60605f611120602d6001600160a01b0385163b611406565b67ffffffffffffffff811115611138576111386113cb565b6040519080825280601f01601f191660200182016040528015611162576020820181803683370190505b5090508051602d60208301853c92915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526111c68482611270565b610950576040516001600160a01b0384811660248301525f60448301526111fa91869182169063095ea7b3906064016110b7565b61095084825b5f5f60205f8451602086015f885af18061121f576040513d5f823e3d81fd5b50505f513d91508115611236578060011415611243565b6001600160a01b0384163b155b1561095057604051635274afe760e01b81526001600160a01b038516600482015260240160405180910390fd5b5f5f5f5f60205f8651602088015f8a5af192503d91505f5190508280156112af575081156112a157806001146112af565b5f866001600160a01b03163b115b93505050505b92915050565b6001600160a01b0381168114610721575f5ffd5b5f5f604083850312156112e0575f5ffd5b8235915060208301356112f2816112bb565b809150509250929050565b5f6020828403121561130d575f5ffd5b5035919050565b602080825282518282018190525f918401906040840190835b818110156113545783516001600160a01b031683526020938401939092019160010161132d565b509095945050505050565b5f6020828403121561136f575f5ffd5b815161137a816112bb565b9392505050565b5f60208284031215611391575f5ffd5b5051919050565b5f602082840312156113a8575f5ffd5b8151801515811461137a575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156112b5576112b56113df565b818103818111156112b5576112b56113df56fea26469706673582212203e75911f8acdc87fed9d6c3b5fd06632aefd7c920bf2a2a04229a7ddade7040b64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000093b4b9bd266ffa8af68e39edfa8cfe2a62011ce00000000000000000000000002d8bce1fae00a959354acd9ebf9174337a64d4fb0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b000000000000000000000000f403c135812408bfbe8713b5a23a04b3d48aae31
-----Decoded View---------------
Arg [0] : _accountant (address): 0x93b4B9bd266fFA8AF68e39EDFa8cFe2A62011Ce0
Arg [1] : _protocolController (address): 0x2d8BcE1FaE00a959354aCD9eBf9174337A64d4fb
Arg [2] : _cvx (address): 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B
Arg [3] : _booster (address): 0xF403C135812408BFbE8713b5A23a04b3D48AAE31
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000093b4b9bd266ffa8af68e39edfa8cfe2a62011ce0
Arg [1] : 0000000000000000000000002d8bce1fae00a959354acd9ebf9174337a64d4fb
Arg [2] : 0000000000000000000000004e3fbd56cd56c3e72c1403e103b45db9da5b9d2b
Arg [3] : 000000000000000000000000f403c135812408bfbe8713b5a23a04b3d48aae31
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
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.