Source Code
Latest 25 from a total of 38 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Sync Reward Toke... | 23018136 | 191 days ago | IN | 0 FRAX | 0.00047561 | ||||
| Create | 22893604 | 193 days ago | IN | 0 FRAX | 0.00038866 | ||||
| Sync Reward Toke... | 22633128 | 200 days ago | IN | 0 FRAX | 0.00031275 | ||||
| Create | 21763482 | 220 days ago | IN | 0 FRAX | 0.00015265 | ||||
| Create | 21763482 | 220 days ago | IN | 0 FRAX | 0.00015265 | ||||
| Create | 21763481 | 220 days ago | IN | 0 FRAX | 0.00015084 | ||||
| Create | 21763481 | 220 days ago | IN | 0 FRAX | 0.00015082 | ||||
| Create | 21763481 | 220 days ago | IN | 0 FRAX | 0.00015085 | ||||
| Create | 21763481 | 220 days ago | IN | 0 FRAX | 0.00015088 | ||||
| Create | 21763481 | 220 days ago | IN | 0 FRAX | 0.00015082 | ||||
| Create | 21763481 | 220 days ago | IN | 0 FRAX | 0.00015084 | ||||
| Create | 21763480 | 220 days ago | IN | 0 FRAX | 0.00015082 | ||||
| Create | 21763480 | 220 days ago | IN | 0 FRAX | 0.00015088 | ||||
| Create | 21763480 | 220 days ago | IN | 0 FRAX | 0.00015088 | ||||
| Create | 21763480 | 220 days ago | IN | 0 FRAX | 0.00015084 | ||||
| Create | 21763480 | 220 days ago | IN | 0 FRAX | 0.00015084 | ||||
| Create | 21763480 | 220 days ago | IN | 0 FRAX | 0.00015084 | ||||
| Create | 21763480 | 220 days ago | IN | 0 FRAX | 0.00015084 | ||||
| Create | 21763480 | 220 days ago | IN | 0 FRAX | 0.00015084 | ||||
| Create | 21763479 | 220 days ago | IN | 0 FRAX | 0.00015086 | ||||
| Create | 21763479 | 220 days ago | IN | 0 FRAX | 0.00015088 | ||||
| Create | 21763479 | 220 days ago | IN | 0 FRAX | 0.00015088 | ||||
| Create | 21763478 | 220 days ago | IN | 0 FRAX | 0.00015088 | ||||
| Create | 21763478 | 220 days ago | IN | 0 FRAX | 0.00015086 | ||||
| Create | 21763478 | 220 days ago | IN | 0 FRAX | 0.00015084 |
Latest 25 internal transactions (View All)
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
CurveFactory
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;
import {Factory} from "src/Factory.sol";
import {IL2Booster} from "@interfaces/convex/IL2Booster.sol";
import {IRewardVault} from "src/interfaces/IRewardVault.sol";
import {ISidecarFactory} from "src/interfaces/ISidecarFactory.sol";
import {IL2LiquidityGauge} from "@interfaces/curve/ILiquidityGauge.sol";
import {Ownable2Step, Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {IChildLiquidityGaugeFactory} from "@interfaces/curve/IChildLiquidityGaugeFactory.sol";
contract CurveFactory is Factory, Ownable2Step {
/// @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"));
/// @notice Convex Booster.
address public immutable BOOSTER;
/// @notice Convex Minimal Proxy Factory for Only Boost.
address public immutable CONVEX_SIDECAR_FACTORY;
/// @notice The child liquidity gauge factories.
IChildLiquidityGaugeFactory[] public childLiquidityGaugeFactories;
/// @notice Error thrown when the set reward receiver fails.
error SetRewardReceiverFailed();
/// @notice Error thrown when the convex sidecar factory is not set.
error ConvexSidecarFactoryNotSet();
/// @notice Error thrown when the child liquidity gauge factories are not set.
error ChildLiquidityGaugeFactoriesNotSet();
/// @notice Event emitted when a vault is deployed.
event VaultDeployed(address gauge, address vault, address rewardReceiver, address sidecar);
constructor(
address admin,
address protocolController,
address vaultImplementation,
address rewardReceiverImplementation,
address locker,
address gateway,
address booster,
address convexSidecarFactory
)
Factory(protocolController, vaultImplementation, rewardReceiverImplementation, CURVE_PROTOCOL_ID, locker, gateway)
Ownable(admin)
{
BOOSTER = booster;
CONVEX_SIDECAR_FACTORY = convexSidecarFactory;
}
/// @notice Create a new vault.
/// @param _pid Pool id.
function create(uint256 _pid) external returns (address vault, address rewardReceiver, address sidecar) {
require(CONVEX_SIDECAR_FACTORY != address(0), ConvexSidecarFactoryNotSet());
(, address gauge,,,) = IL2Booster(BOOSTER).poolInfo(_pid);
/// 1. Create the vault.
(vault, rewardReceiver) = createVault(gauge);
/// 2. Attach the sidecar.
sidecar = ISidecarFactory(CONVEX_SIDECAR_FACTORY).create(gauge, abi.encode(_pid));
/// 3. Emit the event.
emit VaultDeployed(gauge, vault, rewardReceiver, sidecar);
}
function _isValidToken(address _token) internal view virtual override returns (bool isValid) {
/// If the token is not valid, return false.
if (!super._isValidToken(_token)) return false;
require(childLiquidityGaugeFactories.length > 0, ChildLiquidityGaugeFactoriesNotSet());
/// If the token is available as an inflation receiver, it's not valid.
for (uint256 i = 0; i < childLiquidityGaugeFactories.length; i++) {
if (childLiquidityGaugeFactories[i].is_valid_gauge(_token)) {
isValid = false;
break;
}
}
return isValid;
}
function _isValidGauge(address _gauge) internal view virtual override returns (bool isValid) {
require(childLiquidityGaugeFactories.length > 0, ChildLiquidityGaugeFactoriesNotSet());
/// Check if the gauge is a valid candidate and available as an inflation receiver.
/// This call always reverts if the gauge is not valid.
for (uint256 i = 0; i < childLiquidityGaugeFactories.length; i++) {
if (childLiquidityGaugeFactories[i].is_valid_gauge(_gauge)) {
isValid = true;
break;
}
}
/// Check if the gauge is not killed.
if (IL2LiquidityGauge(_gauge).is_killed()) {
isValid = false;
}
return isValid;
}
function _getAsset(address _gauge) internal view virtual override returns (address) {
return IL2LiquidityGauge(_gauge).lp_token();
}
function _setupRewardTokens(address _vault, address _gauge, address _rewardReceiver) internal virtual override {
/// Check if the gauge supports extra rewards.
/// This function is not supported on all gauges, depending on when they were deployed.
bytes memory data = abi.encodeWithSignature("reward_tokens(uint256)", 0);
(bool success,) = _gauge.call(data);
if (!success) return;
/// Loop through the extra reward tokens.
/// 8 is the maximum number of extra reward tokens supported by the gauges.
for (uint8 i = 0; i < 8; i++) {
/// Get the extra reward token address.
address _extraRewardToken = IL2LiquidityGauge(_gauge).reward_tokens(i);
(, uint256 periodFinish,,,) = IL2LiquidityGauge(_gauge).reward_data(_extraRewardToken);
/// If the reward data is not active, skip.
if (periodFinish < block.timestamp) continue;
/// If the address is 0, it means there are no more extra reward tokens.
if (_extraRewardToken == address(0)) break;
/// If the extra reward token is already in the vault, skip.
if (IRewardVault(_vault).isRewardToken(_extraRewardToken)) continue;
/// Performs checks on the extra reward token.
/// Checks like if the token is also an lp token that can be staked in the locker, these tokens are not supported.
if (_isValidToken(_extraRewardToken)) {
/// Then we add the extra reward token to the reward distributor through the strategy.
IRewardVault(_vault).addRewardToken(_extraRewardToken, _rewardReceiver);
}
}
}
function _setRewardReceiver(address _gauge, address _rewardReceiver) internal override {
/// Set RewardReceiver as RewardReceiver on Gauge.
bytes memory data = abi.encodeWithSignature("set_rewards_receiver(address)", _rewardReceiver);
require(_executeTransaction(_gauge, data), SetRewardReceiverFailed());
}
function _initializeVault(address, address _asset, address _gauge) internal override {
/// Initialize the vault.
/// We need to approve the asset to the gauge using the Locker.
bytes memory data = abi.encodeWithSignature("approve(address,uint256)", _gauge, type(uint256).max);
/// Execute the transaction.
require(_executeTransaction(_asset, data), ApproveFailed());
}
/// @notice Set the child liquidity gauge factories.
/// @param _childLiquidityGaugeFactories The child liquidity gauge factories.
function setChildLiquidityGaugeFactories(IChildLiquidityGaugeFactory[] memory _childLiquidityGaugeFactories)
external
onlyOwner
{
childLiquidityGaugeFactories = _childLiquidityGaugeFactories;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {ProtocolContext} from "src/ProtocolContext.sol";
/// @title Factory - Abstract Base Factory Contract
/// @notice A base contract for implementing protocol-specific vault factories
/// @dev Provides core functionality for creating and managing vaults across different protocols
/// Key responsibilities:
/// - Deploys vaults and reward receivers for protocol gauges
/// - Validates gauges and tokens
/// - Registers vaults with the protocol controller
/// - Sets up reward tokens for vaults
abstract contract Factory is ProtocolContext {
//////////////////////////////////////////////////////
// --- IMMUTABLES
//////////////////////////////////////////////////////
/// @notice Reward vault implementation address
/// @dev The implementation contract that will be cloned for each new vault
address public immutable REWARD_VAULT_IMPLEMENTATION;
/// @notice Reward receiver implementation address
/// @dev The implementation contract that will be cloned for each new reward receiver
address public immutable REWARD_RECEIVER_IMPLEMENTATION;
//////////////////////////////////////////////////////
// --- ERRORS
//////////////////////////////////////////////////////
/// @notice Error thrown when the gauge is not a valid candidate
error InvalidGauge();
/// @notice Error thrown when the approve fails
error ApproveFailed();
/// @notice Error thrown when the token is not valid
error InvalidToken();
/// @notice Error thrown when the deployment is not valid
error InvalidDeployment();
/// @notice Error thrown when the gauge has been already used
error AlreadyDeployed();
//////////////////////////////////////////////////////
// --- EVENTS
//////////////////////////////////////////////////////
/// @notice Emitted when a new vault is deployed
/// @param vault Address of the deployed vault
/// @param asset Address of the underlying asset
/// @param gauge Address of the associated gauge
event VaultDeployed(address vault, address asset, address gauge);
//////////////////////////////////////////////////////
// --- CONSTRUCTOR
//////////////////////////////////////////////////////
/// @notice Initializes the factory with protocol controller, reward token, and vault implementation
/// @param _protocolController Address of the protocol controller
/// @param _vaultImplementation Address of the reward vault implementation
/// @param _rewardReceiverImplementation Address of the reward receiver implementation
/// @param _protocolId Protocol identifier
/// @param _locker Address of the locker
/// @param _gateway Address of the gateway
constructor(
address _protocolController,
address _vaultImplementation,
address _rewardReceiverImplementation,
bytes4 _protocolId,
address _locker,
address _gateway
) ProtocolContext(_protocolId, _protocolController, _locker, _gateway) {
require(
_protocolController != address(0) && _vaultImplementation != address(0)
&& _rewardReceiverImplementation != address(0),
ZeroAddress()
);
REWARD_VAULT_IMPLEMENTATION = _vaultImplementation;
REWARD_RECEIVER_IMPLEMENTATION = _rewardReceiverImplementation;
}
//////////////////////////////////////////////////////
// --- EXTERNAL FUNCTIONS
//////////////////////////////////////////////////////
/// @notice Create a new vault for a given gauge
/// @dev Deploys a vault and reward receiver for the gauge, registers them, and sets up reward tokens
/// @param gauge Address of the gauge
/// @return vault Address of the deployed vault
/// @return rewardReceiver Address of the deployed reward receiver
/// @custom:throws InvalidGauge If the gauge is not valid
/// @custom:throws InvalidDeployment If the deployment is not valid
/// @custom:throws GaugeAlreadyUsed If the gauge has already been used
function createVault(address gauge) public virtual returns (address vault, address rewardReceiver) {
/// Perform checks on the gauge to make sure it's valid and can be used
require(_isValidGauge(gauge), InvalidGauge());
require(_isValidDeployment(gauge), InvalidDeployment());
require(PROTOCOL_CONTROLLER.vaults(gauge) == address(0), AlreadyDeployed());
/// Get the asset address from the gauge
address asset = _getAsset(gauge);
/// Prepare the initialization data for the vault
/// The vault needs: gauge and asset
bytes memory data = abi.encodePacked(gauge, asset);
/// Generate a deterministic salt based on the gauge and asset
bytes32 salt = keccak256(data);
/// Clone the vault implementation with the initialization data
vault = Clones.cloneDeterministicWithImmutableArgs(REWARD_VAULT_IMPLEMENTATION, data, salt);
/// Prepare the initialization data for the reward receiver
/// The reward receiver needs: vault
data = abi.encodePacked(vault);
/// Generate a deterministic salt based on the vault
salt = keccak256(abi.encodePacked(vault));
/// Deploy Reward Receiver.
rewardReceiver = Clones.cloneDeterministicWithImmutableArgs(REWARD_RECEIVER_IMPLEMENTATION, data, salt);
/// Initialize the vault.
/// @dev Can be approval if needed etc.
_initializeVault(vault, asset, gauge);
/// Register the vault in the protocol controller
_registerVault(gauge, vault, asset, rewardReceiver);
/// Add extra reward tokens to the vault
_setupRewardTokens(vault, gauge, rewardReceiver);
/// Set the reward receiver for the gauge
_setRewardReceiver(gauge, rewardReceiver);
/// Set the valid allocation target.
PROTOCOL_CONTROLLER.setValidAllocationTarget(gauge, LOCKER);
emit VaultDeployed(vault, asset, gauge);
}
/// @notice Sync reward tokens for a gauge
/// @dev Updates the reward tokens for an existing vault
/// @param gauge Address of the gauge
/// @custom:throws InvalidGauge If the gauge is not valid or has no associated vault
function syncRewardTokens(address gauge) external {
address vault = PROTOCOL_CONTROLLER.vaults(gauge);
require(vault != address(0), InvalidGauge());
_setupRewardTokens(vault, gauge, PROTOCOL_CONTROLLER.rewardReceiver(gauge));
}
//////////////////////////////////////////////////////
// --- INTERNAL VIRTUAL FUNCTIONS
//////////////////////////////////////////////////////
/// @notice Get the asset address from a gauge
/// @dev Must be implemented by derived factories to handle protocol-specific asset retrieval
/// @param gauge Address of the gauge
/// @return The address of the asset associated with the gauge
function _getAsset(address gauge) internal view virtual returns (address);
/// @notice Check if a deployment is valid
/// @dev Can be overridden by derived factories to add additional deployment validation
/// @return True if the deployment is valid, false otherwise
function _isValidDeployment(address) internal view virtual returns (bool) {
return true;
}
/// @notice Initialize the vault
/// @param vault Address of the vault
/// @param asset Address of the asset
/// @param gauge Address of the gauge
function _initializeVault(address vault, address asset, address gauge) internal virtual;
/// @notice Register the vault in the protocol controller
/// @param gauge Address of the gauge
/// @param vault Address of the vault
/// @param asset Address of the asset
/// @param rewardReceiver Address of the reward receiver
function _registerVault(address gauge, address vault, address asset, address rewardReceiver) internal {
PROTOCOL_CONTROLLER.registerVault(gauge, vault, asset, rewardReceiver, PROTOCOL_ID);
}
/// @notice Setup reward tokens for the vault
/// @dev Must be implemented by derived factories to handle protocol-specific reward token setup
/// @param vault Address of the vault
/// @param gauge Address of the gauge
/// @param rewardReceiver Address of the reward receiver
function _setupRewardTokens(address vault, address gauge, address rewardReceiver) internal virtual;
/// @notice Set the reward receiver for a gauge
/// @dev Must be implemented by derived factories to handle protocol-specific reward receiver setup
/// @param gauge Address of the gauge
/// @param rewardReceiver Address of the reward receiver
function _setRewardReceiver(address gauge, address rewardReceiver) internal virtual;
/// @notice Check if a gauge is valid
/// @dev Must be implemented by derived factories to handle protocol-specific gauge validation
/// @param gauge Address of the gauge
/// @return isValid True if the gauge is valid
function _isValidGauge(address gauge) internal view virtual returns (bool);
/// @notice Check if a token is valid as a reward token
/// @dev Validates that the token is not zero address and not the main reward token
/// @param token Address of the token
/// @return isValid True if the token is valid
function _isValidToken(address token) internal view virtual returns (bool) {
return token != address(0) && token != REWARD_TOKEN;
}
}/// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.19;
interface IL2Booster {
function poolLength() external view returns (uint256);
function poolInfo(uint256 pid)
external
view
returns (address lpToken, address gauge, address rewards, bool shutdown, address factory);
function deposit(uint256 _pid, uint256 _amount) external returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
/// @title IRewardVault
/// @notice Interface for the RewardVault contract
interface IRewardVault {
function addRewardToken(address rewardsToken, address distributor) external;
function depositRewards(address _rewardsToken, uint128 _amount) external;
function deposit(uint256 assets, address receiver, address referrer) external returns (uint256 shares);
function deposit(address account, address receiver, uint256 assets, address referrer)
external
returns (uint256 shares);
function claim(address[] calldata tokens, address receiver) external returns (uint256[] memory amounts);
function claim(address account, address[] calldata tokens, address receiver)
external
returns (uint256[] memory amounts);
function getRewardsDistributor(address token) external view returns (address);
function getLastUpdateTime(address token) external view returns (uint32);
function getPeriodFinish(address token) external view returns (uint32);
function getRewardRate(address token) external view returns (uint128);
function getRewardPerTokenStored(address token) external view returns (uint128);
function getRewardPerTokenPaid(address token, address account) external view returns (uint128);
function getClaimable(address token, address account) external view returns (uint128);
function getRewardTokens() external view returns (address[] memory);
function lastTimeRewardApplicable(address token) external view returns (uint256);
function rewardPerToken(address token) external view returns (uint128);
function earned(address account, address token) external view returns (uint128);
function isRewardToken(address rewardToken) external view returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
interface ISidecarFactory {
function sidecar(address gauge) external view returns (address);
function create(address token, bytes memory args) external returns (address);
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.0;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IL2LiquidityGauge {
function reward_data(address arg0)
external
view
returns (
address distributor,
uint256 period_finish,
uint256 rate,
uint256 last_update,
uint256 integral
);
function reward_tokens(uint256 arg0) external view returns (address);
function is_killed() external view returns (bool);
function lp_token() external view returns (address);
}
interface ILiquidityGauge is IERC20 {
event ApplyOwnership(address admin);
event CommitOwnership(address admin);
event Deposit(address indexed provider, uint256 value);
event UpdateLiquidityLimit(
address user, uint256 original_balance, uint256 original_supply, uint256 working_balance, uint256 working_supply
);
event Withdraw(address indexed provider, uint256 value);
function add_reward(address _reward_token, address _distributor) external;
function approve(address _spender, uint256 _value) external returns (bool);
function claim_rewards() external;
function claim_rewards(address _addr) external;
function claim_rewards(address _addr, address _receiver) external;
function claimable_tokens(address addr) external returns (uint256);
function decreaseAllowance(address _spender, uint256 _subtracted_value) external returns (bool);
function deposit(uint256 _value) external;
function deposit(uint256 _value, address _addr) external;
function deposit(uint256 _value, address _addr, bool _claim_rewards) external;
function deposit_reward_token(address _reward_token, uint256 _amount) external;
function increaseAllowance(address _spender, uint256 _added_value) external returns (bool);
function initialize(address _lp_token) external;
function kick(address addr) external;
function set_killed(bool _is_killed) external;
function set_reward_distributor(address _reward_token, address _distributor) external;
function set_rewards_receiver(address _receiver) external;
function transfer(address _to, uint256 _value) external returns (bool);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
function user_checkpoint(address addr) external returns (bool);
function withdraw(uint256 _value) external;
function withdraw(uint256 _value, bool _claim_rewards) external;
function allowance(address arg0, address arg1) external view returns (uint256);
function balanceOf(address arg0) external view returns (uint256);
function claimable_reward(address _user, address _reward_token) external view returns (uint256);
function claimed_reward(address _addr, address _token) external view returns (uint256);
function decimals() external view returns (uint256);
function factory() external view returns (address);
function future_epoch_time() external view returns (uint256);
function inflation_rate() external view returns (uint256);
function integrate_checkpoint() external view returns (uint256);
function integrate_checkpoint_of(address arg0) external view returns (uint256);
function integrate_fraction(address arg0) external view returns (uint256);
function integrate_inv_supply(uint256 arg0) external view returns (uint256);
function integrate_inv_supply_of(address arg0) external view returns (uint256);
function is_killed() external view returns (bool);
function lp_token() external view returns (address);
function name() external view returns (string memory);
function period() external view returns (int128);
function period_timestamp(uint256 arg0) external view returns (uint256);
function reward_count() external view returns (uint256);
function reward_data(address arg0)
external
view
returns (
address token,
address distributor,
uint256 period_finish,
uint256 rate,
uint256 last_update,
uint256 integral
);
function reward_integral_for(address arg0, address arg1) external view returns (uint256);
function reward_tokens(uint256 arg0) external view returns (address);
function rewards_receiver(address arg0) external view returns (address);
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function working_balances(address arg0) external view returns (uint256);
function working_supply() external view returns (uint256);
function admin() external view returns (address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.20;
import {Ownable} from "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This extension of the {Ownable} contract includes a two-step mechanism to transfer
* ownership, where the new owner must call {acceptOwnership} in order to replace the
* old one. This can help prevent common mistakes, such as transfers of ownership to
* incorrect accounts, or to contracts that are unable to interact with the
* permission system.
*
* The initial owner is specified at deployment time in the constructor for `Ownable`. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*
* Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.0;
interface IChildLiquidityGaugeFactory {
function voting_escrow() external view returns (address);
function is_valid_gauge(address _gauge) external view returns (bool);
}// 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: BUSL-1.1
pragma solidity 0.8.28;
import {IModuleManager} from "@interfaces/safe/IModuleManager.sol";
import {IAccountant} from "src/interfaces/IAccountant.sol";
import {IProtocolController} from "src/interfaces/IProtocolController.sol";
/// @title ProtocolContext
/// @author Stake DAO
/// @notice Base contract providing shared protocol configuration and transaction execution
/// @dev Inherited by Strategy and other protocol-specific contracts to ensure consistent configuration
contract ProtocolContext {
//////////////////////////////////////////////////////
// --- IMMUTABLES
//////////////////////////////////////////////////////
/// @notice Unique identifier for the protocol (e.g., keccak256("CURVE") for Curve)
/// @dev Used to look up protocol-specific components in ProtocolController
bytes4 public immutable PROTOCOL_ID;
/// @notice The locker contract that holds and manages protocol tokens (e.g., veCRV)
/// @dev On L2s, this may be the same as GATEWAY when no separate locker exists
address public immutable LOCKER;
/// @notice Safe multisig that owns the locker and executes privileged operations
/// @dev All protocol interactions go through this gateway for security
address public immutable GATEWAY;
/// @notice The accountant responsible for tracking rewards and user balances
/// @dev Retrieved from ProtocolController during construction
address public immutable ACCOUNTANT;
/// @notice The main reward token for this protocol (e.g., CRV for Curve)
/// @dev Retrieved from the accountant's configuration
address public immutable REWARD_TOKEN;
/// @notice Reference to the central registry for protocol components
IProtocolController public immutable PROTOCOL_CONTROLLER;
//////////////////////////////////////////////////////
// --- ERRORS
//////////////////////////////////////////////////////
/// @notice Error thrown when a required address is zero
error ZeroAddress();
/// @notice Error thrown when a protocol ID is zero
error InvalidProtocolId();
//////////////////////////////////////////////////////
// --- CONSTRUCTOR
//////////////////////////////////////////////////////
/// @notice Initializes protocol configuration that all inheriting contracts will use
/// @dev Retrieves accountant and reward token from ProtocolController for consistency
/// @param _protocolId The protocol identifier (must match registered protocol in controller)
/// @param _protocolController The protocol controller contract address
/// @param _locker The locker contract address (pass address(0) for L2s where gateway acts as locker)
/// @param _gateway The gateway contract address (Safe multisig)
/// @custom:throws ZeroAddress If protocol controller or gateway is zero
/// @custom:throws InvalidProtocolId If protocol ID is empty
constructor(bytes4 _protocolId, address _protocolController, address _locker, address _gateway) {
require(_protocolController != address(0) && _gateway != address(0), ZeroAddress());
require(_protocolId != bytes4(0), InvalidProtocolId());
GATEWAY = _gateway;
PROTOCOL_ID = _protocolId;
ACCOUNTANT = IProtocolController(_protocolController).accountant(_protocolId);
REWARD_TOKEN = IAccountant(ACCOUNTANT).REWARD_TOKEN();
PROTOCOL_CONTROLLER = IProtocolController(_protocolController);
// L2 optimization: Gateway can act as both transaction executor and token holder
if (_locker == address(0)) {
LOCKER = GATEWAY;
} else {
LOCKER = _locker;
}
}
//////////////////////////////////////////////////////
// --- INTERNAL FUNCTIONS
//////////////////////////////////////////////////////
/// @notice Executes privileged transactions through the Safe module system
/// @dev Handles two execution patterns:
/// - Mainnet: Gateway -> Locker -> Target (locker holds funds and executes)
/// - L2: Gateway acts as locker and executes directly on target
/// @param target The address of the contract to interact with
/// @param data The calldata to send to the target
/// @return success Whether the transaction executed successfully
function _executeTransaction(address target, bytes memory data) internal returns (bool success) {
if (LOCKER == GATEWAY) {
// L2 pattern: Gateway holds funds and executes directly
success = IModuleManager(GATEWAY).execTransactionFromModule(target, 0, data, IModuleManager.Operation.Call);
} else {
// Mainnet pattern: Gateway instructs locker (which holds funds) to execute
// The locker contract has the necessary approvals and balances
success = IModuleManager(GATEWAY).execTransactionFromModule(
LOCKER,
0,
abi.encodeWithSignature("execute(address,uint256,bytes)", target, 0, data),
IModuleManager.Operation.Call
);
}
}
}// 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.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// 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: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/**
* @title IModuleManager - An interface of contract managing Safe modules
* @notice Modules are extensions with unlimited access to a Safe that can be added to a Safe by its owners.
⚠️ WARNING: Modules are a security risk since they can execute arbitrary transactions,
so only trusted and audited modules should be added to a Safe. A malicious module can
completely takeover a Safe.
* @author @safe-global/safe-protocol
*/
interface IModuleManager {
enum Operation {
Call,
DelegateCall
}
event EnabledModule(address indexed module);
event DisabledModule(address indexed module);
event ExecutionFromModuleSuccess(address indexed module);
event ExecutionFromModuleFailure(address indexed module);
event ChangedModuleGuard(address indexed moduleGuard);
/**
* @notice Enables the module `module` for the Safe.
* @dev This can only be done via a Safe transaction.
* @param module Module to be whitelisted.
*/
function enableModule(address module) external;
/**
* @notice Disables the module `module` for the Safe.
* @dev This can only be done via a Safe transaction.
* @param prevModule Previous module in the modules linked list.
* @param module Module to be removed.
*/
function disableModule(address prevModule, address module) external;
/**
* @notice Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token)
* @param to Destination address of module transaction.
* @param value Ether value of module transaction.
* @param data Data payload of module transaction.
* @param operation Operation type of module transaction.
* @return success Boolean flag indicating if the call succeeded.
*/
function execTransactionFromModule(
address to,
uint256 value,
bytes memory data,
Operation operation
) external returns (bool success);
/**
* @notice Execute `operation` (0: Call, 1: DelegateCall) to `to` with `value` (Native Token) and return data
* @param to Destination address of module transaction.
* @param value Ether value of module transaction.
* @param data Data payload of module transaction.
* @param operation Operation type of module transaction.
* @return success Boolean flag indicating if the call succeeded.
* @return returnData Data returned by the call.
*/
function execTransactionFromModuleReturnData(
address to,
uint256 value,
bytes memory data,
Operation operation
) external returns (bool success, bytes memory returnData);
/**
* @notice Returns if a module is enabled
* @return True if the module is enabled
*/
function isModuleEnabled(address module) external view returns (bool);
/**
* @notice Returns an array of modules.
* If all entries fit into a single page, the next pointer will be 0x1.
* If another page is present, next will be the last element of the returned array.
* @param start Start of the page. Has to be a module or start pointer (0x1 address)
* @param pageSize Maximum number of modules that should be returned. Has to be > 0
* @return array Array of modules.
* @return next Start of the next page.
*/
function getModulesPaginated(address start, uint256 pageSize) external view returns (address[] memory array, address next);
/**
* @dev Set a module guard that checks transactions initiated by the module before execution
* This can only be done via a Safe transaction.
* ⚠️ IMPORTANT: Since a module guard has full power to block Safe transaction execution initiated via a module,
* a broken module guard can cause a denial of service for the Safe modules. Make sure to carefully
* audit the module guard code and design recovery mechanisms.
* @notice Set Module Guard `moduleGuard` for the Safe. Make sure you trust the module guard.
* @param moduleGuard The address of the module guard to be used or the zero address to disable the module guard.
*/
function setModuleGuard(address moduleGuard) external;
}// 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 _vaults, bytes[] calldata harvestData) external;
function claim(address[] calldata _vaults, bytes[] calldata harvestData, address receiver) external;
function claim(address[] calldata _vaults, address account, bytes[] calldata harvestData) external;
function claim(address[] calldata _vaults, address account, bytes[] calldata harvestData, address receiver)
external;
function claimProtocolFees() external;
function harvest(address[] calldata _vaults, bytes[] calldata _harvestData, address _receiver) external;
function REWARD_TOKEN() external view returns (address);
}/// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
interface IProtocolController {
function vaults(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 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 isShutdown(address) external view returns (bool);
function isFullyWithdrawn(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 shutdown(address _gauge) external;
function markGaugeAsFullyWithdrawn(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.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// 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;
}// 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/",
"shared/=node_modules/@stake-dao/shared/",
"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/",
"@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,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"protocolController","type":"address"},{"internalType":"address","name":"vaultImplementation","type":"address"},{"internalType":"address","name":"rewardReceiverImplementation","type":"address"},{"internalType":"address","name":"locker","type":"address"},{"internalType":"address","name":"gateway","type":"address"},{"internalType":"address","name":"booster","type":"address"},{"internalType":"address","name":"convexSidecarFactory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyDeployed","type":"error"},{"inputs":[],"name":"ApproveFailed","type":"error"},{"inputs":[],"name":"ChildLiquidityGaugeFactoriesNotSet","type":"error"},{"inputs":[],"name":"CloneArgumentsTooLong","type":"error"},{"inputs":[],"name":"ConvexSidecarFactoryNotSet","type":"error"},{"inputs":[],"name":"Create2EmptyBytecode","type":"error"},{"inputs":[],"name":"FailedDeployment","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidDeployment","type":"error"},{"inputs":[],"name":"InvalidGauge","type":"error"},{"inputs":[],"name":"InvalidProtocolId","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"SetRewardReceiverFailed","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"address","name":"gauge","type":"address"}],"name":"VaultDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"gauge","type":"address"},{"indexed":false,"internalType":"address","name":"vault","type":"address"},{"indexed":false,"internalType":"address","name":"rewardReceiver","type":"address"},{"indexed":false,"internalType":"address","name":"sidecar","type":"address"}],"name":"VaultDeployed","type":"event"},{"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":"CONVEX_SIDECAR_FACTORY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GATEWAY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCKER","outputs":[{"internalType":"address","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_RECEIVER_IMPLEMENTATION","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARD_VAULT_IMPLEMENTATION","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"childLiquidityGaugeFactories","outputs":[{"internalType":"contract IChildLiquidityGaugeFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"create","outputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"rewardReceiver","type":"address"},{"internalType":"address","name":"sidecar","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"createVault","outputs":[{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"rewardReceiver","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IChildLiquidityGaugeFactory[]","name":"_childLiquidityGaugeFactories","type":"address[]"}],"name":"setChildLiquidityGaugeFactories","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"gauge","type":"address"}],"name":"syncRewardTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101c0604052348015610010575f5ffd5b50604051611f2d380380611f2d83398101604081905261002f9161032b565b878787877fc715e3736a8cb018f630cb9a1df908ad1629e9c2da4cd190b2dc83d6687ba1698888828683836001600160a01b0383161580159061007a57506001600160a01b03811615155b6100975760405163d92e233d60e01b815260040160405180910390fd5b6001600160e01b031984166100bf576040516355e7c3d960e11b815260040160405180910390fd5b6001600160a01b0381811660c0526001600160e01b03198516608081905260405163669cc2c960e11b815260048101919091529084169063cd39859290602401602060405180830381865afa15801561011a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061013e91906103bd565b6001600160a01b031660e0819052604080516399248ea760e01b815290516399248ea7916004808201926020929091908290030181865afa158015610185573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101a991906103bd565b6001600160a01b03908116610100528381166101205282166101d95760c0516001600160a01b031660a0526101e7565b6001600160a01b03821660a0525b505050506001600160a01b0386161580159061020b57506001600160a01b03851615155b801561021f57506001600160a01b03841615155b61023c5760405163d92e233d60e01b815260040160405180910390fd5b5050506001600160a01b03918216610140528116610160528216905061027b57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b610284816102a5565b506001600160a01b0391821661018052166101a052506103dd945050505050565b600180546001600160a01b03191690556102be816102c1565b50565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b0381168114610326575f5ffd5b919050565b5f5f5f5f5f5f5f5f610100898b031215610343575f5ffd5b61034c89610310565b975061035a60208a01610310565b965061036860408a01610310565b955061037660608a01610310565b945061038460808a01610310565b935061039260a08a01610310565b92506103a060c08a01610310565b91506103ae60e08a01610310565b90509295985092959890939650565b5f602082840312156103cd575f5ffd5b6103d682610310565b9392505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051611a636104ca5f395f81816103a10152818161053e015261062501525f818161021f015261059b01525f8181610369015261095901525f81816101f001526108cf01525f818161028b015281816103f7015281816104b2015281816107eb015281816109f401526110ab01525f81816102fc01526114c801525f6102c501525f81816101b4015281816112cf0152818161133d01526113c101525f8181610130015281816109cc015281816112f901526113f001525f818161017401526110840152611a635ff3fe608060405234801561000f575f5ffd5b5060043610610127575f3560e01c80637dc93390116100a9578063c7da89611161006e578063c7da896114610351578063e14e387814610364578063e30c39781461038b578063ec1100c21461039c578063f2fde38b146103c3575f5ffd5b80637dc93390146102ad5780638b9d2940146102c05780638da5cb5b146102e757806399248ea7146102f7578063b4bd6f461461031e575f5ffd5b8063715018a6116100ef578063715018a61461021257806375b0ffd11461021a578063780900dc1461024157806379ba50971461027e5780637aaf53e614610286575f5ffd5b806308ecd9a61461012b5780630db41f311461016f578063338c5371146101af5780633bc9a431146101d65780634a7500a6146101eb575b5f5ffd5b6101527f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6101967f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160e01b03199091168152602001610166565b6101527f000000000000000000000000000000000000000000000000000000000000000081565b6101e96101e436600461167f565b6103d6565b005b6101527f000000000000000000000000000000000000000000000000000000000000000081565b6101e9610526565b6101527f000000000000000000000000000000000000000000000000000000000000000081565b61025461024f36600461169a565b610539565b604080516001600160a01b0394851681529284166020840152921691810191909152606001610166565b6101e9610731565b6101527f000000000000000000000000000000000000000000000000000000000000000081565b6101526102bb36600461169a565b61077a565b6101527f000000000000000000000000000000000000000000000000000000000000000081565b5f546001600160a01b0316610152565b6101527f000000000000000000000000000000000000000000000000000000000000000081565b61033161032c36600461167f565b6107a2565b604080516001600160a01b03938416815292909116602083015201610166565b6101e961035f3660046116d0565b610a9f565b6101527f000000000000000000000000000000000000000000000000000000000000000081565b6001546001600160a01b0316610152565b6101527f000000000000000000000000000000000000000000000000000000000000000081565b6101e96103d136600461167f565b610aba565b604051632988bb9f60e21b81526001600160a01b0382811660048301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063a622ee7c90602401602060405180830381865afa15801561043e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610462919061179b565b90506001600160a01b03811661048b576040516365da5bb960e11b815260040160405180910390fd5b604051630339050960e51b81526001600160a01b03838116600483015261052291839185917f000000000000000000000000000000000000000000000000000000000000000090911690636720a12090602401602060405180830381865afa1580156104f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061051d919061179b565b610b2a565b5050565b61052e610dd1565b6105375f610dfd565b565b5f80807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166105835760405163267f175960e01b815260040160405180910390fd5b604051631526fe2760e01b8152600481018590525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631526fe279060240160a060405180830381865afa1580156105e8573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061060c91906117c5565b50505091505061061b816107a2565b80945081955050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3f697ba828760405160200161066691815260200190565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610692929190611860565b6020604051808303815f875af11580156106ae573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106d2919061179b565b604080516001600160a01b0384811682528781166020830152868116828401528316606082015290519193507f08063c8075192206c58e6dd01ffef672f99055179aead6066f80fb31dd2db150919081900360800190a1509193909250565b60015433906001600160a01b0316811461076e5760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61077781610dfd565b50565b60028181548110610789575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f5f6107ad83610e16565b6107ca576040516365da5bb960e11b815260040160405180910390fd5b604051632988bb9f60e21b81526001600160a01b0384811660048301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063a622ee7c90602401602060405180830381865afa158015610832573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610856919061179b565b6001600160a01b03161461087d5760405163a6ef0ba160e01b815260040160405180910390fd5b5f61088784610f4f565b6040516001600160601b0319606087811b8216602084015283901b1660348201529091505f9060480160408051601f19818403018152919052805160208201209091506108f57f00000000000000000000000000000000000000000000000000000000000000008383610fb6565b6040516001600160601b0319606083901b16602082015290955060340160408051601f19818403018152908290526001600160601b0319606088901b166020830152925060340160405160208183030381529060405280519060200120905061097f7f00000000000000000000000000000000000000000000000000000000000000008383610fb6565b935061098c858488610fcd565b61099886868587611044565b6109a3858786610b2a565b6109ad8685611108565b60405163a129290360e01b81526001600160a01b0387811660048301527f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063a1292903906044015f604051808303815f87803b158015610a35575f5ffd5b505af1158015610a47573d5f5f3e3d5ffd5b5050604080516001600160a01b03898116825287811660208301528a168183015290517f26ad9f07a47e389150a15677a365d64f42af0000b792c182ada6a3b5ab193a0b9350908190036060019150a1505050915091565b610aa7610dd1565b80516105229060029060208401906115f4565b610ac2610dd1565b600180546001600160a01b0383166001600160a01b03199091168117909155610af25f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6040515f602482018190529060440160408051601f198184030181529181526020820180516001600160e01b03166354c49fe960e01b179052519091505f906001600160a01b03851690610b7f90849061189a565b5f604051808303815f865af19150503d805f8114610bb8576040519150601f19603f3d011682016040523d82523d5f602084013e610bbd565b606091505b5050905080610bcd575050505050565b5f5b60088160ff161015610dc9576040516354c49fe960e01b815260ff821660048201525f906001600160a01b038716906354c49fe990602401602060405180830381865afa158015610c22573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c46919061179b565b604051632474e32f60e11b81526001600160a01b0380831660048301529192505f918816906348e9c65e9060240160a060405180830381865afa158015610c8f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cb391906118a5565b50505091505042811015610cc8575050610dc1565b6001600160a01b038216610cdd575050610dc9565b6040516316bfae7f60e31b81526001600160a01b03838116600483015289169063b5fd73f890602401602060405180830381865afa158015610d21573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d4591906118ea565b15610d51575050610dc1565b610d5a82611177565b15610dbe5760405163023cb23960e41b81526001600160a01b03838116600483015287811660248301528916906323cb2390906044015f604051808303815f87803b158015610da7575f5ffd5b505af1158015610db9573d5f5f3e3d5ffd5b505050505b50505b600101610bcf565b505050505050565b5f546001600160a01b031633146105375760405163118cdaa760e01b8152336004820152602401610765565b600180546001600160a01b03191690556107778161125a565b6002545f90610e385760405163242a2cc560e01b815260040160405180910390fd5b5f5b600254811015610ee15760028181548110610e5757610e57611903565b5f91825260209091200154604051634b92037960e01b81526001600160a01b03858116600483015290911690634b92037990602401602060405180830381865afa158015610ea7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ecb91906118ea565b15610ed95760019150610ee1565b600101610e3a565b50816001600160a01b0316639c868ac06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f1e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f4291906118ea565b15610f4a57505f5b919050565b5f816001600160a01b03166382c630666040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f8c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fb0919061179b565b92915050565b5f610fc38484845f6112a9565b90505b9392505050565b6040516001600160a01b03821660248201525f1960448201525f9060640160408051601f198184030181529190526020810180516001600160e01b031663095ea7b360e01b179052905061102183826112cc565b61103e57604051633e3f8f7360e01b815260040160405180910390fd5b50505050565b604051633e331d7160e11b81526001600160a01b0385811660048301528481166024830152838116604483015282811660648301526001600160e01b03197f00000000000000000000000000000000000000000000000000000000000000001660848301527f00000000000000000000000000000000000000000000000000000000000000001690637c663ae29060a4015f604051808303815f87803b1580156110ec575f5ffd5b505af11580156110fe573d5f5f3e3d5ffd5b5050505050505050565b6040516001600160a01b03821660248201525f9060440160408051601f198184030181529190526020810180516001600160e01b0316635efcc08b60e11b179052905061115583826112cc565b61117257604051631475790360e11b815260040160405180910390fd5b505050565b5f611181826114b2565b61118c57505f919050565b6002546111ac5760405163242a2cc560e01b815260040160405180910390fd5b5f5b60025481101561125457600281815481106111cb576111cb611903565b5f91825260209091200154604051634b92037960e01b81526001600160a01b03858116600483015290911690634b92037990602401602060405180830381865afa15801561121b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061123f91906118ea565b1561124c575f9150611254565b6001016111ae565b50919050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f5f6112b58686611502565b90506112c2838583611560565b9695505050505050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316036113bf5760405163468721a760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063468721a7906113789086905f9087908290600401611917565b6020604051808303815f875af1158015611394573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113b891906118ea565b9050610fb0565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663468721a77f00000000000000000000000000000000000000000000000000000000000000005f865f876040516024016114259392919061196a565b60408051601f198184030181529181526020820180516001600160e01b0316635b0e93fb60e11b1790525160e085901b6001600160e01b0319168152611472939291905f90600401611917565b6020604051808303815f875af115801561148e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fc691906118ea565b5f6001600160a01b03821615801590610fb057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316141592915050565b6060615fd3825111156115285760405163250a241560e21b815260040160405180910390fd5b815161153590602d61199f565b8383604051602001611549939291906119be565b604051602081830303815290604052905092915050565b5f8347101561158b5760405163cf47918160e01b815247600482015260248101859052604401610765565b81515f036115ac57604051631328927760e21b815260040160405180910390fd5b8282516020840186f590503d1519811516156115cd576040513d5f823e3d81fd5b6001600160a01b038116610fc65760405163b06ebf3d60e01b815260040160405180910390fd5b828054828255905f5260205f20908101928215611647579160200282015b8281111561164757825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190611612565b50611653929150611657565b5090565b5b80821115611653575f8155600101611658565b6001600160a01b0381168114610777575f5ffd5b5f6020828403121561168f575f5ffd5b8135610fc68161166b565b5f602082840312156116aa575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b8035610f4a8161166b565b5f602082840312156116e0575f5ffd5b813567ffffffffffffffff8111156116f6575f5ffd5b8201601f81018413611706575f5ffd5b803567ffffffffffffffff811115611720576117206116b1565b8060051b604051601f19603f830116810181811067ffffffffffffffff8211171561174d5761174d6116b1565b60405291825260208184018101929081018784111561176a575f5ffd5b6020850194505b8385101561179057611782856116c5565b815260209485019401611771565b509695505050505050565b5f602082840312156117ab575f5ffd5b8151610fc68161166b565b80518015158114610f4a575f5ffd5b5f5f5f5f5f60a086880312156117d9575f5ffd5b85516117e48161166b565b60208701519095506117f58161166b565b60408701519094506118068161166b565b9250611814606087016117b6565b915060808601516118248161166b565b809150509295509295909350565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90610fc390830184611832565b5f81518060208401855e5f93019283525090919050565b5f610fc68284611883565b5f5f5f5f5f60a086880312156118b9575f5ffd5b85516118c48161166b565b602087015160408801516060890151608090990151929a91995097965090945092505050565b5f602082840312156118fa575f5ffd5b610fc6826117b6565b634e487b7160e01b5f52603260045260245ffd5b60018060a01b0385168152836020820152608060408201525f61193d6080830185611832565b90506002831061195b57634e487b7160e01b5f52602160045260245ffd5b82606083015295945050505050565b6001600160a01b038416815260ff831660208201526060604082018190525f9061199690830184611832565b95945050505050565b80820180821115610fb057634e487b7160e01b5f52601160045260245ffd5b606160f81b815260f084901b6001600160f01b0319166001820152703d81600a3d39f3363d3d373d3d3d363d7360781b6003820152606083901b6001600160601b03191660148201526e5af43d82803e903d91602b57fd5bf360881b60288201525f611996603783018461188356fea26469706673582212203999f4521ca8146620c8bc7b3a4f59595ecc9148aef4303b9d7a2cf882971d1a64736f6c634300081c0033000000000000000000000000000755fbe4a24d7478bfcfc1e561afce82d1ff620000000000000000000000004d4c2c4777625e97be1985682fae5a53f5c44a80000000000000000000000000b8b83008a2aca8d5f5feeae2c3e764de0290c286000000000000000000000000182137f70a3639a07ec385dec750d60b70bb3fbe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b6000000000000000000000000d3327cb05a8e0095a543d582b5b3ce3e19270389000000000000000000000000b8368dd16e0a29ba8936856887003be9bf31d3a4
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610127575f3560e01c80637dc93390116100a9578063c7da89611161006e578063c7da896114610351578063e14e387814610364578063e30c39781461038b578063ec1100c21461039c578063f2fde38b146103c3575f5ffd5b80637dc93390146102ad5780638b9d2940146102c05780638da5cb5b146102e757806399248ea7146102f7578063b4bd6f461461031e575f5ffd5b8063715018a6116100ef578063715018a61461021257806375b0ffd11461021a578063780900dc1461024157806379ba50971461027e5780637aaf53e614610286575f5ffd5b806308ecd9a61461012b5780630db41f311461016f578063338c5371146101af5780633bc9a431146101d65780634a7500a6146101eb575b5f5ffd5b6101527f00000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101967fc715e3730000000000000000000000000000000000000000000000000000000081565b6040516001600160e01b03199091168152602001610166565b6101527f00000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b681565b6101e96101e436600461167f565b6103d6565b005b6101527f000000000000000000000000b8b83008a2aca8d5f5feeae2c3e764de0290c28681565b6101e9610526565b6101527f000000000000000000000000d3327cb05a8e0095a543d582b5b3ce3e1927038981565b61025461024f36600461169a565b610539565b604080516001600160a01b0394851681529284166020840152921691810191909152606001610166565b6101e9610731565b6101527f0000000000000000000000004d4c2c4777625e97be1985682fae5a53f5c44a8081565b6101526102bb36600461169a565b61077a565b6101527f000000000000000000000000a7d6dd95a06d95b65edf32b94ed46996e151c06f81565b5f546001600160a01b0316610152565b6101527f000000000000000000000000331b9182088e2a7d6d3fe4742aba1fb231aecc5681565b61033161032c36600461167f565b6107a2565b604080516001600160a01b03938416815292909116602083015201610166565b6101e961035f3660046116d0565b610a9f565b6101527f000000000000000000000000182137f70a3639a07ec385dec750d60b70bb3fbe81565b6001546001600160a01b0316610152565b6101527f000000000000000000000000b8368dd16e0a29ba8936856887003be9bf31d3a481565b6101e96103d136600461167f565b610aba565b604051632988bb9f60e21b81526001600160a01b0382811660048301525f917f0000000000000000000000004d4c2c4777625e97be1985682fae5a53f5c44a809091169063a622ee7c90602401602060405180830381865afa15801561043e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610462919061179b565b90506001600160a01b03811661048b576040516365da5bb960e11b815260040160405180910390fd5b604051630339050960e51b81526001600160a01b03838116600483015261052291839185917f0000000000000000000000004d4c2c4777625e97be1985682fae5a53f5c44a8090911690636720a12090602401602060405180830381865afa1580156104f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061051d919061179b565b610b2a565b5050565b61052e610dd1565b6105375f610dfd565b565b5f80807f000000000000000000000000b8368dd16e0a29ba8936856887003be9bf31d3a46001600160a01b03166105835760405163267f175960e01b815260040160405180910390fd5b604051631526fe2760e01b8152600481018590525f907f000000000000000000000000d3327cb05a8e0095a543d582b5b3ce3e192703896001600160a01b031690631526fe279060240160a060405180830381865afa1580156105e8573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061060c91906117c5565b50505091505061061b816107a2565b80945081955050507f000000000000000000000000b8368dd16e0a29ba8936856887003be9bf31d3a46001600160a01b031663a3f697ba828760405160200161066691815260200190565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610692929190611860565b6020604051808303815f875af11580156106ae573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106d2919061179b565b604080516001600160a01b0384811682528781166020830152868116828401528316606082015290519193507f08063c8075192206c58e6dd01ffef672f99055179aead6066f80fb31dd2db150919081900360800190a1509193909250565b60015433906001600160a01b0316811461076e5760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61077781610dfd565b50565b60028181548110610789575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f5f6107ad83610e16565b6107ca576040516365da5bb960e11b815260040160405180910390fd5b604051632988bb9f60e21b81526001600160a01b0384811660048301525f917f0000000000000000000000004d4c2c4777625e97be1985682fae5a53f5c44a809091169063a622ee7c90602401602060405180830381865afa158015610832573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610856919061179b565b6001600160a01b03161461087d5760405163a6ef0ba160e01b815260040160405180910390fd5b5f61088784610f4f565b6040516001600160601b0319606087811b8216602084015283901b1660348201529091505f9060480160408051601f19818403018152919052805160208201209091506108f57f000000000000000000000000b8b83008a2aca8d5f5feeae2c3e764de0290c2868383610fb6565b6040516001600160601b0319606083901b16602082015290955060340160408051601f19818403018152908290526001600160601b0319606088901b166020830152925060340160405160208183030381529060405280519060200120905061097f7f000000000000000000000000182137f70a3639a07ec385dec750d60b70bb3fbe8383610fb6565b935061098c858488610fcd565b61099886868587611044565b6109a3858786610b2a565b6109ad8685611108565b60405163a129290360e01b81526001600160a01b0387811660048301527f00000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b6811660248301527f0000000000000000000000004d4c2c4777625e97be1985682fae5a53f5c44a80169063a1292903906044015f604051808303815f87803b158015610a35575f5ffd5b505af1158015610a47573d5f5f3e3d5ffd5b5050604080516001600160a01b03898116825287811660208301528a168183015290517f26ad9f07a47e389150a15677a365d64f42af0000b792c182ada6a3b5ab193a0b9350908190036060019150a1505050915091565b610aa7610dd1565b80516105229060029060208401906115f4565b610ac2610dd1565b600180546001600160a01b0383166001600160a01b03199091168117909155610af25f546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6040515f602482018190529060440160408051601f198184030181529181526020820180516001600160e01b03166354c49fe960e01b179052519091505f906001600160a01b03851690610b7f90849061189a565b5f604051808303815f865af19150503d805f8114610bb8576040519150601f19603f3d011682016040523d82523d5f602084013e610bbd565b606091505b5050905080610bcd575050505050565b5f5b60088160ff161015610dc9576040516354c49fe960e01b815260ff821660048201525f906001600160a01b038716906354c49fe990602401602060405180830381865afa158015610c22573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c46919061179b565b604051632474e32f60e11b81526001600160a01b0380831660048301529192505f918816906348e9c65e9060240160a060405180830381865afa158015610c8f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cb391906118a5565b50505091505042811015610cc8575050610dc1565b6001600160a01b038216610cdd575050610dc9565b6040516316bfae7f60e31b81526001600160a01b03838116600483015289169063b5fd73f890602401602060405180830381865afa158015610d21573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d4591906118ea565b15610d51575050610dc1565b610d5a82611177565b15610dbe5760405163023cb23960e41b81526001600160a01b03838116600483015287811660248301528916906323cb2390906044015f604051808303815f87803b158015610da7575f5ffd5b505af1158015610db9573d5f5f3e3d5ffd5b505050505b50505b600101610bcf565b505050505050565b5f546001600160a01b031633146105375760405163118cdaa760e01b8152336004820152602401610765565b600180546001600160a01b03191690556107778161125a565b6002545f90610e385760405163242a2cc560e01b815260040160405180910390fd5b5f5b600254811015610ee15760028181548110610e5757610e57611903565b5f91825260209091200154604051634b92037960e01b81526001600160a01b03858116600483015290911690634b92037990602401602060405180830381865afa158015610ea7573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ecb91906118ea565b15610ed95760019150610ee1565b600101610e3a565b50816001600160a01b0316639c868ac06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f1e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f4291906118ea565b15610f4a57505f5b919050565b5f816001600160a01b03166382c630666040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f8c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fb0919061179b565b92915050565b5f610fc38484845f6112a9565b90505b9392505050565b6040516001600160a01b03821660248201525f1960448201525f9060640160408051601f198184030181529190526020810180516001600160e01b031663095ea7b360e01b179052905061102183826112cc565b61103e57604051633e3f8f7360e01b815260040160405180910390fd5b50505050565b604051633e331d7160e11b81526001600160a01b0385811660048301528481166024830152838116604483015282811660648301526001600160e01b03197fc715e373000000000000000000000000000000000000000000000000000000001660848301527f0000000000000000000000004d4c2c4777625e97be1985682fae5a53f5c44a801690637c663ae29060a4015f604051808303815f87803b1580156110ec575f5ffd5b505af11580156110fe573d5f5f3e3d5ffd5b5050505050505050565b6040516001600160a01b03821660248201525f9060440160408051601f198184030181529190526020810180516001600160e01b0316635efcc08b60e11b179052905061115583826112cc565b61117257604051631475790360e11b815260040160405180910390fd5b505050565b5f611181826114b2565b61118c57505f919050565b6002546111ac5760405163242a2cc560e01b815260040160405180910390fd5b5f5b60025481101561125457600281815481106111cb576111cb611903565b5f91825260209091200154604051634b92037960e01b81526001600160a01b03858116600483015290911690634b92037990602401602060405180830381865afa15801561121b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061123f91906118ea565b1561124c575f9150611254565b6001016111ae565b50919050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f5f6112b58686611502565b90506112c2838583611560565b9695505050505050565b5f7f00000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b66001600160a01b03167f00000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b66001600160a01b0316036113bf5760405163468721a760e01b81526001600160a01b037f00000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b6169063468721a7906113789086905f9087908290600401611917565b6020604051808303815f875af1158015611394573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113b891906118ea565b9050610fb0565b7f00000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b66001600160a01b031663468721a77f00000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b65f865f876040516024016114259392919061196a565b60408051601f198184030181529181526020820180516001600160e01b0316635b0e93fb60e11b1790525160e085901b6001600160e01b0319168152611472939291905f90600401611917565b6020604051808303815f875af115801561148e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fc691906118ea565b5f6001600160a01b03821615801590610fb057507f000000000000000000000000331b9182088e2a7d6d3fe4742aba1fb231aecc566001600160a01b0316826001600160a01b0316141592915050565b6060615fd3825111156115285760405163250a241560e21b815260040160405180910390fd5b815161153590602d61199f565b8383604051602001611549939291906119be565b604051602081830303815290604052905092915050565b5f8347101561158b5760405163cf47918160e01b815247600482015260248101859052604401610765565b81515f036115ac57604051631328927760e21b815260040160405180910390fd5b8282516020840186f590503d1519811516156115cd576040513d5f823e3d81fd5b6001600160a01b038116610fc65760405163b06ebf3d60e01b815260040160405180910390fd5b828054828255905f5260205f20908101928215611647579160200282015b8281111561164757825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190611612565b50611653929150611657565b5090565b5b80821115611653575f8155600101611658565b6001600160a01b0381168114610777575f5ffd5b5f6020828403121561168f575f5ffd5b8135610fc68161166b565b5f602082840312156116aa575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b8035610f4a8161166b565b5f602082840312156116e0575f5ffd5b813567ffffffffffffffff8111156116f6575f5ffd5b8201601f81018413611706575f5ffd5b803567ffffffffffffffff811115611720576117206116b1565b8060051b604051601f19603f830116810181811067ffffffffffffffff8211171561174d5761174d6116b1565b60405291825260208184018101929081018784111561176a575f5ffd5b6020850194505b8385101561179057611782856116c5565b815260209485019401611771565b509695505050505050565b5f602082840312156117ab575f5ffd5b8151610fc68161166b565b80518015158114610f4a575f5ffd5b5f5f5f5f5f60a086880312156117d9575f5ffd5b85516117e48161166b565b60208701519095506117f58161166b565b60408701519094506118068161166b565b9250611814606087016117b6565b915060808601516118248161166b565b809150509295509295909350565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90610fc390830184611832565b5f81518060208401855e5f93019283525090919050565b5f610fc68284611883565b5f5f5f5f5f60a086880312156118b9575f5ffd5b85516118c48161166b565b602087015160408801516060890151608090990151929a91995097965090945092505050565b5f602082840312156118fa575f5ffd5b610fc6826117b6565b634e487b7160e01b5f52603260045260245ffd5b60018060a01b0385168152836020820152608060408201525f61193d6080830185611832565b90506002831061195b57634e487b7160e01b5f52602160045260245ffd5b82606083015295945050505050565b6001600160a01b038416815260ff831660208201526060604082018190525f9061199690830184611832565b95945050505050565b80820180821115610fb057634e487b7160e01b5f52601160045260245ffd5b606160f81b815260f084901b6001600160f01b0319166001820152703d81600a3d39f3363d3d373d3d3d363d7360781b6003820152606083901b6001600160601b03191660148201526e5af43d82803e903d91602b57fd5bf360881b60288201525f611996603783018461188356fea26469706673582212203999f4521ca8146620c8bc7b3a4f59595ecc9148aef4303b9d7a2cf882971d1a64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000755fbe4a24d7478bfcfc1e561afce82d1ff620000000000000000000000004d4c2c4777625e97be1985682fae5a53f5c44a80000000000000000000000000b8b83008a2aca8d5f5feeae2c3e764de0290c286000000000000000000000000182137f70a3639a07ec385dec750d60b70bb3fbe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b6000000000000000000000000d3327cb05a8e0095a543d582b5b3ce3e19270389000000000000000000000000b8368dd16e0a29ba8936856887003be9bf31d3a4
-----Decoded View---------------
Arg [0] : admin (address): 0x000755Fbe4A24d7478bfcFC1E561AfCE82d1ff62
Arg [1] : protocolController (address): 0x4D4c2C4777625e97be1985682fAE5A53f5C44A80
Arg [2] : vaultImplementation (address): 0xB8B83008a2Aca8D5F5feeae2c3e764DE0290c286
Arg [3] : rewardReceiverImplementation (address): 0x182137f70A3639A07EC385DeC750d60B70bb3fbE
Arg [4] : locker (address): 0x0000000000000000000000000000000000000000
Arg [5] : gateway (address): 0x52f541764E6e90eeBc5c21Ff570De0e2D63766B6
Arg [6] : booster (address): 0xd3327cb05a8E0095A543D582b5B3Ce3e19270389
Arg [7] : convexSidecarFactory (address): 0xb8368DD16E0A29ba8936856887003Be9bF31d3A4
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000000755fbe4a24d7478bfcfc1e561afce82d1ff62
Arg [1] : 0000000000000000000000004d4c2c4777625e97be1985682fae5a53f5c44a80
Arg [2] : 000000000000000000000000b8b83008a2aca8d5f5feeae2c3e764de0290c286
Arg [3] : 000000000000000000000000182137f70a3639a07ec385dec750d60b70bb3fbe
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 00000000000000000000000052f541764e6e90eebc5c21ff570de0e2d63766b6
Arg [6] : 000000000000000000000000d3327cb05a8e0095a543d582b5b3ce3e19270389
Arg [7] : 000000000000000000000000b8368dd16e0a29ba8936856887003be9bf31d3a4
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
[ Download: CSV Export ]
[ Download: CSV Export ]
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.