WithdrawController
Inherits: IWithdrawController, AccessControl, ReentrancyGuard, Constants
Author: luoyhang003
Handles withdrawal requests, processing, reviewing, rejection, and completion.
Integrates with AccessRegistry for whitelisting, OracleRegistry for pricing, ParamRegistry for fee/limit parameters, and AssetsRouter for asset routing. Implements a multi-step withdrawal lifecycle controlled by admin/operator roles.
State Variables
WITHDRAWAL_ADMIN_ROLE
Role allowed to manage WithdrawController
Calculated as keccak256("WITHDRAWAL_ADMIN_ROLE").
bytes32 public constant WITHDRAWAL_ADMIN_ROLE = keccak256("WITHDRAWAL_ADMIN_ROLE");
WITHDRAWAL_OPERATOR_ROLE
Role allowed to operate WithdrawController
Calculated as keccak256("WITHDRAWAL_OPERATOR_ROLE").
bytes32 public constant WITHDRAWAL_OPERATOR_ROLE = keccak256("WITHDRAWAL_OPERATOR_ROLE");
shareToken
ERC20 share token representing ownership in the vault
Token public immutable shareToken;
accessRegistry
Registry managing whitelisted users for withdrawal access
IAccessRegistry public accessRegistry;
oracleRegistry
Registry providing oracle-based pricing for vault tokens and assets
IOracleRegistry public oracleRegistry;
paramRegistry
Registry holding fee rates, withdrawal caps, and forfeit/fee recipient
IParamRegistry public paramRegistry;
assetsRouter
Router responsible for routing assets to destinations
IAssetsRouter public assetsRouter;
withdrawalAssets
List of supported withdrawal assets
address[] public withdrawalAssets;
withdrawalReceipts
Stores all withdrawal receipts (requests + state tracking)
WithdrawalReceipt[] public withdrawalReceipts;
isWithdrawalAsset
Mapping of supported withdrawal asset status
mapping(address => bool) public isWithdrawalAsset;
tokenDecimals
Cached decimals for each withdrawal asset
mapping(address => uint8) public tokenDecimals;
Functions
constructor
Deploys WithdrawController with initial configs.
Validates input addresses, registers assets, and stores decimals.
constructor(
address _defaultAdmin,
address _adminRole,
address _operatorRole,
address _shareToken,
address _accessRegistry,
address _oracleRegistry,
address _paramRegistry,
address _assetsRouter,
address[] memory _withdrawalAssets
);
Parameters
| Name | Type | Description |
|---|---|---|
_defaultAdmin | address | Address granted DEFAULT_ADMIN_ROLE. |
_adminRole | address | Address granted WITHDRAWAL_ADMIN_ROLE. |
_operatorRole | address | Address granted WITHDRAWAL_OPERATOR_ROLE. |
_shareToken | address | ERC20 share token used for withdrawals. |
_accessRegistry | address | Registry of whitelisted users. |
_oracleRegistry | address | Registry for asset/oracle prices. |
_paramRegistry | address | Registry for fees and limits. |
_assetsRouter | address | Router contract for asset routing. |
_withdrawalAssets | address[] | Initial list of supported withdrawal assets. |
requestWithdrawal
Request withdrawal of a specific asset by burning shares.
User must be whitelisted. Generates a withdrawal receipt.
function requestWithdrawal(address _requestToken, uint256 _shares) external;
Parameters
| Name | Type | Description |
|---|---|---|
_requestToken | address | Asset to withdraw into. |
_shares | uint256 | Number of shares to redeem. |
requestWithdrawals
Batch request withdrawals across multiple assets.
Lengths must match. Generates multiple withdrawal receipts.
function requestWithdrawals(address[] memory _requestTokens, uint256[] memory _shares) external;
Parameters
| Name | Type | Description |
|---|---|---|
_requestTokens | address[] | List of withdrawal asset addresses. |
_shares | uint256[] | Corresponding share amounts per asset. |
cancelWithdrawal
Cancel a single pending withdrawal request.
Only the original requester can cancel. Shares are refunded.
function cancelWithdrawal(uint256 _id) external;
Parameters
| Name | Type | Description |
|---|---|---|
_id | uint256 | Receipt ID of the withdrawal request. |
cancelWithdrawals
Batch cancel withdrawal requests.
Only the original requester can cancel. Shares are refunded.
function cancelWithdrawals(uint256[] memory _ids) external;
Parameters
| Name | Type | Description |
|---|---|---|
_ids | uint256[] | An array of receipt IDs of the withdrawal requests. |
completeWithdrawal
Complete a withdrawal once processed.
Burns shares, transfers asset to user, applies fees.
function completeWithdrawal(uint256 _id) external;
Parameters
| Name | Type | Description |
|---|---|---|
_id | uint256 | Receipt ID of withdrawal. |
completeWithdrawals
Batch complete withdrawals.
Burns shares, transfers asset to user, applies fees.
function completeWithdrawals(uint256[] memory _ids) external;
Parameters
| Name | Type | Description |
|---|---|---|
_ids | uint256[] | An array of receipt IDs of withdrawals. |
getWithdrawalReceiptsLength
Returns total number of withdrawal receipts created.
function getWithdrawalReceiptsLength() external view returns (uint256 length_);
Returns
| Name | Type | Description |
|---|---|---|
length_ | uint256 | Total number of withdrawal receipts. |
getWithdrawalReceipts
Paginates withdrawal receipts.
function getWithdrawalReceipts(uint256 _offset, uint256 _limit)
external
view
returns (WithdrawalReceipt[] memory receipts_);
Parameters
| Name | Type | Description |
|---|---|---|
_offset | uint256 | Start index in array. |
_limit | uint256 | Number of receipts to fetch. |
Returns
| Name | Type | Description |
|---|---|---|
receipts_ | WithdrawalReceipt[] | List of withdrawal receipts within range. |
markAsProcessing
Mark receipts as PROCESSING with reference prices.
Operator-only. Sets asset and share prices in receipt.
function markAsProcessing(uint256[] memory _ids, uint256 _priceIndex, bool _isCompleted)
external
onlyRole(WITHDRAWAL_OPERATOR_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_ids | uint256[] | Array of receipt IDs. |
_priceIndex | uint256 | Oracle price index to use. |
_isCompleted | bool | Whether all are finalized as processed. |
markAsProcessed
Mark receipts as PROCESSED, ready for completion.
function markAsProcessed(uint256[] memory _ids) external onlyRole(WITHDRAWAL_OPERATOR_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_ids | uint256[] | Array of receipt IDs. |
markAsReviewing
Move receipts to REVIEWING state.
function markAsReviewing(uint256[] memory _ids) external onlyRole(WITHDRAWAL_OPERATOR_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_ids | uint256[] | Array of receipt IDs. |
markAsRejected
Reject withdrawal requests under review.
Returns original shares to user.
function markAsRejected(uint256[] memory _ids) external onlyRole(WITHDRAWAL_OPERATOR_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_ids | uint256[] | Array of receipt IDs. |
markAsForfeited
Forfeit withdrawals under review.
Redirects shares to treasury (penalty).
function markAsForfeited(uint256[] memory _ids) external onlyRole(WITHDRAWAL_OPERATOR_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_ids | uint256[] | Array of receipt IDs. |
repayAssets
Repays assets back into the controller (usually for liquidity replenishment).
Callable only by WITHDRAWAL_OPERATOR_ROLE.
Lengths of _assets and _amounts must match and be > 0.
Ensures asset is supported and amount is nonzero.
Tokens are transferred from operator to this contract.
function repayAssets(address[] memory _assets, uint256[] memory _amounts) external onlyRole(WITHDRAWAL_OPERATOR_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_assets | address[] | Array of ERC20 token addresses to repay. |
_amounts | uint256[] | Array of amounts to repay for each corresponding asset. |
addWithdrawalAsset
Adds a new supported withdrawal asset.
Callable only by WITHDRAWAL_ADMIN_ROLE.
Requires a valid oracle registered for _asset.
Stores token decimals (must be ≤ 18).
Emits {WithdrawalAssetAdded}.
function addWithdrawalAsset(address _asset) external onlyRole(WITHDRAWAL_ADMIN_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_asset | address | ERC20 token address to be added as a withdrawal option. |
removeWithdrawalAsset
Removes an existing withdrawal asset from the supported list.
Callable only by WITHDRAWAL_ADMIN_ROLE.
Reverts if _asset is not currently supported.
Updates mapping and storage list.
Emits {WithdrawalAssetRemoved}.
function removeWithdrawalAsset(address _asset) external onlyRole(WITHDRAWAL_ADMIN_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_asset | address | ERC20 token address to remove. |
forceRouteAssets
Force routes a specific amount of an asset through the AssetsRouter.
Callable only by WITHDRAWAL_ADMIN_ROLE. Typically used in emergencies or manual corrections. Resets and re-approves allowance before routing.
function forceRouteAssets(address _asset, uint256 _amount) external onlyRole(WITHDRAWAL_ADMIN_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_asset | address | ERC20 token address to route. |
_amount | uint256 | Amount of _asset to route. |
setAssetsRouter
Updates the AssetsRouter contract used for routing assets.
Callable only by WITHDRAWAL_ADMIN_ROLE. Emits {SetAssetsRouter}. Does not reset allowances for all assets (admin must manage separately if needed).
function setAssetsRouter(address _assetsRouter) external onlyRole(WITHDRAWAL_ADMIN_ROLE);
Parameters
| Name | Type | Description |
|---|---|---|
_assetsRouter | address | Address of the new AssetsRouter contract. |
_requestWithdrawal
Emits {WithdrawalRequested}.
Internal logic for handling withdrawal requests. Transfers shares from user, creates a withdrawal receipt, applies fee rate from ParamRegistry, and marks status as REQUESTED.
function _requestWithdrawal(address _requestToken, uint256 _shares) internal nonReentrant;
Parameters
| Name | Type | Description |
|---|---|---|
_requestToken | address | Address of the withdrawal asset requested. |
_shares | uint256 | Amount of shares to redeem. |
_cancelWithdrawal
Emits {WithdrawalCancelled}.
Internal logic for cancelling a withdrawal request. Refunds shares to requester and updates receipt status.
function _cancelWithdrawal(uint256 _id) internal;
Parameters
| Name | Type | Description |
|---|---|---|
_id | uint256 | ID of the withdrawal receipt to cancel. |
_completeWithdrawal
Emits {WithdrawalCompleted}.
Internal logic for completing withdrawals after being processed. Calculates withdrawn amount using oracle prices, applies fee, burns shares, and transfers assets to requester.
function _completeWithdrawal(uint256 _id) internal nonReentrant;
Parameters
| Name | Type | Description |
|---|---|---|
_id | uint256 | ID of the withdrawal receipt to complete. |
_normalize
Normalizes token amounts to base decimals (18).
Expands or compresses numbers depending on asset decimals.
function _normalize(uint256 _amount, uint256 _decimals) internal pure returns (uint256 normalized_);
Parameters
| Name | Type | Description |
|---|---|---|
_amount | uint256 | Token amount in original decimals. |
_decimals | uint256 | Decimals of the token. |
Returns
| Name | Type | Description |
|---|---|---|
normalized_ | uint256 | Amount scaled to 18 decimals. |
_denormalize
Denormalizes token amounts from base decimals (18) to asset decimals.
Reverses normalization logic.
function _denormalize(uint256 _amount, uint256 _decimals) internal pure returns (uint256 denormalized_);
Parameters
| Name | Type | Description |
|---|---|---|
_amount | uint256 | Amount in 18 decimals. |
_decimals | uint256 | Decimals of the asset. |
Returns
| Name | Type | Description |
|---|---|---|
denormalized_ | uint256 | Amount scaled back to asset decimals. |