withdraw
Function Type: external payable
Function Signature: withdraw(address,address,uint256,bytes1)
Returns: void
Withdraws assets from the EVVM virtual blockchain to an external blockchain through cross-chain protocols. This function debits the user's EVVM balance and initiates a cross-chain transfer to the specified recipient on the external chain.
Parameters
Parameter | Type | Description |
---|---|---|
toAddress | address | Recipient address on the external chain |
token | address | Token contract address or address(0) for native coin |
amount | uint256 | Amount to withdraw |
protocolToExecute | bytes1 | Cross-chain protocol identifier (0x01 , 0x02 , or 0x03 ) |
Protocol Identifiers
Value | Protocol | Description |
---|---|---|
0x01 | Hyperlane | Uses Hyperlane mailbox for cross-chain messaging |
0x02 | LayerZero | Uses LayerZero endpoint for omnichain transfers |
0x03 | Axelar | Uses Axelar gateway for decentralized cross-chain communication |
Workflow
Initial Validations
- Principal Token Protection: Verifies the token is not the ecosystem's principal token using
getEvvmMetadata().principalTokenAddress
. Reverts withPrincipalTokenIsNotWithdrawable
if attempting to withdraw principal token. - Balance Verification: Ensures user has sufficient balance in EVVM using
getBalance(msg.sender, token) < amount
. Reverts withInsufficientBalance
if insufficient funds. - EVVM Balance Debit: Calls
removeAmountFromUser(msg.sender, token, amount)
to deduct amount from user's EVVM balance.
Protocol-Specific Execution
Hyperlane (0x01
)
uint256 quote = getQuoteHyperlane(toAddress, token, amount);
IMailbox(hyperlane.mailboxAddress).dispatch{value: quote}(
hyperlane.externalChainStationDomainId,
hyperlane.externalChainStationAddress,
payload
);
- Gas Estimation: Calls
getQuoteHyperlane()
to estimate required native tokens - Message Dispatch: Sends encoded payload to external chain station via Hyperlane mailbox
- Native Payment:
msg.value
must cover the quoted gas fee
LayerZero (0x02
)
uint256 fee = quoteLayerZero(toAddress, token, amount);
_lzSend(
layerZero.externalChainStationEid,
payload,
_options,
MessagingFee(fee, 0),
msg.sender
);
- Fee Calculation: Estimates LayerZero messaging fees
- Omnichain Send: Uses LayerZero's
_lzSend
with predefined options - Refund Address: Excess fees refunded to
msg.sender
Axelar (0x03
)
IAxelarGasService(axelar.gasServiceAddress).payNativeGasForContractCall{
value: msg.value
}(
address(this),
axelar.externalChainStationChainName,
axelar.externalChainStationAddress,
payload,
msg.sender
);
gateway().callContract(
axelar.externalChainStationChainName,
axelar.externalChainStationAddress,
payload
);
- Gas Service Payment: Pays native tokens to Axelar gas service
- Gateway Call: Initiates cross-chain contract call through Axelar gateway
- Refund Recipient: Gas refunds directed to
msg.sender
Payload Encoding
The function encodes transfer data as:
bytes memory payload = abi.encode(token, toAddress, amount);
This payload is decoded on the external chain station to:
- Identify the token type
- Determine the recipient address
- Process the transfer amount
Gas Requirements
Users must send sufficient native tokens with the transaction to cover:
- Hyperlane: Mailbox dispatch fees
- LayerZero: Endpoint messaging fees
- Axelar: Gas service payments
The transaction will revert if insufficient native tokens are provided to cover cross-chain messaging costs. Use the respective quote functions to estimate required amounts.
Security Features
- Authorization: Only token holders can withdraw their own balances
- Principal Token Protection: Prevents withdrawal of ecosystem's core token
- Balance Verification: Ensures sufficient EVVM balance before processing
- Protocol Validation: Reverts for unsupported protocol identifiers
External Chain Processing
Upon successful cross-chain message delivery, the external chain station will:
- Decode the payload to extract transfer details
- Transfer the corresponding assets to the specified recipient
- Handle both native coins and ERC20 tokens appropriately