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/fuses/aave_v3/AaveV3CollateralFuse.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
import {Errors} from "../../libraries/errors/Errors.sol";
import {IFuseCommon} from "../IFuseCommon.sol";
import {IPool} from "./ext/IPool.sol";
import {IPoolAddressesProvider} from "./ext/IPoolAddressesProvider.sol";
import {PlasmaVaultConfigLib} from "../../libraries/PlasmaVaultConfigLib.sol";
/// @title AaveV3CollateralFuse
/// @dev Fuse for Aave V3 responsible for managing isolated collateral in Aave V3
contract AaveV3CollateralFuse is IFuseCommon {
address public immutable VERSION;
uint256 public immutable MARKET_ID;
address public immutable AAVE_V3_POOL_ADDRESSES_PROVIDER;
error AaveV3CollateralFuseUnsupportedAsset(string action, address asset);
event AaveV3EnableCollateralFuse(address version, address asset);
event AaveV3DisableCollateralFuse(address version, address asset);
constructor(uint256 marketId_, address aaveV3PoolAddressesProvider_) {
VERSION = address(this);
MARKET_ID = marketId_;
if (aaveV3PoolAddressesProvider_ == address(0)) {
revert Errors.WrongAddress();
}
AAVE_V3_POOL_ADDRESSES_PROVIDER = aaveV3PoolAddressesProvider_;
}
/// @notice Enters the Aave V3 Collateral Fuse with the specified asset address, enabling isolated collateral
/// @param assetAddress collateral asset address
function enter(address assetAddress) external {
if (!PlasmaVaultConfigLib.isSubstrateAsAssetGranted(MARKET_ID, assetAddress)) {
revert AaveV3CollateralFuseUnsupportedAsset("enter", assetAddress);
}
IPool pool = IPool(IPoolAddressesProvider(AAVE_V3_POOL_ADDRESSES_PROVIDER).getPool());
pool.setUserUseReserveAsCollateral(assetAddress, true);
emit AaveV3EnableCollateralFuse(VERSION, assetAddress);
}
/// @notice Exits the Aave V3 Collateral Fuse with the specified asset address, disabling isolated collateral
/// @param assetAddress collateral asset address
function exit(address assetAddress) external {
if (!PlasmaVaultConfigLib.isSubstrateAsAssetGranted(MARKET_ID, assetAddress)) {
revert AaveV3CollateralFuseUnsupportedAsset("enter", assetAddress);
}
IPool pool = IPool(IPoolAddressesProvider(AAVE_V3_POOL_ADDRESSES_PROVIDER).getPool());
pool.setUserUseReserveAsCollateral(assetAddress, false);
emit AaveV3DisableCollateralFuse(VERSION, assetAddress);
}
}
"
},
"contracts/libraries/errors/Errors.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
/// @title Errors in Ipor Fusion
library Errors {
/// @notice Error when wrong address is used
error WrongAddress();
/// @notice Error when wrong value is used
error WrongValue();
/// @notice Error when wrong decimals are used
error WrongDecimals();
/// @notice Error when wrong array length is used
error WrongArrayLength();
/// @notice Error when wrong caller is used
error WrongCaller(address caller);
/// @notice Error when wrong quote currency is used
error UnsupportedQuoteCurrencyFromOracle();
/// @notice Error when unsupported price oracle middleware is used
error UnsupportedPriceOracleMiddleware();
}
"
},
"contracts/fuses/IFuseCommon.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
/// @title Interface for Fuses Common functions
interface IFuseCommon {
/// @notice Market ID associated with the Fuse
//solhint-disable-next-line
function MARKET_ID() external view returns (uint256);
}
"
},
"contracts/fuses/aave_v3/ext/IPool.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;
interface IPool {
/**
* @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User supplies 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to supply
* @param amount The amount to be supplied
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
*/
function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
/**
* @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to The address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
*/
function withdraw(address asset, uint256 amount, address to) external returns (uint256);
/**
* @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
* already supplied enough collateral, or he was given enough allowance by a credit delegator on the
* corresponding debt token (StableDebtToken or VariableDebtToken)
* - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
* and 100 stable/variable debt tokens, depending on the `interestRateMode`
* @param asset The address of the underlying asset to borrow
* @param amount The amount to be borrowed
* @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
* @param referralCode The code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
* @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
* calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
* if he has been given credit delegation allowance
*/
function borrow(
address asset,
uint256 amount,
uint256 interestRateMode,
uint16 referralCode,
address onBehalfOf
) external;
/**
* @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
* - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
* @param asset The address of the borrowed underlying asset previously borrowed
* @param amount The amount to repay
* - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
* @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
* @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the
* user calling the function if he wants to reduce/remove his own debt, or the address of any other
* other borrower whose debt should be removed
* @return The final amount repaid
*/
function repay(
address asset,
uint256 amount,
uint256 interestRateMode,
address onBehalfOf
) external returns (uint256);
/**
* @notice Allows a user to use the protocol in eMode
* @param categoryId The id of the category
*/
function setUserEMode(uint8 categoryId) external;
/**
* @notice Returns the list of the underlying assets of all the initialized reserves
* @dev It does not include dropped reserves
* @return The addresses of the underlying assets of the initialized reserves
*/
function getReservesList() external view returns (address[] memory);
/**
* @notice Returns the user account data across all the reserves
* @param user The address of the user
* @return totalCollateralBase The total collateral of the user in the base currency used by the price feed
* @return totalDebtBase The total debt of the user in the base currency used by the price feed
* @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed
* @return currentLiquidationThreshold The liquidation threshold of the user
* @return ltv The loan to value of The user
* @return healthFactor The current health factor of the user
*/
function getUserAccountData(
address user
)
external
view
returns (
uint256 totalCollateralBase,
uint256 totalDebtBase,
uint256 availableBorrowsBase,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
/**
* @notice Allows suppliers to enable/disable a specific supplied asset as collateral
* @param asset The address of the underlying asset supplied
* @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise
*/
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;
}
"
},
"contracts/fuses/aave_v3/ext/IPoolAddressesProvider.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity 0.8.26;
interface IPoolAddressesProvider {
function getPool() external view returns (address);
function getPriceOracle() external view returns (address);
function getPoolDataProvider() external view returns (address);
}
"
},
"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/PlasmaVaultStorageLib.sol": {
"content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.26;
/**
* @title Plasma Vault Storage Library
* @notice Library managing storage layout and access for the PlasmaVault system using ERC-7201 namespaced storage pattern
* @dev This library is a core component of the PlasmaVault system that:
* 1. Defines and manages all storage structures using ERC-7201 namespaced storage pattern
* 2. Provides storage access functions for PlasmaVault.sol, PlasmaVaultBase.sol and PlasmaVaultGovernance.sol
* 3. Ensures storage safety for the upgradeable vault system
*
* Storage Components:
* - Core ERC4626 vault storage (asset, decimals)
* - Market management (assets, balances, substrates)
* - Fee system storage (performance, management fees)
* - Access control and execution state
* - Fuse system configuration
* - Price oracle and rewards management
*
* Key Integrations:
* - Used by PlasmaVault.sol for core vault operations and asset management
* - Used by PlasmaVaultGovernance.sol for configuration and admin functions
* - Used by PlasmaVaultBase.sol for ERC20 functionality and access control
*
* Security Considerations:
* - Uses ERC-7201 namespaced storage pattern to prevent storage collisions
* - Each storage struct has a unique namespace derived from its purpose
* - Critical for maintaining storage integrity in upgradeable contracts
* - Storage slots are carefully chosen and must not be modified
*
* @custom:security-contact security@ipor.io
*/
library PlasmaVaultStorageLib {
/**
* @dev Storage slot for ERC4626 vault configuration following ERC-7201 namespaced storage pattern
* @notice This storage location is used to store the core ERC4626 vault data (asset address and decimals)
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC4626")) - 1)) & ~bytes32(uint256(0xff))
*
* Important:
* - This value MUST NOT be changed as it's used by OpenZeppelin's ERC4626 implementation
* - Changing this value would break storage compatibility with existing deployments
* - Used by PlasmaVault.sol for core vault operations like deposit/withdraw
*
* Storage Layout:
* - Points to ERC4626Storage struct containing:
* - asset: address of the underlying token
* - underlyingDecimals: decimals of the underlying token
*/
bytes32 private constant ERC4626_STORAGE_LOCATION =
0x0773e532dfede91f04b12a73d3d2acd361424f41f76b4fb79f090161e36b4e00;
/**
* @dev Storage slot for ERC20Capped configuration following ERC-7201 namespaced storage pattern
* @notice This storage location manages the total supply cap functionality for the vault
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20Capped")) - 1)) & ~bytes32(uint256(0xff))
*
* Important:
* - This value MUST NOT be changed as it's used by OpenZeppelin's ERC20Capped implementation
* - Changing this value would break storage compatibility with existing deployments
* - Used by PlasmaVault.sol and PlasmaVaultBase.sol for supply cap enforcement
*
* Storage Layout:
* - Points to ERC20CappedStorage struct containing:
* - cap: maximum total supply allowed for the vault tokens
*
* Usage:
* - Enforces maximum supply limits during minting operations
* - Can be temporarily disabled for fee-related minting operations
* - Critical for maintaining vault supply control
*/
bytes32 private constant ERC20_CAPPED_STORAGE_LOCATION =
0x0f070392f17d5f958cc1ac31867dabecfc5c9758b4a419a200803226d7155d00;
/**
* @dev Storage slot for managing the ERC20 supply cap validation state
* @notice Controls whether total supply cap validation is active or temporarily disabled
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.Erc20CappedValidationFlag")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Provides a mechanism to temporarily disable supply cap checks
* - Essential for special minting operations like fee distribution
* - Used by PlasmaVault.sol during performance and management fee minting
*
* Storage Layout:
* - Points to ERC20CappedValidationFlag struct containing:
* - value: flag indicating if cap validation is enabled (0) or disabled (1)
*
* Usage Pattern:
* - Default state: Enabled (0) - enforces supply cap
* - Temporarily disabled (1) during:
* - Performance fee minting
* - Management fee minting
* - Always re-enabled after special minting operations
*
* Security Note:
* - Critical for maintaining controlled token supply
* - Only disabled briefly during authorized fee operations
* - Must be properly re-enabled to prevent unlimited minting
*/
bytes32 private constant ERC20_CAPPED_VALIDATION_FLAG =
0xaef487a7a52e82ae7bbc470b42be72a1d3c066fb83773bf99cce7e6a7df2f900;
/**
* @dev Storage slot for tracking total assets across all markets in the Plasma Vault
* @notice Maintains the global accounting of all assets managed by the vault
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.PlasmaVaultTotalAssetsInAllMarkets")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Tracks the total value of assets managed by the vault across all markets
* - Used for global vault accounting and share price calculations
* - Critical for ERC4626 compliance and vault operations
*
* Storage Layout:
* - Points to TotalAssets struct containing:
* - value: total assets in underlying token decimals
*
* Usage:
* - Updated during deposit/withdraw operations
* - Used in share price calculations
* - Referenced for fee calculations
* - Key component in asset distribution checks
*
* Integration Points:
* - PlasmaVault.sol: Used in totalAssets() calculations
* - Fee System: Used as base for fee calculations
* - Asset Protection: Used in distribution limit checks
*
* Security Considerations:
* - Must be accurately maintained for proper vault operation
* - Critical for share price accuracy
* - Any updates must consider all asset sources (markets, rewards, etc.)
*/
bytes32 private constant PLASMA_VAULT_TOTAL_ASSETS_IN_ALL_MARKETS =
0x24e02552e88772b8e8fd15f3e6699ba530635ffc6b52322da922b0b497a77300;
/**
* @dev Storage slot for tracking assets per individual market in the Plasma Vault
* @notice Maintains per-market asset accounting for the vault's distributed positions
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.PlasmaVaultTotalAssetsInMarket")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Tracks assets allocated to each market individually
* - Enables market-specific asset distribution control
* - Used for market balance validation and limits enforcement
*
* Storage Layout:
* - Points to MarketTotalAssets struct containing:
* - value: mapping(uint256 marketId => uint256 assets)
* - Assets stored in underlying token decimals
*
* Usage:
* - Updated during market operations via fuses
* - Used in market balance checks
* - Referenced for market limit validations
* - Key for asset distribution protection
*
* Integration Points:
* - Balance Fuses: Update market balances
* - Asset Distribution Protection: Enforce market limits
* - Withdrawal Logic: Check available assets per market
*
* Security Considerations:
* - Critical for market-specific asset limits
* - Must be synchronized with actual market positions
* - Updates protected by balance fuse system
*/
bytes32 private constant PLASMA_VAULT_TOTAL_ASSETS_IN_MARKET =
0x656f5ca8c676f20b936e991a840e1130bdd664385322f33b6642ec86729ee600;
/**
* @dev Storage slot for market substrates configuration in the Plasma Vault
* @notice Manages the configuration of supported assets and sub-markets for each market
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.CfgPlasmaVaultMarketSubstrates")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Defines which assets/sub-markets are supported in each market
* - Controls market-specific asset allowances
* - Essential for market integration configuration
*
* Storage Layout:
* - Points to MarketSubstrates struct containing:
* - value: mapping(uint256 marketId => MarketSubstratesStruct)
* where MarketSubstratesStruct contains:
* - substrateAllowances: mapping(bytes32 => uint256) for permission control
* - substrates: bytes32[] list of supported substrates
*
* Usage:
* - Configured by governance for each market
* - Referenced during market operations
* - Used by fuses to validate operations
* - Controls which assets can be used in each market
*
* Integration Points:
* - Fuse System: Validates allowed substrates
* - Market Operations: Controls available assets
* - Governance: Manages market configurations
*
* Security Considerations:
* - Critical for controlling market access
* - Only modifiable through governance
* - Impacts market operation permissions
*/
bytes32 private constant CFG_PLASMA_VAULT_MARKET_SUBSTRATES =
0x78e40624004925a4ef6749756748b1deddc674477302d5b7fe18e5335cde3900;
/**
* @dev Storage slot for pre-hooks configuration in the Plasma Vault
* @notice Manages function-specific pre-execution hooks and their implementations
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.CfgPlasmaVaultPreHooks")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Maps function selectors to their pre-execution hook implementations
* - Enables customizable pre-execution validation and logic
* - Provides extensible function-specific behavior
* - Coordinates cross-function state updates
*
* Storage Layout:
* - Points to PreHooksConfig struct containing:
* - hooksImplementation: mapping(bytes4 selector => address implementation)
* - selectors: bytes4[] array of registered function selectors
* - indexes: mapping(bytes4 selector => uint256 index) for O(1) selector lookup
*
* Usage Pattern:
* - Each function can have one designated pre-hook
* - Hooks execute before main function logic
* - Selector array enables efficient iteration over registered hooks
* - Index mapping provides quick hook existence checks
*
* Integration Points:
* - PlasmaVault.execute: Pre-execution hook invocation
* - PreHooksHandler: Hook execution coordination
* - PlasmaVaultGovernance: Hook configuration
* - Function-specific hooks: Custom validation logic
*
* Security Considerations:
* - Only modifiable through governance
* - Critical for function execution control
* - Must validate hook implementations
* - Requires careful state management
* - Key component of vault security layer
*/
bytes32 private constant CFG_PLASMA_VAULT_PRE_HOOKS =
0xd334d8b26e68f82b7df26f2f64b6ffd2aaae5e2fc0e8c144c4b3598dcddd4b00;
/**
* @dev Storage slot for balance fuses configuration in the Plasma Vault
* @notice Maps markets to their balance fuses and maintains an ordered list of active markets
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.CfgPlasmaVaultBalanceFuses")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Associates balance fuses with specific markets for asset tracking
* - Maintains ordered list of active markets for efficient iteration
* - Enables market balance validation and updates
* - Coordinates multi-market balance operations
*
* Storage Layout:
* - Points to BalanceFuses struct containing:
* - fuseAddresses: mapping(uint256 marketId => address fuseAddress)
* - marketIds: uint256[] array of active market IDs
* - indexes: Maps market IDs to their position+1 in marketIds array
*
* Usage Pattern:
* - Each market has one designated balance fuse
* - Market IDs array enables efficient iteration over active markets
* - Index mapping provides quick market existence checks
* - Used during balance updates and market operations
*
* Integration Points:
* - PlasmaVault._updateMarketsBalances: Market balance tracking
* - Balance Fuses: Market position management
* - PlasmaVaultGovernance: Fuse configuration
* - Asset Protection: Balance validation
*
* Security Considerations:
* - Only modifiable through governance
* - Critical for accurate asset tracking
* - Must maintain market list integrity
* - Requires proper fuse address validation
* - Key component of vault accounting
*/
bytes32 private constant CFG_PLASMA_VAULT_BALANCE_FUSES =
0x150144dd6af711bac4392499881ec6649090601bd196a5ece5174c1400b1f700;
/**
* @dev Storage slot for instant withdrawal fuses configuration
* @notice Stores ordered array of fuses that can be used for instant withdrawals
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.CfgPlasmaVaultInstantWithdrawalFusesArray")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Maintains list of fuses available for instant withdrawals
* - Defines order of withdrawal attempts
* - Enables efficient withdrawal path selection
*
* Storage Layout:
* - Points to InstantWithdrawalFuses struct containing:
* - value: address[] array of fuse addresses
* - Order of fuses in array determines withdrawal priority
*
* Usage:
* - Referenced during withdrawal operations
* - Used by PlasmaVault.sol in _withdrawFromMarkets
* - Determines withdrawal execution sequence
*
* Integration Points:
* - Withdrawal System: Defines available withdrawal paths
* - Fuse System: Lists supported instant withdrawal fuses
* - Governance: Manages withdrawal configuration
*
* Security Considerations:
* - Order of fuses is critical for optimal withdrawals
* - Same fuse can appear multiple times with different params
* - Must be carefully managed to ensure withdrawal efficiency
*/
bytes32 private constant CFG_PLASMA_VAULT_INSTANT_WITHDRAWAL_FUSES_ARRAY =
0xd243afa3da07e6bdec20fdd573a17f99411aa8a62ae64ca2c426d3a86ae0ac00;
/**
* @dev Storage slot for price oracle middleware configuration
* @notice Stores the address of the price oracle middleware used for asset price conversions
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.PriceOracleMiddleware")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Provides price feed access for asset valuations
* - Essential for market value calculations
* - Used in balance conversions and limit checks
*
* Storage Layout:
* - Points to PriceOracleMiddleware struct containing:
* - value: address of the price oracle middleware contract
*
* Usage:
* - Used during market balance updates
* - Required for USD value calculations
* - Critical for asset distribution checks
*
* Integration Points:
* - Balance Fuses: Asset value calculations
* - Market Operations: Price conversions
* - Asset Protection: Value-based limits
*
* Security Considerations:
* - Must point to a valid and secure price oracle
* - Critical for accurate vault valuations
* - Only updatable through governance
*/
bytes32 private constant PRICE_ORACLE_MIDDLEWARE =
0x0d761ae54d86fc3be4f1f2b44ade677efb1c84a85fc6bb1d087dc42f1e319a00;
/**
* @dev Storage slot for instant withdrawal fuse parameters configuration
* @notice Maps fuses to their specific withdrawal parameters for instant withdrawal execution
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.CfgPlasmaVaultInstantWithdrawalFusesParams")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Stores configuration parameters for each instant withdrawal fuse
* - Enables customized withdrawal behavior per fuse
* - Supports multiple parameter sets for the same fuse at different indices
*
* Storage Layout:
* - Points to InstantWithdrawalFusesParams struct containing:
* - value: mapping(bytes32 => bytes32[]) where:
* - key: keccak256(abi.encodePacked(fuse address, index))
* - value: array of parameters specific to the fuse
*
* Parameter Structure:
* - params[0]: Always represents withdrawal amount in underlying token
* - params[1+]: Fuse-specific parameters (e.g., slippage, path, market-specific data)
*
* Usage Pattern:
* - Referenced during instant withdrawal operations in PlasmaVault
* - Parameters are passed to fuse's instantWithdraw function
* - Supports multiple parameter sets for same fuse with different indices
*
* Integration Points:
* - PlasmaVault._withdrawFromMarkets: Uses params for withdrawal execution
* - PlasmaVaultGovernance: Manages parameter configuration
* - Fuse Contracts: Receive and interpret parameters during withdrawal
*
* Security Considerations:
* - Only modifiable through governance
* - Critical for controlling withdrawal behavior
* - Parameters must be carefully validated per fuse requirements
* - Order of parameters must match fuse expectations
*/
bytes32 private constant CFG_PLASMA_VAULT_INSTANT_WITHDRAWAL_FUSES_PARAMS =
0x45a704819a9dcb1bb5b8cff129eda642cf0e926a9ef104e27aa53f1d1fa47b00;
/**
* @dev Storage slot for fee configuration in the Plasma Vault
* @notice Manages the fee configuration including performance and management fees
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.CfgPlasmaVaultFeeConfig")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Stores comprehensive fee configuration for the vault
* - Manages both IPOR DAO and recipient-specific fee settings
* - Enables flexible fee distribution model
*
* Storage Layout:
* - Points to FeeConfig struct containing:
* - feeFactory: address of the FeeManagerFactory contract
* - iporDaoManagementFee: management fee percentage for IPOR DAO
* - iporDaoPerformanceFee: performance fee percentage for IPOR DAO
* - iporDaoFeeRecipientAddress: address receiving IPOR DAO fees
* - recipientManagementFees: array of management fee percentages for other recipients
* - recipientPerformanceFees: array of performance fee percentages for other recipients
*
* Fee Structure:
* - Management fees: Continuous time-based fees on AUM
* - Performance fees: Charged on positive vault performance
* - All fees in basis points (1/10000)
*
* Integration Points:
* - FeeManagerFactory: Deploys fee management contracts
* - FeeManager: Handles fee calculations and distributions
* - PlasmaVault: References for fee realizations
*
* Security Considerations:
* - Only modifiable through governance
* - Fee percentages must be within reasonable bounds
* - Critical for vault economics and sustainability
* - Must maintain proper recipient configurations
*/
bytes32 private constant CFG_PLASMA_VAULT_FEE_CONFIG =
0x78b5ce597bdb64d5aa30a201c7580beefe408ff13963b5d5f3dce2dc09e89c00;
/**
* @dev Storage slot for performance fee data in the Plasma Vault
* @notice Stores current performance fee configuration and recipient information
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.PlasmaVaultPerformanceFeeData")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Manages performance fee settings and collection
* - Tracks fee recipient address
* - Controls performance-based revenue sharing
*
* Storage Layout:
* - Points to PerformanceFeeData struct containing:
* - feeAccount: address receiving performance fees
* - feeInPercentage: current fee rate (basis points, 1/10000)
*
* Fee Mechanics:
* - Calculated on positive vault performance
* - Applied during execute() operations
* - Minted as new vault shares to fee recipient
* - Charged only on realized gains
*
* Integration Points:
* - PlasmaVault._addPerformanceFee: Fee calculation and minting
* - FeeManager: Fee configuration management
* - PlasmaVaultGovernance: Fee settings updates
*
* Security Considerations:
* - Only modifiable through governance
* - Fee percentage must be within defined limits
* - Critical for fair value distribution
* - Must maintain valid fee recipient address
* - Requires careful handling during share minting
*/
bytes32 private constant PLASMA_VAULT_PERFORMANCE_FEE_DATA =
0x9399757a27831a6cfb6cf4cd5c97a908a2f8f41e95a5952fbf83a04e05288400;
/**
* @notice Stores management fee configuration and time tracking data
* @dev Manages continuous fee collection with time-based accrual
* @custom:storage-location erc7201:io.ipor.PlasmaVaultManagementFeeData
*/
bytes32 private constant PLASMA_VAULT_MANAGEMENT_FEE_DATA =
0x239dd7e43331d2af55e2a25a6908f3bcec2957025f1459db97dcdc37c0003f00;
/**
* @dev Storage slot for rewards claim manager address
* @notice Stores the address of the contract managing external protocol rewards
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.RewardsClaimManagerAddress")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Manages external protocol reward claims
* - Tracks claimable rewards across integrated protocols
* - Centralizes reward collection logic
*
* Storage Layout:
* - Points to RewardsClaimManagerAddress struct containing:
* - value: address of the rewards claim manager contract
*
* Functionality:
* - Coordinates reward claims from multiple protocols
* - Tracks unclaimed rewards in underlying asset terms
* - Included in total assets calculations when active
* - Optional component (can be set to address(0))
*
* Integration Points:
* - PlasmaVault._getGrossTotalAssets: Includes rewards in total assets
* - PlasmaVault.claimRewards: Executes reward collection
* - External protocols: Source of claimable rewards
*
* Security Considerations:
* - Only modifiable through governance
* - Must handle protocol-specific claim logic safely
* - Critical for accurate reward accounting
* - Requires careful integration testing
* - Should handle failed claims gracefully
*/
bytes32 private constant REWARDS_CLAIM_MANAGER_ADDRESS =
0x08c469289c3f85d9b575f3ae9be6831541ff770a06ea135aa343a4de7c962d00;
/**
* @dev Storage slot for market allocation limits
* @notice Controls maximum asset allocation per market in the vault
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.MarketLimits")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Enforces market-specific allocation limits
* - Prevents over-concentration in single markets
* - Enables risk management through diversification
*
* Storage Layout:
* - Points to MarketLimits struct containing:
* - limitInPercentage: mapping(uint256 marketId => uint256 limit)
* - Limits stored in basis points (1e18 = 100%)
*
* Limit Mechanics:
* - Each market has independent allocation limit
* - Limits are percentage of total vault assets
* - Zero limit for marketId 0 deactivates all limits
* - Non-zero limit for marketId 0 activates limit system
*
* Integration Points:
* - AssetDistributionProtectionLib: Enforces limits
* - PlasmaVault._updateMarketsBalances: Checks limits
* - PlasmaVaultGovernance: Limit configuration
*
* Security Considerations:
* - Only modifiable through governance
* - Critical for risk management
* - Must handle percentage calculations carefully
* - Requires proper market balance tracking
* - Should prevent concentration risk
*/
bytes32 private constant MARKET_LIMITS = 0xc2733c187287f795e2e6e84d35552a190e774125367241c3e99e955f4babf000;
/**
* @dev Storage slot for market balance dependency relationships
* @notice Manages interconnected market balance update requirements
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.DependencyBalanceGraph")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Tracks dependencies between market balances
* - Ensures atomic balance updates across related markets
* - Maintains consistency in cross-market positions
*
* Storage Layout:
* - Points to DependencyBalanceGraph struct containing:
* - dependencyGraph: mapping(uint256 marketId => uint256[] marketIds)
* - Each market maps to array of dependent market IDs
*
* Dependency Mechanics:
* - Markets can depend on multiple other markets
* - When updating a market balance, all dependent markets must be updated
* - Dependencies are unidirectional (A->B doesn't imply B->A)
* - Empty dependency array means no dependencies
*
* Integration Points:
* - PlasmaVault._checkBalanceFusesDependencies: Resolves update order
* - PlasmaVault._updateMarketsBalances: Ensures complete updates
* - PlasmaVaultGovernance: Dependency configuration
*
* Security Considerations:
* - Only modifiable through governance
* - Must prevent circular dependencies
* - Critical for market balance integrity
* - Requires careful dependency chain validation
* - Should handle deep dependency trees efficiently
*/
bytes32 private constant DEPENDENCY_BALANCE_GRAPH =
0x82411e549329f2815579116a6c5e60bff72686c93ab5dba4d06242cfaf968900;
/**
* @dev Storage slot for tracking execution state of vault operations
* @notice Controls execution flow and prevents concurrent operations in the vault
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.executeRunning")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Prevents concurrent execution of vault operations
* - Enables callback handling during execution
* - Acts as a reentrancy guard for execute() operations
*
* Storage Layout:
* - Points to ExecuteState struct containing:
* - value: uint256 flag indicating execution state
* - 0: No execution in progress
* - 1: Execution in progress
*
* Usage Pattern:
* - Set to 1 at start of execute() operation
* - Checked during callback handling
* - Reset to 0 when execution completes
* - Used by PlasmaVault.execute() and callback system
*
* Integration Points:
* - PlasmaVault.execute: Sets/resets execution state
* - CallbackHandlerLib: Validates callbacks during execution
* - Fallback function: Routes callbacks during execution
*
* Security Considerations:
* - Critical for preventing concurrent operations
* - Must be properly reset after execution
* - Protects against malicious callbacks
* - Part of vault's security architecture
*/
bytes32 private constant EXECUTE_RUNNING = 0x054644eb87255c1c6a2d10801735f52fa3b9d6e4477dbed74914d03844ab6600;
/**
* @dev Storage slot for callback handler mapping in the Plasma Vault
* @notice Maps protocol-specific callbacks to their handler contracts
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.callbackHandler")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Routes protocol-specific callbacks to appropriate handlers
* - Enables dynamic callback handling during vault operations
* - Supports integration with external protocols
* - Manages protocol-specific callback logic
*
* Storage Layout:
* - Points to CallbackHandler struct containing:
* - callbackHandler: mapping(bytes32 => address)
* - key: keccak256(abi.encodePacked(sender, sig))
* - value: address of the handler contract
*
* Usage Pattern:
* - Callbacks received during execute() operations
* - Key generated from sender address and function signature
* - Handler contract processes protocol-specific logic
* - Only accessible when execution is in progress
*
* Integration Points:
* - PlasmaVault.fallback: Routes incoming callbacks
* - CallbackHandlerLib: Processes callback routing
* - Protocol-specific handlers: Implement callback logic
* - PlasmaVaultGovernance: Manages handler configuration
*
* Security Considerations:
* - Only callable during active execution
* - Handler addresses must be trusted
* - Prevents unauthorized callback processing
* - Critical for secure protocol integration
* - Must validate callback sources
*/
bytes32 private constant CALLBACK_HANDLER = 0xb37e8684757599da669b8aea811ee2b3693b2582d2c730fab3f4965fa2ec3e00;
/**
* @dev Storage slot for withdraw manager contract address
* @notice Manages withdrawal controls and permissions in the Plasma Vault
*
* Calculation:
* keccak256(abi.encode(uint256(keccak256("io.ipor.WithdrawManager")) - 1)) & ~bytes32(uint256(0xff))
*
* Purpose:
* - Controls withdrawal permissions and limits
* - Manages withdrawal schedules and timing
* - Enforces withdrawal restrictions
* - Coordinates withdrawal validation
*
* Storage Layout:
* - Points to WithdrawManager struct containing:
* - manager: address of the withdraw manager contract
* - Zero address indicates disabled withdrawal controls
*
* Usage Pattern:
* - Checked during withdraw() and redeem() operations
* - Validates withdrawal permissions
* - Enforces withdrawal schedules
* - Can be disabled by setting to address(0)
*
* Integration Points:
* - PlasmaVault.withdraw: Checks withdrawal permissions
* - PlasmaVault.redeem: Validates redemption requests
* - PlasmaVaultGovernance: Manager configuration
* - AccessManager: Permission coordination
*
* Security Considerations:
* - Critical for controlling asset outflows
* - Only modifiable through governance
* - Must maintain withdrawal restrictions
* - Coordinates with access control system
* - Key component of vault security
*/
bytes32 private constant WITHDRAW_MANAGER = 0xb37e8684757599da669b8aea811ee2b3693b2582d2c730fab3f4965fa2ec3e11;
/**
* @dev Storage slot for plasma vault base address. Computed as:
* keccak256(abi.encode(uint256(keccak256("io.ipor.fusion.PlasmaVaultBase")) - 1)) & ~bytes32(uint256(0xff))
*/
bytes32 private constant PLASMA_VAULT_BASE_SLOT =
0x708fd1151214a098976e0893cd3883792c21aeb94a31cd7733c8947c13c23000;
/**
* @dev Storage slot for share scale multiplier. Computed as:
* keccak256(abi.encode(uint256(keccak256("io.ipor.fusion.param.ShareScaleMultiplier")) - 1)) & ~bytes32(uint256(0xff))
*/
bytes32 private constant SHARE_SCALE_MULTIPLIER_SLOT =
0x5bb34fc23414cfe7e422518e1d8590877bcc5dcacad5f8689bfd98e9a05ac600;
/**
* @notice Maps callback signatures to their handler contracts
* @dev Stores routing information for protocol-specific callbacks
* @custom:storage-location erc7201:io.ipor.callbackHandler
*/
struct CallbackHandler {
/// @dev key: keccak256(abi.encodePacked(sender, sig)), value: handler address
mapping(bytes32 key => address handler) callbackHandler;
}
/**
* @notice Stores and manages per-market allocation limits for the vault
* @custom:storage-location erc7201:io.ipor.MarketLimits
*/
struct MarketLimits {
mapping(uint256 marketId => uint256 limit) limitInPercentage;
}
/**
* @notice Core storage for ERC4626 vault implementation
* @dev Value taken from OpenZeppelin's ERC4626 implementation - DO NOT MODIFY
* @custom:storage-location erc7201:openzeppelin.storage.ERC4626
*/
struct ERC4626Storage {
/// @dev underlying asset in Plasma Vault
address asset;
/// @dev underlying asset decimals in Plasma Vault
uint8 underlyingDecimals;
}
/// @dev Value taken from ERC20VotesUpgradeable contract, don't change it!
/// @custom:storage-location erc7201:openzeppelin.storage.ERC20Capped
struct ERC20CappedStorage {
uint256 cap;
}
/// @notice ERC20CappedValidationFlag is used to enable or disable the total supply cap validation during execution
/// Required for situation when performance fee or management fee is minted for fee managers
/// @custom:storage-location erc7201:io.ipor.Erc20CappedValidationFlag
struct ERC20CappedValidationFlag {
uint256 value;
}
/**
* @notice Stores address of the contract managing protocol reward claims
* @dev Optional component - can be set to address(0) to disable rewards
* @custom:storage-location erc7201:io.ipor.RewardsClaimManagerAddress
*/
struct RewardsClaimManagerAddress {
/// @dev total assets in the Plasma Vault
address value;
}
/**
* @notice Tracks total assets across all markets in the vault
* @dev Used for global accounting and share price calculations
* @custom:storage-location erc7201:io.ipor.PlasmaVaultTotalAssetsInAllMarkets
*/
struct TotalAssets {
/// @dev total assets in the Plasma Vault
uint256 value;
}
/**
* @notice Tracks per-market asset balances in the vault
* @dev Used for market-specific accounting and limit enforcement
* @custom:storage-location erc7201:io.ipor.PlasmaVaultTotalAssetsInMarket
*/
struct MarketTotalAssets {
/// @dev marketId => total assets in the vault in the market
mapping(uint256 => uint256) value;
}
/**
* @notice Market Substrates configuration
* @dev Substrate - abstract item in the market, could be asset or sub market in the external protocol, it could be any item required to calculate balance in the market
* @custom:storage-location erc7201:io.ipor.CfgPlasmaVaultMarketSubstrates
*/
struct MarketSubstratesStruct {
/// @notice Define which substrates are allowed and supported in the market
/// @dev key can be specific asset or sub market in a specific external protocol (market), value - 1 - granted, otherwise - not granted
mapping(bytes32 => uint256) substrateAllowances;
/// @dev it could be list of assets or sub markets in a specific protocol or any other ids required to calculate balance in the market (external protocol)
bytes32[] substrates;
}
/**
* @notice Maps markets to their supported substrate configurations
* @dev Stores per-market substrate allowances and lists
* @custom:storage-location erc7201:io.ipor.CfgPlasmaVaultMarketSubstrates
*/
struct MarketSubstrates {
/// @dev marketId => MarketSubstratesStruct
mapping(uint256 => MarketSubstratesStruct) value;
}
/**
* @notice Manages market-to-fuse mappings and active market tracking
* @dev Provides efficient market lookup and iteration capabilities
* @custom:storage-location erc7201:io.ipor.CfgPlasmaVaultBalanceFuses
*
* Storage Components:
* - fuseAddresses: Maps each market to its designated balance fuse
* - marketIds: Maintains ordered list of active markets for iteration
* - indexes: Maps market IDs to their position+1 in marketIds array
*
* Key Features:
* - Efficient market-fuse relationship management
* - Fast mark
Submitted on: 2025-10-30 17:39:44
Comments
Log in to comment.
No comments yet.