Skip to main content

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

ParameterTypeDescription
toAddressaddressRecipient address on the external chain
tokenaddressToken contract address or address(0) for native coin
amountuint256Amount to withdraw
protocolToExecutebytes1Cross-chain protocol identifier (0x01, 0x02, or 0x03)

Protocol Identifiers

ValueProtocolDescription
0x01HyperlaneUses Hyperlane mailbox for cross-chain messaging
0x02LayerZeroUses LayerZero endpoint for omnichain transfers
0x03AxelarUses Axelar gateway for decentralized cross-chain communication

Workflow

Initial Validations

  1. Principal Token Protection: Verifies the token is not the ecosystem's principal token using getEvvmMetadata().principalTokenAddress. Reverts with PrincipalTokenIsNotWithdrawable if attempting to withdraw principal token.
  2. Balance Verification: Ensures user has sufficient balance in EVVM using getBalance(msg.sender, token) < amount. Reverts with InsufficientBalance if insufficient funds.
  3. 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:

  1. Identify the token type
  2. Determine the recipient address
  3. 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
Gas Payment Required

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:

  1. Decode the payload to extract transfer details
  2. Transfer the corresponding assets to the specified recipient
  3. Handle both native coins and ERC20 tokens appropriately