withdraw
Function Type: external
Function Signature: withdraw(address,uint256)
Returns: void
Withdraws host chain coins or ERC20 tokens from the EVVM virtual blockchain back to the user's wallet on the host blockchain. This function includes principal token protection to prevent withdrawal of the ecosystem's core token.
Parameters
| Parameter | Type | Description |
|---|---|---|
token | address | Token contract address or address(0) for host chain coin |
amount | uint256 | Amount to withdraw |
Workflow
- Principal Token Protection: Checks if the token is the ecosystem's principal token using
core.getPrincipalTokenAddress(). Reverts withPrincipalTokenIsNotWithdrawable()if attempting to withdraw the principal token. - EVVM Balance Verification: Validates that the user has sufficient balance in EVVM using
core.getBalance(msg.sender, token) < amount. Reverts withInsufficientBalance()if the user lacks adequate funds. - Conditional Transfer Flow:
- Host Chain Coin Withdrawal (
token == address(0)):- Calls
core.removeAmountFromUser(msg.sender, address(0), amount)to debit the user's EVVM balance - Uses
SafeTransferLib.safeTransferETH(msg.sender, amount)to transfer host chain coins from Treasury to user
- Calls
- ERC20 Withdrawal (
token != address(0)):- Calls
core.removeAmountFromUser(msg.sender, token, amount)to debit the user's EVVM balance - Executes
IERC20(token).transfer(msg.sender, amount)to send tokens from Treasury to user
- Calls
- Host Chain Coin Withdrawal (
Errors
PrincipalTokenIsNotWithdrawable()— Reverted when attempting to withdraw the configured Principal Token (seecore.getPrincipalTokenAddress()).InsufficientBalance()— Reverted whencore.getBalance(msg.sender, token) < amount.
Security & Notes
- The contract updates EVVM balances via
core.removeAmountFromUser(...)before performing the external token/ETH transfer. This is a safe ordering (state change before external call) and helps prevent reentrancy issues on withdraw paths. - For ETH transfers the contract uses
SafeTransferLib.safeTransferETHwhich is recommended. For ERC20 transfers it usesIERC20(token).transfer(...)— consider usingSafeTransferLib.safeTransferfor robustness against non-compliant tokens and to detect transfer failures. - The correctness of
removeAmountFromUser/addAmountToUserdepends on the Core contract having the Treasury as the authorized caller (i.e.,Core.treasuryAddressmust be set). Tests should ensure thatCoreis configured so that these treasury calls succeed. - Add unit tests that cover: withdrawing the principal token (should revert), insufficient balance, successful ETH withdraw, successful ERC20 withdraw, and token transfer failures.