State Management & Operations
Last updated
Last updated
// Deposit States
mapping(address => ERC7540_Request) private _pendingDepositRequest;
mapping(address => ERC7540_FilledRequest) private _claimableDepositRequest;
// Withdrawal States
mapping(address => ERC7540_Request) private _pendingRedeemRequest;
mapping(address => ERC7540_FilledRequest) private _claimableRedeemRequest;
// Locks & Tracking
mapping(address => bool) public redeemLocked;
mapping(address => uint256) internal _depositLockCheckPoint;
// 1. Request Creation
function requestDeposit(
uint256 assets,
address controller,
address owner
) public returns (uint256 requestId) {
// Validate conditions
require(!emergencyShutdown, "Shutdown");
require(assets > 0, "Zero amount");
// Transfer assets
asset().safeTransferFrom(owner, address(this), assets);
// Create request (immediately fulfilled)
_fulfillDepositRequest(controller, assets, convertToShares(assets));
}
// 2. Deposit Execution
function deposit(
uint256 assets,
address to,
address controller
) public returns (uint256 shares) {
// Validate claimable amount
require(assets <= maxDeposit(controller), "Exceeds max");
// Process deposit
shares = _processDeposit(assets, to, controller);
// Update accounting
_afterDeposit(assets, shares);
}
Prevents front-running
Ensures consistent state
Reduces gas costs
Simplifies error handling
function requestRedeem(
uint256 shares,
address controller,
address owner
) public returns (uint256 requestId) {
// Validate lock status
_checkSharesLocked(controller);
// Create pending request
_pendingRedeemRequest[controller] =
_pendingRedeemRequest[controller].add(shares);
// Lock redemption
redeemLocked[controller] = true;
// Transfer shares to vault
_transfer(owner, address(this), shares);
}
function processRedeemRequest(
address controller,
/*withdraw configs*/
) external {
// Load cache
ProcessRedeemRequestCache memory cache;
cache.assets = convertToAssets(shares);
// Check idle assets
if (_totalIdle >= cache.assets) {
// Direct fulfillment
cache.totalClaimableWithdraw = cache.assets;
} else {
// Calculate withdrawal route
cache.amountToWithdraw = cache.assets - _totalIdle;
_prepareWithdrawalRoute(cache);
// Process withdrawals
_processWithdrawals(cache);
}
// Update states
_updateRedeemStates(controller, cache);
}
function settleLiquidation(
address controller,
uint256[] calldata superformIds
) external {
// Receive assets
uint256 settledAssets = _receiveAssets();
// Move to claimable state
_moveToClaimable(controller, settledAssets);
// Update accounting
_updateVaultAccounting(settledAssets);
}
function redeem(
uint256 shares,
address receiver,
address controller
) public returns (uint256 assets) {
// Verify processing complete
require(!redeemLocked[controller], "Not processed");
// Check claimable amount
require(shares <= maxRedeem(controller), "Exceeds max");
// Process redemption
assets = _processRedemption(shares, receiver, controller);
// Clear state
_clearRedeemRequest(controller);
}
struct InvestmentState {
uint128 totalIdle; // Unallocated assets
uint128 totalDebt; // Allocated assets
mapping(uint256 => VaultData) vaultData;
}
// Gateway State Tracking
mapping(uint256 => uint256) public pendingXChainInvests;
uint256 public totalpendingXChainInvests;
// Investment Processing
function investSingleXChainSingleVault(
SingleXChainSingleVaultStateReq memory req
) external payable {
// Pre-investment state
uint256 preInvestIdle = _totalIdle;
// Track pending investment
pendingXChainInvests[req.superformData.superformId] += amount;
totalpendingXChainInvests += amount;
// Update vault state
_totalIdle -= amount;
// Initiate cross-chain transfer
gateway.investSingleXChainSingleVault{value: msg.value}(req);
}
function settleXChainInvest(
uint256 superformId,
uint256 bridgedAssets
) public {
// Verify caller
require(msg.sender == address(gateway), "Only Gateway");
// Update accounting
_totalDebt += bridgedAssets;
vaults[superformId].totalDebt += bridgedAssets;
// Clear pending state
pendingXChainInvests[superformId] = 0;
totalpendingXChainInvests -= bridgedAssets;
emit SettleXChainInvest(superformId, bridgedAssets);
}
// NFT (Superform Position) Handling
interface ISuperPositions {
function balanceOf(address, uint256) external view returns (uint256);
function safeTransferFrom(address, address, uint256, uint256, bytes calldata) external;
}
// Position Tracking
function _sharesBalance(VaultData memory data) internal view returns (uint256) {
if (data.chainId == THIS_CHAIN_ID) {
return ERC4626(data.vaultAddress).balanceOf(address(this));
} else {
return gateway.balanceOf(address(this), data.superformId);
}
}
error InsufficientAssets();
error InsufficientGas();
error VaultNotListed();
error RequestNotSettled();
error SharesLocked();
error VaultShutdown();
// Emergency Controls
function setEmergencyShutdown(bool _emergencyShutdown) external {
require(hasRole(EMERGENCY_ADMIN_ROLE, msg.sender), "Not admin");
emergencyShutdown = _emergencyShutdown;
emit EmergencyShutdown(_emergencyShutdown);
}
// Asset Recovery
function recoverAssets(
address token,
address recipient,
uint256 amount
) external {
require(hasRole(ADMIN_ROLE, msg.sender), "Not admin");
require(recipient == recoveryAddress, "Invalid recipient");
if (token == address(0)) {
payable(recipient).transfer(amount);
} else {
IERC20(token).safeTransfer(recipient, amount);
}
}
// Gateway Recovery
function handleFailedMessage(
uint256 superformId,
bytes memory failureData
) external {
require(msg.sender == address(gateway), "Only Gateway");
// Reverse pending states
uint256 failedAmount = pendingXChainInvests[superformId];
pendingXChainInvests[superformId] = 0;
totalpendingXChainInvests -= failedAmount;
// Return assets to idle
_totalIdle += failedAmount;
emit CrossChainFailure(superformId, failedAmount);
}
Atomic state updates
Lock mechanisms
Balance reconciliation
Message verification
Timeout handling
Slippage protection
Role-based permissions
Time locks
Emergency procedures