Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"contracts/rewards_fuses/stake_dao_v2/StakeDaoV2ClaimFuse.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IRewardVault} from "../../fuses/stake_dao_v2/ext/IRewardVault.sol";
import {IAccountant} from "../../fuses/stake_dao_v2/ext/IAccountant.sol";
import {PlasmaVaultConfigLib} from "../../libraries/PlasmaVaultConfigLib.sol";
import {PlasmaVaultLib} from "../../libraries/PlasmaVaultLib.sol";
contract StakeDaoV2ClaimFuse {
using SafeERC20 for IERC20;
event StakeDaoV2MainRewardsClaimed(
address indexed version,
address receiver,
address rewardVault,
address accountant,
address gauge
);
event StakeDaoV2ExtraRewardsClaimed(
address indexed version,
address receiver,
address rewardVault,
address[] tokens,
uint256[] amounts
);
error StakeDaoV2ClaimFuseRewardVaultNotGranted(address vault);
error StakeDaoV2ClaimFuseArrayLengthMismatch(uint256 vaultsLength, uint256 tokensLength);
error StakeDaoV2ClaimFuseRewardsClaimManagerNotSet();
address public immutable VERSION;
uint256 public immutable MARKET_ID;
constructor(uint256 marketId_) {
VERSION = address(this);
MARKET_ID = marketId_;
}
/// Main Protocol Rewards (e.g., CRV, BAL)
function claimMainRewards(address[] calldata rewardVaults) public {
address receiver = _getReceiver();
_validateRewardVaults(rewardVaults);
address[] memory gauges;
IAccountant accountant;
address rewardVault;
uint256 length = rewardVaults.length;
for (uint256 i; i < length; i++) {
rewardVault = rewardVaults[i];
accountant = IRewardVault(rewardVault).ACCOUNTANT();
gauges = new address[](1);
gauges[0] = IRewardVault(rewardVault).gauge();
accountant.claim(gauges, new bytes[](0), receiver);
emit StakeDaoV2MainRewardsClaimed(VERSION, receiver, rewardVault, address(accountant), gauges[0]);
}
}
/// Extra rewards (e.g., CVX, LDO)
function claimExtraRewards(address[] calldata rewardVaults, address[][] calldata rewardVaultsTokens) public {
address receiver = _getReceiver();
_validateRewardVaults(rewardVaults);
uint256[] memory amounts;
uint256 length = rewardVaults.length;
for (uint256 i; i < length; i++) {
amounts = IRewardVault(rewardVaults[i]).claim(rewardVaultsTokens[i], receiver);
emit StakeDaoV2ExtraRewardsClaimed(VERSION, receiver, rewardVaults[i], rewardVaultsTokens[i], amounts);
}
}
function _getReceiver() internal view returns (address receiver) {
receiver = PlasmaVaultLib.getRewardsClaimManagerAddress();
if (receiver == address(0)) {
revert StakeDaoV2ClaimFuseRewardsClaimManagerNotSet();
}
return receiver;
}
function _validateRewardVaults(address[] calldata rewardVaults) internal view {
uint256 length = rewardVaults.length;
for (uint256 i; i < length; i++) {
if (!PlasmaVaultConfigLib.isSubstrateAsAssetGranted(MARKET_ID, rewardVaults[i])) {
revert StakeDaoV2ClaimFuseRewardVaultNotGranted(rewardVaults[i]);
}
}
}
}
"
},
"node_modules/@openzeppelin/contracts/token/ERC20/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the 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);
}
"
},
"node_modules/@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}
"
},
"contracts/fuses/stake_dao_v2/ext/IRewardVault.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
import {IAccountant} from "./IAccountant.sol";
interface IRewardVault {
/// @notice Accountant tracks user balances and main protocol rewards
// solhint-disable-next-line func-name-mixedcase
function ACCOUNTANT() external view returns (IAccountant accountant);
/// @notice Claims rewards for multiple tokens in a single transaction
/// @dev Updates reward state and transfers claimed rewards to the receiver
/// @param tokens Array of reward token addresses to claim
/// @param receiver Address to receive the claimed rewards (defaults to msg.sender if zero)
/// @return amounts Array of amounts claimed for each token, in the same order as input tokens
function claim(address[] calldata tokens, address receiver) external returns (uint256[] memory amounts);
/// @notice Retrieves the gauge address from clone arguments
/// @dev Uses assembly to read from clone initialization data
/// @return gauge The gauge contract address
/// @custom:reverts CloneArgsNotFound if clone is incorrectly initialized
function gauge() external view returns (address gauge);
}
"
},
"contracts/fuses/stake_dao_v2/ext/IAccountant.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
interface IAccountant {
function claim(address[] calldata _gauges, bytes[] calldata harvestData, address receiver) external;
}
"
},
"contracts/libraries/PlasmaVaultConfigLib.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
import {PlasmaVaultStorageLib} from "./PlasmaVaultStorageLib.sol";
/// @title Plasma Vault Configuration Library responsible for managing the configuration of the Plasma Vault
library PlasmaVaultConfigLib {
event MarketSubstratesGranted(uint256 marketId, bytes32[] substrates);
/// @notice Checks if a given asset address is granted as a substrate for a specific market
/// @dev This function is part of the Plasma Vault's substrate management system that controls which assets can be used in specific markets
///
/// @param marketId_ The ID of the market to check
/// @param substrateAsAsset The address of the asset to verify as a substrate
/// @return bool True if the asset is granted as a substrate for the market, false otherwise
///
/// @custom:security-notes
/// - Substrates are stored internally as bytes32 values
/// - Asset addresses are converted to bytes32 for storage efficiency
/// - Part of the vault's asset distribution protection system
///
/// @custom:context The function is used in conjunction with:
/// - PlasmaVault's execute() function for validating market operations
/// - PlasmaVaultGovernance's grantMarketSubstrates() for configuration
/// - Asset distribution protection system for market limit enforcement
///
/// @custom:example
/// ```solidity
/// // Check if USDC is granted for market 1
/// bool isGranted = isSubstrateAsAssetGranted(1, USDC_ADDRESS);
/// ```
///
/// @custom:permissions
/// - View function, no special permissions required
/// - Substrate grants are managed by ATOMIST_ROLE through PlasmaVaultGovernance
///
/// @custom:related-functions
/// - grantMarketSubstrates(): For granting substrates to markets
/// - isMarketSubstrateGranted(): For checking non-asset substrates
/// - getMarketSubstrates(): For retrieving all granted substrates
function isSubstrateAsAssetGranted(uint256 marketId_, address substrateAsAsset) internal view returns (bool) {
PlasmaVaultStorageLib.MarketSubstratesStruct storage marketSubstrates = _getMarketSubstrates(marketId_);
return marketSubstrates.substrateAllowances[addressToBytes32(substrateAsAsset)] == 1;
}
/// @notice Validates if a substrate is granted for a specific market
/// @dev Part of the Plasma Vault's substrate management system that enables flexible market configurations
///
/// @param marketId_ The ID of the market to check
/// @param substrate_ The bytes32 identifier of the substrate to verify
/// @return bool True if the substrate is granted for the market, false otherwise
///
/// @custom:security-notes
/// - Substrates are stored and compared as raw bytes32 values
/// - Used for both asset and non-asset substrates (e.g., vaults, parameters)
/// - Critical for market access control and security
///
/// @custom:context The function is used for:
/// - Validating market operations in PlasmaVault.execute()
/// - Checking substrate permissions before market interactions
/// - Supporting various substrate types:
/// * Asset addresses (converted to bytes32)
/// * Protocol-specific vault identifiers
/// * Market parameters and configuration values
///
/// @custom:example
/// ```solidity
/// // Check if a compound vault substrate is granted
/// bytes32 vaultId = keccak256(abi.encode("compound-vault-1"));
/// bool isGranted = isMarketSubstrateGranted(1, vaultId);
///
/// // Check if a market parameter is granted
/// bytes32 param = bytes32("max-leverage");
/// bool isParamGranted = isMarketSubstrateGranted(1, param);
/// ```
///
/// @custom:permissions
/// - View function, no special permissions required
/// - Substrate grants are managed by ATOMIST_ROLE through PlasmaVaultGovernance
///
/// @custom:related-functions
/// - isSubstrateAsAssetGranted(): For checking asset-specific substrates
/// - grantMarketSubstrates(): For granting substrates to markets
/// - getMarketSubstrates(): For retrieving all granted substrates
function isMarketSubstrateGranted(uint256 marketId_, bytes32 substrate_) internal view returns (bool) {
PlasmaVaultStorageLib.MarketSubstratesStruct storage marketSubstrates = _getMarketSubstrates(marketId_);
return marketSubstrates.substrateAllowances[substrate_] == 1;
}
/// @notice Retrieves all granted substrates for a specific market
/// @dev Part of the Plasma Vault's substrate management system that provides visibility into market configurations
///
/// @param marketId_ The ID of the market to query
/// @return bytes32[] Array of all granted substrate identifiers for the market
///
/// @custom:security-notes
/// - Returns raw bytes32 values that may represent different substrate types
/// - Order of substrates in array is preserved from grant operations
/// - Empty array indicates no substrates are granted
///
/// @custom:context The function is used for:
/// - Auditing market configurations
/// - Validating substrate grants during governance operations
/// - Supporting UI/external systems that need market configuration data
/// - Debugging and monitoring market setups
///
/// @custom:substrate-types The returned array may contain:
/// - Asset addresses (converted to bytes32)
/// - Protocol-specific vault identifiers
/// - Market parameters and configuration values
/// - Any other substrate type granted to the market
///
/// @custom:example
/// ```solidity
/// // Get all substrates for market 1
/// bytes32[] memory substrates = getMarketSubstrates(1);
///
/// // Process different substrate types
/// for (uint256 i = 0; i < substrates.length; i++) {
/// if (isSubstrateAsAssetGranted(1, bytes32ToAddress(substrates[i]))) {
/// // Handle asset substrate
/// } else {
/// // Handle other substrate type
/// }
/// }
/// ```
///
/// @custom:permissions
/// - View function, no special permissions required
/// - Useful for both governance and user interfaces
///
/// @custom:related-functions
/// - isMarketSubstrateGranted(): For checking individual substrate grants
/// - grantMarketSubstrates(): For modifying substrate grants
/// - bytes32ToAddress(): For converting asset substrates back to addresses
function getMarketSubstrates(uint256 marketId_) internal view returns (bytes32[] memory) {
return _getMarketSubstrates(marketId_).substrates;
}
/// @notice Grants or updates substrate permissions for a specific market
/// @dev Core function for managing market substrate configurations in the Plasma Vault system
///
/// @param marketId_ The ID of the market to configure
/// @param substrates_ Array of substrate identifiers to grant to the market
///
/// @custom:security-notes
/// - Revokes all existing substrate grants before applying new ones
/// - Atomic operation - either all substrates are granted or none
/// - Emits MarketSubstratesGranted event for tracking changes
/// - Critical for market security and access control
///
/// @custom:context The function is used for:
/// - Initial market setup by governance
/// - Updating market configurations
/// - Managing protocol integrations
/// - Controlling asset access per market
///
/// @custom:substrate-handling
/// - Accepts both asset and non-asset substrates:
/// * Asset addresses (converted to bytes32)
/// * Protocol-specific vault identifiers
/// * Market parameters
/// * Configuration values
/// - Maintains a list of active substrates
/// - Updates allowance mapping for each substrate
///
/// @custom:example
/// ```solidity
/// // Grant multiple substrates to market 1
/// bytes32[] memory substrates = new bytes32[](2);
/// substrates[0] = addressToBytes32(USDC_ADDRESS);
/// substrates[1] = keccak256(abi.encode("compound-vault-1"));
/// grantMarketSubstrates(1, substrates);
/// ```
///
/// @custom:permissions
/// - Should only be called by authorized governance functions
/// - Typically restricted to ATOMIST_ROLE
/// - Critical for vault security
///
/// @custom:related-functions
/// - isMarketSubstrateGranted(): For checking granted substrates
/// - getMarketSubstrates(): For viewing current grants
/// - grantSubstratesAsAssetsToMarket(): For asset-specific grants
///
/// @custom:events
/// - Emits MarketSubstratesGranted(marketId, substrates)
function grantMarketSubstrates(uint256 marketId_, bytes32[] memory substrates_) internal {
PlasmaVaultStorageLib.MarketSubstratesStruct storage marketSubstrates = _getMarketSubstrates(marketId_);
_revokeMarketSubstrates(marketSubstrates);
bytes32[] memory list = new bytes32[](substrates_.length);
for (uint256 i; i < substrates_.length; ++i) {
marketSubstrates.substrateAllowances[substrates_[i]] = 1;
list[i] = substrates_[i];
}
marketSubstrates.substrates = list;
emit MarketSubstratesGranted(marketId_, substrates_);
}
/// @notice Grants asset-specific substrates to a market
/// @dev Specialized function for managing asset-type substrates in the Plasma Vault system
///
/// @param marketId_ The ID of the market to configure
/// @param substratesAsAssets_ Array of asset addresses to grant as substrates
///
/// @custom:security-notes
/// - Revokes all existing substrate grants before applying new ones
/// - Converts addresses to bytes32 for storage efficiency
/// - Atomic operation - either all assets are granted or none
/// - Emits MarketSubstratesGranted event with converted addresses
/// - Critical for market asset access control
///
/// @custom:context The function is used for:
/// - Setting up asset permissions for markets
/// - Managing DeFi protocol integrations
/// - Controlling which tokens can be used in specific markets
/// - Implementing asset-based strategies
///
/// @custom:implementation-details
/// - Converts each address to bytes32 using addressToBytes32()
/// - Updates both allowance mapping and substrate list
/// - Maintains consistency between address and bytes32 representations
/// - Ensures proper event emission with converted values
///
/// @custom:example
/// ```solidity
/// // Grant USDC and DAI access to market 1
/// address[] memory assets = new address[](2);
/// assets[0] = USDC_ADDRESS;
/// assets[1] = DAI_ADDRESS;
/// grantSubstratesAsAssetsToMarket(1, assets);
/// ```
///
/// @custom:permissions
/// - Should only be called by authorized governance functions
/// - Typically restricted to ATOMIST_ROLE
/// - Critical for vault security and asset management
///
/// @custom:related-functions
/// - grantMarketSubstrates(): For granting general substrates
/// - isSubstrateAsAssetGranted(): For checking asset grants
/// - addressToBytes32(): For address conversion
///
/// @custom:events
/// - Emits MarketSubstratesGranted(marketId, convertedSubstrates)
function grantSubstratesAsAssetsToMarket(uint256 marketId_, address[] calldata substratesAsAssets_) internal {
PlasmaVaultStorageLib.MarketSubstratesStruct storage marketSubstrates = _getMarketSubstrates(marketId_);
_revokeMarketSubstrates(marketSubstrates);
bytes32[] memory list = new bytes32[](substratesAsAssets_.length);
for (uint256 i; i < substratesAsAssets_.length; ++i) {
marketSubstrates.substrateAllowances[addressToBytes32(substratesAsAssets_[i])] = 1;
list[i] = addressToBytes32(substratesAsAssets_[i]);
}
marketSubstrates.substrates = list;
emit MarketSubstratesGranted(marketId_, list);
}
/// @notice Converts an Ethereum address to its bytes32 representation for substrate storage
/// @dev Core utility function for substrate address handling in the Plasma Vault system
///
/// @param address_ The Ethereum address to convert
/// @return bytes32 The bytes32 representation of the address
///
/// @custom:security-notes
/// - Performs unchecked conversion from address to bytes32
/// - Pads the address (20 bytes) with zeros to fill bytes32 (32 bytes)
/// - Used for storage efficiency in substrate mappings
/// - Critical for consistent substrate identifier handling
///
/// @custom:context The function is used for:
/// - Converting asset addresses for substrate storage
/// - Maintaining consistent substrate identifier format
/// - Supporting the substrate allowance system
/// - Enabling efficient storage and comparison operations
///
/// @custom:implementation-details
/// - Uses uint160 casting to handle address bytes
/// - Follows standard Solidity type conversion patterns
/// - Zero-pads the upper bytes implicitly
/// - Maintains compatibility with bytes32ToAddress()
///
/// @custom:example
/// ```solidity
/// // Convert USDC address to substrate identifier
/// bytes32 usdcSubstrate = addressToBytes32(USDC_ADDRESS);
///
/// // Use in substrate allowance mapping
/// marketSubstrates.substrateAllowances[usdcSubstrate] = 1;
/// ```
///
/// @custom:permissions
/// - Pure function, no state modifications
/// - Can be called by any function
/// - Used internally for substrate management
///
/// @custom:related-functions
/// - bytes32ToAddress(): Complementary conversion function
/// - grantSubstratesAsAssetsToMarket(): Uses this for address conversion
/// - isSubstrateAsAssetGranted(): Uses converted values for comparison
function addressToBytes32(address address_) internal pure returns (bytes32) {
return bytes32(uint256(uint160(address_)));
}
/// @notice Converts a bytes32 substrate identifier to its corresponding address representation
/// @dev Core utility function for substrate address handling in the Plasma Vault system
///
/// @param substrate_ The bytes32 substrate identifier to convert
/// @return address The resulting Ethereum address
///
/// @custom:security-notes
/// - Performs unchecked conversion from bytes32 to address
/// - Only the last 20 bytes (160 bits) are used
/// - Should only be used for known substrate conversions
/// - Critical for proper asset substrate handling
///
/// @custom:context The function is used for:
/// - Converting stored substrate identifiers back to asset addresses
/// - Processing asset-type substrates in market operations
/// - Interfacing with external protocols using addresses
/// - Validating asset substrate configurations
///
/// @custom:implementation-details
/// - Uses uint160 casting to ensure proper address size
/// - Follows standard Solidity address conversion pattern
/// - Maintains compatibility with addressToBytes32()
/// - Zero-pads the upper bytes implicitly
///
/// @custom:example
/// ```solidity
/// // Convert a stored substrate back to an asset address
/// bytes32 storedSubstrate = marketSubstrates.substrates[0];
/// address assetAddress = bytes32ToAddress(storedSubstrate);
///
/// // Use in asset validation
/// if (assetAddress == USDC_ADDRESS) {
/// // Handle USDC-specific logic
/// }
/// ```
///
/// @custom:related-functions
/// - addressToBytes32(): Complementary conversion function
/// - isSubstrateAsAssetGranted(): Uses this for address comparison
/// - getMarketSubstrates(): Returns values that may need conversion
function bytes32ToAddress(bytes32 substrate_) internal pure returns (address) {
return address(uint160(uint256(substrate_)));
}
/// @notice Gets the market substrates configuration for a specific market
function _getMarketSubstrates(
uint256 marketId_
) private view returns (PlasmaVaultStorageLib.MarketSubstratesStruct storage) {
return PlasmaVaultStorageLib.getMarketSubstrates().value[marketId_];
}
function _revokeMarketSubstrates(PlasmaVaultStorageLib.MarketSubstratesStruct storage marketSubstrates) private {
uint256 length = marketSubstrates.substrates.length;
for (uint256 i; i < length; ++i) {
marketSubstrates.substrateAllowances[marketSubstrates.substrates[i]] = 0;
}
}
}
"
},
"contracts/libraries/PlasmaVaultLib.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {Errors} from "./errors/Errors.sol";
import {PlasmaVaultStorageLib} from "./PlasmaVaultStorageLib.sol";
import {FusesLib} from "./FusesLib.sol";
/// @title InstantWithdrawalFusesParamsStruct
/// @notice A technical struct used to configure instant withdrawal fuses and their parameters in the Plasma Vault system
/// @dev This struct is used primarily in configureInstantWithdrawalFuses function to set up withdrawal paths
struct InstantWithdrawalFusesParamsStruct {
/// @notice The address of the fuse contract that handles a specific withdrawal path
/// @dev Must be a valid and supported fuse contract address that implements instant withdrawal logic
address fuse;
/// @notice Array of parameters specific to the fuse's withdrawal logic
/// @dev Parameter structure:
/// - params[0]: Always represents the withdrawal amount in underlying token decimals (set during withdrawal, not during configuration)
/// - params[1+]: Additional fuse-specific parameters such as:
/// - Asset addresses
/// - Market IDs
/// - Slippage tolerances
/// - Protocol-specific parameters
/// @dev The same fuse can appear multiple times with different params for different withdrawal paths
bytes32[] params;
}
/// @title Plasma Vault Library
/// @notice Core library responsible for managing the Plasma Vault's state and operations
/// @dev Provides centralized management of vault operations, fees, configuration and state updates
///
/// Key responsibilities:
/// - Asset management and accounting
/// - Fee configuration and calculations
/// - Market balance tracking and updates
/// - Withdrawal system configuration
/// - Access control and execution state
/// - Price oracle integration
/// - Rewards claim management
library PlasmaVaultLib {
using SafeCast for uint256;
using SafeCast for int256;
/// @dev Hard CAP for the performance fee in percentage - 50%
uint256 public constant PERFORMANCE_MAX_FEE_IN_PERCENTAGE = 5000;
/// @dev Hard CAP for the management fee in percentage - 5%
uint256 public constant MANAGEMENT_MAX_FEE_IN_PERCENTAGE = 500;
/// @dev The offset for the underlying asset decimals in the Plasma Vault
uint8 public constant DECIMALS_OFFSET = 2;
error InvalidPerformanceFee(uint256 feeInPercentage);
error InvalidManagementFee(uint256 feeInPercentage);
event InstantWithdrawalFusesConfigured(InstantWithdrawalFusesParamsStruct[] fuses);
event PriceOracleMiddlewareChanged(address newPriceOracleMiddleware);
event PerformanceFeeDataConfigured(address feeAccount, uint256 feeInPercentage);
event ManagementFeeDataConfigured(address feeAccount, uint256 feeInPercentage);
event RewardsClaimManagerAddressChanged(address newRewardsClaimManagerAddress);
event DependencyBalanceGraphChanged(uint256 marketId, uint256[] newDependenceGraph);
event WithdrawManagerChanged(address newWithdrawManager);
event TotalSupplyCapChanged(uint256 newTotalSupplyCap);
/// @notice Gets the total assets in the vault for all markets
/// @dev Retrieves the total value of assets across all integrated markets and protocols
/// @return uint256 The total assets in the vault, represented in decimals of the underlying asset
///
/// This function:
/// - Returns the raw total of assets without considering:
/// - Unrealized management fees
/// - Unrealized performance fees
/// - Pending rewards
/// - Current vault balance
///
/// Used by:
/// - PlasmaVault.totalAssets() for share price calculations
/// - Fee calculations and accrual
/// - Asset distribution checks
/// - Market limit validations
///
/// @dev Important: This value represents only the tracked assets in markets,
/// for full vault assets see PlasmaVault._getGrossTotalAssets()
function getTotalAssetsInAllMarkets() internal view returns (uint256) {
return PlasmaVaultStorageLib.getTotalAssets().value;
}
/// @notice Gets the total assets in the vault for a specific market
/// @param marketId_ The ID of the market to query
/// @return uint256 The total assets in the vault for the market, represented in decimals of the underlying asset
///
/// @dev This function provides market-specific asset tracking and is used for:
/// - Market balance validation
/// - Asset distribution checks
/// - Market limit enforcement
/// - Balance dependency resolution
///
/// Important considerations:
/// - Returns raw balance without considering fees
/// - Value is updated by balance fuses during market interactions
/// - Used in conjunction with market dependency graphs
/// - Critical for maintaining proper asset distribution across markets
///
/// Integration points:
/// - Balance Fuses: Update market balances
/// - Asset Distribution Protection: Check market limits
/// - Withdrawal System: Verify available assets
/// - Market Dependencies: Track related market updates
function getTotalAssetsInMarket(uint256 marketId_) internal view returns (uint256) {
return PlasmaVaultStorageLib.getMarketTotalAssets().value[marketId_];
}
/// @notice Gets the dependency balance graph for a specific market
/// @param marketId_ The ID of the market to query
/// @return uint256[] Array of market IDs that depend on the queried market
///
/// @dev The dependency balance graph is critical for maintaining consistent state across related markets:
/// - Ensures atomic balance updates across dependent markets
/// - Prevents inconsistent states in interconnected protocols
/// - Manages complex market relationships
///
/// Use cases:
/// - Market balance updates
/// - Withdrawal validations
/// - Asset rebalancing
/// - Protocol integrations
///
/// Example dependencies:
/// - Lending markets depending on underlying asset markets
/// - LP token markets depending on constituent token markets
/// - Derivative markets depending on base asset markets
///
/// Important considerations:
/// - Dependencies are unidirectional (A->B doesn't imply B->A)
/// - Empty array means no dependencies
/// - Order of dependencies may matter for some operations
/// - Used by _checkBalanceFusesDependencies() during balance updates
function getDependencyBalanceGraph(uint256 marketId_) internal view returns (uint256[] memory) {
return PlasmaVaultStorageLib.getDependencyBalanceGraph().dependencyGraph[marketId_];
}
/// @notice Updates the dependency balance graph for a specific market
/// @param marketId_ The ID of the market to update
/// @param newDependenceGraph_ Array of market IDs that should depend on this market
/// @dev Updates the market dependency relationships and emits an event
///
/// This function:
/// - Overwrites existing dependencies for the market
/// - Establishes new dependency relationships
/// - Triggers event for dependency tracking
///
/// Security considerations:
/// - Only callable by authorized governance functions
/// - Critical for maintaining market balance consistency
/// - Must prevent circular dependencies
/// - Should validate market existence
///
/// Common update scenarios:
/// - Adding new market dependencies
/// - Removing obsolete dependencies
/// - Modifying existing dependency chains
/// - Protocol integration changes
///
/// @dev Important: Changes to dependency graph affect:
/// - Balance update order
/// - Withdrawal validations
/// - Market rebalancing operations
/// - Protocol interaction flows
function updateDependencyBalanceGraph(uint256 marketId_, uint256[] memory newDependenceGraph_) internal {
PlasmaVaultStorageLib.getDependencyBalanceGraph().dependencyGraph[marketId_] = newDependenceGraph_;
emit DependencyBalanceGraphChanged(marketId_, newDependenceGraph_);
}
/// @notice Adds or subtracts an amount from the total assets in the Plasma Vault
/// @param amount_ The signed amount to adjust total assets by, represented in decimals of the underlying asset
/// @dev Updates the global total assets tracker based on market operations
///
/// Function behavior:
/// - Positive amount: Increases total assets
/// - Negative amount: Decreases total assets
/// - Zero amount: No effect
///
/// Used during:
/// - Market balance updates
/// - Fee realizations
/// - Asset rebalancing
/// - Withdrawal processing
///
/// Security considerations:
/// - Handles signed integers safely using SafeCast
/// - Only called during validated operations
/// - Must maintain accounting consistency
/// - Critical for share price calculations
///
/// @dev Important: This function affects:
/// - Total vault valuation
/// - Share price calculations
/// - Fee calculations
/// - Asset distribution checks
function addToTotalAssetsInAllMarkets(int256 amount_) internal {
if (amount_ < 0) {
PlasmaVaultStorageLib.getTotalAssets().value -= (-amount_).toUint256();
} else {
PlasmaVaultStorageLib.getTotalAssets().value += amount_.toUint256();
}
}
/// @notice Updates the total assets in the Plasma Vault for a specific market
/// @param marketId_ The ID of the market to update
/// @param newTotalAssetsInUnderlying_ The new total assets value for the market
/// @return deltaInUnderlying The net change in assets (positive or negative), represented in underlying decimals
/// @dev Updates market-specific asset tracking and calculates the change in total assets
///
/// Function behavior:
/// - Stores new total assets for the market
/// - Calculates delta between old and new values
/// - Returns signed delta for total asset updates
///
/// Used during:
/// - Balance fuse updates
/// - Market rebalancing
/// - Protocol interactions
/// - Asset redistribution
///
/// Security considerations:
/// - Handles asset value transitions safely
/// - Uses SafeCast for integer conversions
/// - Must be called within proper market context
/// - Critical for maintaining accurate balances
///
/// Integration points:
/// - Called by balance fuses after market operations
/// - Used in _updateMarketsBalances for batch updates
/// - Triggers market limit validations
/// - Affects total asset calculations
///
/// @dev Important: The returned delta is used by:
/// - addToTotalAssetsInAllMarkets
/// - Asset distribution protection checks
/// - Market balance event emissions
function updateTotalAssetsInMarket(
uint256 marketId_,
uint256 newTotalAssetsInUnderlying_
) internal returns (int256 deltaInUnderlying) {
uint256 oldTotalAssetsInUnderlying = PlasmaVaultStorageLib.getMarketTotalAssets().value[marketId_];
PlasmaVaultStorageLib.getMarketTotalAssets().value[marketId_] = newTotalAssetsInUnderlying_;
deltaInUnderlying = newTotalAssetsInUnderlying_.toInt256() - oldTotalAssetsInUnderlying.toInt256();
}
/// @notice Gets the management fee configuration data
/// @return managementFeeData The current management fee configuration containing:
/// - feeAccount: Address receiving management fees
/// - feeInPercentage: Current fee rate (basis points, 1/10000)
/// - lastUpdateTimestamp: Last time fees were realized
/// @dev Retrieves the current management fee settings from storage
///
/// Fee structure:
/// - Continuous time-based fee on assets under management (AUM)
/// - Fee percentage limited by MANAGEMENT_MAX_FEE_IN_PERCENTAGE (5%)
/// - Fees accrue linearly over time
/// - Realized during vault operations
///
/// Used for:
/// - Fee calculations in totalAssets()
/// - Fee realization during operations
/// - Management fee distribution
/// - Governance fee adjustments
///
/// Integration points:
/// - PlasmaVault._realizeManagementFee()
/// - PlasmaVault.totalAssets()
/// - FeeManager contract
/// - Governance configuration
///
/// @dev Important: Management fees:
/// - Are calculated based on total vault assets
/// - Affect share price calculations
/// - Must be realized before major vault operations
/// - Are distributed to configured fee recipients
function getManagementFeeData()
internal
view
returns (PlasmaVaultStorageLib.ManagementFeeData memory managementFeeData)
{
return PlasmaVaultStorageLib.getManagementFeeData();
}
/// @notice Configures the management fee settings for the vault
/// @param feeAccount_ The address that will receive management fees
/// @param feeInPercentage_ The management fee rate in basis points (100 = 1%)
/// @dev Updates fee configuration and emits event
///
/// Parameter requirements:
/// - feeAccount_: Must be non-zero address. The address of the technical Management Fee Account that will receive the management fee collected by the Plasma Vault and later on distributed to IPOR DAO and recipients by FeeManager
/// - feeInPercentage_: Must not exceed MANAGEMENT_MAX_FEE_IN_PERCENTAGE (5%)
///
/// Fee account types:
/// - FeeManager contract: Distributes fees to IPOR DAO and other recipients
/// - EOA/MultiSig: Receives fees directly without distribution
/// - Technical account: Temporary fee collection before distribution
///
/// Fee percentage format:
/// - Uses 2 decimal places (basis points)
/// - Examples:
/// - 10000 = 100%
/// - 100 = 1%
/// - 1 = 0.01%
///
/// Security considerations:
/// - Only callable by authorized governance functions
/// - Validates fee percentage against maximum limit
/// - Emits event for tracking changes
/// - Critical for vault economics
///
/// @dev Important: Changes affect:
/// - Future fee calculations
/// - Share price computations
/// - Vault revenue distribution
/// - Total asset calculations
function configureManagementFee(address feeAccount_, uint256 feeInPercentage_) internal {
if (feeAccount_ == address(0)) {
revert Errors.WrongAddress();
}
if (feeInPercentage_ > MANAGEMENT_MAX_FEE_IN_PERCENTAGE) {
revert InvalidManagementFee(feeInPercentage_);
}
PlasmaVaultStorageLib.ManagementFeeData storage managementFeeData = PlasmaVaultStorageLib
.getManagementFeeData();
managementFeeData.feeAccount = feeAccount_;
managementFeeData.feeInPercentage = feeInPercentage_.toUint16();
emit ManagementFeeDataConfigured(feeAccount_, feeInPercentage_);
}
/// @notice Gets the performance fee configuration data
/// @return performanceFeeData The current performance fee configuration containing:
/// - feeAccount: The address of the technical Performance Fee Account that will receive the performance fee collected by the Plasma Vault and later on distributed to IPOR DAO and recipients by FeeManager
/// - feeInPercentage: Current fee rate (basis points, 1/10000)
/// @dev Retrieves the current performance fee settings from storage
///
/// Fee structure:
/// - Charged on positive vault performance
/// - Fee percentage limited by PERFORMANCE_MAX_FEE_IN_PERCENTAGE (50%)
/// - Calculated on realized gains only
/// - Applied during execute() operations
///
/// Used for:
/// - Performance fee calculations
/// - Fee realization during profitable operations
/// - Performance fee distribution
/// - Governance fee adjustments
///
/// Integration points:
/// - PlasmaVault._addPerformanceFee()
/// - PlasmaVault.execute()
/// - FeeManager contract
/// - Governance configuration
///
/// @dev Important: Performance fees:
/// - Only charged on positive performance
/// - Calculated based on profit since last fee realization
/// - Minted as new vault shares
/// - Distributed to configured fee recipients
function getPerformanceFeeData()
internal
view
returns (PlasmaVaultStorageLib.PerformanceFeeData memory performanceFeeData)
{
return PlasmaVaultStorageLib.getPerformanceFeeData();
}
/// @notice Configures the performance fee settings for the vault
/// @param feeAccount_ The address that will receive performance fees
/// @param feeInPercentage_ The performance fee rate in basis points (100 = 1%)
/// @dev Updates fee configuration and emits event
///
/// Parameter requirements:
/// - feeAccount_: Must be non-zero address. The address of the technical Performance Fee Account that will receive the performance fee collected by the Plasma Vault and later on distributed to IPOR DAO and recipients by FeeManager
/// - feeInPercentage_: Must not exceed PERFORMANCE_MAX_FEE_IN_PERCENTAGE (50%)
///
/// Fee account types:
/// - FeeManager contract: Distributes fees to IPOR DAO and other recipients
/// - EOA/MultiSig: Receives fees directly without distribution
/// - Technical account: Temporary fee collection before distribution
///
/// Fee percentage format:
/// - Uses 2 decimal places (basis points)
/// - Examples:
/// - 10000 = 100%
/// - 100 = 1%
/// - 1 = 0.01%
///
/// Security considerations:
/// - Only callable by authorized governance functions
/// - Validates fee percentage against maximum limit
/// - Emits event for tracking changes
/// - Critical for vault incentive structure
///
/// @dev Important: Changes affect:
/// - Profit sharing calculations
/// - Alpha incentive alignment
/// - Vault performance metrics
/// - Revenue distribution model
function configurePerformanceFee(address feeAccount_, uint256 feeInPercentage_) internal {
if (feeAccount_ == address(0)) {
revert Errors.WrongAddress();
}
if (feeInPercentage_ > PERFORMANCE_MAX_FEE_IN_PERCENTAGE) {
revert InvalidPerformanceFee(feeInPercentage_);
}
PlasmaVaultStorageLib.PerformanceFeeData storage performanceFeeData = PlasmaVaultStorageLib
.getPerformanceFeeData();
performanceFeeData.feeAccount = feeAccount_;
performanceFeeData.feeInPercentage = feeInPercentage_.toUint16();
emit PerformanceFeeDataConfigured(feeAccount_, feeInPercentage_);
}
/// @notice Updates the management fee timestamp for fee accrual tracking
/// @dev Updates lastUpdateTimestamp to current block timestamp for fee calculations
///
/// Function behavior:
/// - Sets lastUpdateTimestamp to current block.timestamp
/// - Used to mark points of fee realization
/// - Critical for time-based fee calculations
///
/// Called during:
/// - Fee realization operations
/// - Deposit transactions
/// - Withdrawal transactions
/// - Share minting/burning
///
/// Integration points:
/// - PlasmaVault._realizeManagementFee()
/// - PlasmaVault.deposit()
/// - PlasmaVault.withdraw()
/// - PlasmaVault.mint()
///
/// @dev Important considerations:
/// - Must be called after fee realization
/// - Affects future fee calculations
/// - Uses uint32 for timestamp storage
/// - Critical for fee accounting accuracy
function updateManagementFeeData() internal {
PlasmaVaultStorageLib.ManagementFeeData storage feeData = PlasmaVaultStorageLib.getManagementFeeData();
feeData.lastUpdateTimestamp = block.timestamp.toUint32();
}
/// @notice Gets the ordered list of instant withdrawal fuses
/// @return address[] Array of fuse addresses in withdrawal priority order
/// @dev Retrieves the configured withdrawal path sequence
///
/// Function behavior:
/// - Returns ordered array of fuse addresses
/// - Empty array if no withdrawal paths configured
/// - Order determines withdrawal attempt sequence
/// - Same fuse can appear multiple times with different params
///
/// Used during:
/// - Withdrawal operations
/// - Instant withdrawal processing
/// - Withdrawal path validation
/// - Withdrawal strategy execution
///
/// Integration points:
/// - PlasmaVault._withdrawFromMarkets()
/// - Withdrawal execution logic
/// - Balance validation
/// - Fuse interaction coordination
///
/// @dev Important considerations:
/// - Order is critical for withdrawal efficiency
/// - Multiple entries of same fuse allowed
/// - Each fuse needs corresponding params
/// - Used in conjunction with getInstantWithdrawalFusesParams
function getInstantWithdrawalFuses() internal view returns (address[] memory) {
return PlasmaVaultStorageLib.getInstantWithdrawalFusesArray().value;
}
/// @notice Gets the parameters for a specific instant withdrawal fuse at a given index
/// @param fuse_ The address of the withdrawal fuse contract
/// @param index_ The position of the fuse in the withdrawal sequence
/// @return bytes32[] Array of parameters configured for this fuse instance
/// @dev Retrieves withdrawal configuration parameters for specific fuse execution
///
/// Parameter structure:
/// - params[0]: Reserved for withdrawal amount (set during execution)
/// - params[1+]: Fuse-specific parameters such as:
/// - Market identifiers
/// - Asset addresses
/// - Slippage tolerances
/// - Protocol-specific configuration
///
/// Storage pattern:
/// - Uses keccak256(abi.encodePacked(fuse_, index_)) as key
/// - Allows same fuse to have different params at different indices
/// - Supports protocol-specific parameter requirements
///
/// Used during:
/// - Withdrawal execution
/// - Parameter validation
/// - Withdrawal path configuration
/// - Fuse interaction setup
///
/// @dev Important considerations:
/// - Parameters must match fuse expectations
/// - Index must correspond to getInstantWithdrawalFuses array
/// - First parameter reserved for withdrawal amount
/// - Critical for proper withdrawal execution
function getInstantWithdrawalFusesParams(address fuse_, uint256 index_) internal view returns (bytes32[] memory) {
return
PlasmaVaultStorageLib.getInstantWithdrawalFusesParams().value[keccak256(abi.encodePacked(fuse_, index_))];
}
/// @notice Configures the instant withdrawal fuse sequence and parameters
/// @param fuses_ Array of fuse configurations with their respective parameters
/// @dev Sets up withdrawal paths and their execution parameters
///
/// Configuration process:
/// - Creates ordered list of withdrawal fuses
/// - Stores parameters for each fuse instance, in most cases are substrates used for instant withdraw
/// - Validates fuse support status
/// - Updates storage and emits event
///
/// Parameter validation:
/// - Each fuse must be supported
/// - Parameters must match fuse requirements
/// - Fuse order determines execution priority
/// - Same fuse can appear multiple times
///
/// Storage updates:
/// - Clears existing configuration
/// - Stores new fuse sequence
/// - Maps parameters to fuse+index combinations
/// - Maintains parameter ordering
///
/// Security considerations:
/// - Only callable by authorized governance
/// - Validates all fuse addresses
/// - Prevents invalid configurations
/// - Critical for withdrawal security
///
/// @dev Important: Configuration affects:
/// - Withdrawal path selection
/// - Execution sequence
/// - Protocol interactions
/// - Withdrawal efficiency
///
/// Common configurations:
/// - Multiple paths through same protocol
/// - Different slippage per path
/// - Market-specific parameters
/// - Fallback withdrawal routes
function configureInstantWithdrawalFuses(InstantWithdrawalFusesParamsStruct[] calldata fuses_) internal {
address[] memory fusesList = new address[](fuses_.length);
PlasmaVaultStorageLib.InstantWithdrawalFusesParams storage instantWithdrawalFusesParams = PlasmaVaultStorageLib
.getInstantWithdrawalFusesParams();
bytes32 key;
for (uint256 i; i < fuses_.length; ++i) {
if (!FusesLib.isFuseSupported(fuses_[i].fuse)) {
revert FusesLib.FuseUnsupported(fuses_[i].fuse);
}
fusesList[i] = fuses_[i].fuse;
key = keccak256(abi.encodePacked(fuses_[i].fuse, i));
delete instantWithdrawalFusesParams.value[key];
for (uint256 j; j < fuses_[i].params.length; ++j) {
instantWithdrawalFusesParams.value[key].push(fuses_[i].params[j]);
}
}
delete PlasmaVaultStorageLib.getInstantWithdrawalFusesArray().value;
PlasmaVaultStorageLib.getInstantWithdrawalFusesArray().value = fusesList;
emit InstantWithdrawalFusesConfigured(fuses_);
}
/// @notice Gets the Price Oracle Middleware address
/// @return address The current price oracle middleware contract address
/// @dev Retrieves the address of the price oracle middleware used for asset valuations
///
/// Price Oracle Middleware:
/// - Provides standardized price feeds for vault assets
/// - Must support USD as quote currency
/// - Critical for asset valuation and calculations
/// - Required for market operations
///
/// Used during:
/// - Asset valuation calculations
/// - Market balance updates
/// - Fee computations
/// - Share price determinations
///
/// Integration points:
/// - Balance fuses for market valuations
/// - Withdrawal calculations
/// - Performance tracking
/// - Asset distribution checks
///
/// @dev Important considerations:
/// - Must be properly initialized
/// - Critical for vault operations
/// - Required for accurate share pricing
/// - Core component for market interactions
function getPriceOracleMiddleware() internal view returns (address) {
return PlasmaVaultStorageLib.getPriceOracleMiddleware().value;
}
/// @notice Sets the Price Oracle Middleware address for the vault
/// @param priceOracleMiddleware_ The new price oracle middleware contract address
/// @dev Updates the price oracle middleware and emits event
///
/// Validation requirements:
/// - Must support USD as quote currency
/// - Must maintain same quote currency decimals
/// - Must be compatible with existing vault operations
/// - Address must be non-zero
///
/// Security considerations:
/// - Only callable by authorized governance
/// - Critical for vault operations
/// - Must validate oracle compatibility
/// - Affects all price-dependent operations
///
/// Integration impacts:
/// - Asset valuations
/// - Share price calculations
/// - Market balance updates
/// - Fee computations
///
/// @dev Important: Changes affect:
/// - All price-dependent calculations
/// - Market operations
/// - Withdrawal validations
/// - Performance tracking
///
/// Called during:
/// - Initial vault setup
/// - Oracle upgrades
/// - Protocol improvements
/// - Emergency oracle changes
function setPriceOracleMiddleware(address priceOracleMiddleware_) internal {
PlasmaVaultStorageLib.getPriceOracleMiddleware().value = priceOracleMiddleware_;
emit PriceOracleMiddlewareChanged(priceOracleMiddleware_);
}
/// @notice Gets the Rewards Claim Manager address
/// @return address The current rewards claim manager contract address
/// @dev Retrieves the address of the contract managing reward claims and distributions
///
/// Rewards Claim Manager:
/// - Handles protocol reward claims
/// - Manages reward token distributions
/// - Tracks claimable rewards
/// - Coordinates reward strategies
///
/// Used during:
/// - Reward claim operations
/// - Total asset calculations
/// - Fee computations
/// - Performance tracking
///
/// Integration points:
/// - Protocol reward systems
/// - Asset valuation calculations
/// - Performance fee assessments
/// - Governance operations
///
/// @dev Important considerations:
/// - Can be zero address (rewards disabled)
/// - Critical for reward accounting
/// - Affects total asset calculations
/// - Impacts performance metrics
function getRewardsClaimManagerAddress() internal view returns (address) {
return PlasmaVaultStorageLib.getRewardsClaimManagerAddress().value;
}
/// @notice Sets the Rewards Claim Manager address for the vault
/// @param rewardsClaimManagerAddress_ The new rewards claim manager contract address
/// @dev Updates rewards manager configuration and emits event
///
/// Configuration options:
/// - Non-zero address: Enables reward claiming functionality
/// - Zero address: Disables reward claiming system
///
/// Security considerations:
/// - Only callable by authorized governance
/// - Critical for reward system operation
/// - Affects total asset calculations
/// - Impacts performance metrics
///
/// Integration impacts:
/// - Protocol reward claiming
/// - Asset valuation calculations
/// - Performance tracking
/// - Fee computations
///
/// @dev Important: Changes affect:
/// - Reward claiming capability
/// - Total asset calculations
/// - Performance measurements
/// - Protocol integrations
///
/// Called during:
/// - Initial vault setup
/// - Rewards system upgrades
/// - Protocol improvements
/// - Emergency system changes
function setRewardsClaimManagerAddress(address rewardsClaimManagerAddress_) internal {
PlasmaVaultStorageLib.getRewardsClaimManagerAddress().value = rewardsClaimManagerAddress_;
emit RewardsClaimManagerAddressChanged(rewardsClaimManagerAddress_);
}
/// @notice Gets the total supply cap for the vault
/// @return uint256 The maximum allowed total supply in underlying asset decimals
/// @dev Retrieves the configured supply cap that limits total vault shares
///
/// Supply cap usage:
/// - Enforces maximum vault size
/// - Limits total value locked (TVL)
/// - Guards against excessive concentration
/// - Supports gradual scaling
///
/// Used during:
/// - Deposit validation
/// - Share minting checks
/// - Fee minting operations
/// - Governance monitoring
///
/// Integration points:
/// - ERC4626 deposit/mint functions
/// - Fee realization operations
/// - Governance configuration
/// - Risk management systems
///
/// @dev Important considerations:
/// - Cap applies to total shares outstanding
/// - Can be temporarily bypassed for fees
/// - Critical for risk management
/// - Affects deposit availability
function getTotalSupplyCap() internal view returns (uint256) {
return PlasmaVaultStorageLib.getERC20CappedStorage().cap;
}
/// @notice Sets the total supply cap for the vault
/// @param cap_ The new maximum total supply in underlying asset decimals
/// @dev Updates the vault's total supply limit and validates input
///
/// Validation requirements:
/// - Must be non-zero value
/// - Must be sufficient for expected vault operations
/// - Should consider asset decimals
/// - Must accommodate fee minting
///
/// Security considerations:
/// - Only callable by authorized governance
/// - Critical for vault size control
/// - Affects deposit availability
/// - Impacts risk management
///
/// Integration impacts:
/// - Deposit operations
/// - Share minting limits
/// - Fee realization
/// - TVL management
///
/// @dev Important: Changes affect:
/// - Maximum vault capacity
/// - Deposit availability
/// - Fee minting headroom
/// - Risk parameters
///
/// Called during:
/// - Initial vault setup
/// - Capacity adjustments
/// - Growth management
/// - Risk parameter updates
function setTotalSupplyCap(uint256 cap_) int
Submitted on: 2025-10-30 17:32:37
Comments
Log in to comment.
No comments yet.