quoteSend, then pass the returned fee to
send and attach that fee as the transaction’s native value. You can use the
contract explorer or the official LayerZero CLI.
Chains and contracts
Use the destination LayerZero V2 endpoint ID (EID) indstEid. An EID is not
an EVM chain ID. Call quoteSend and send on the source contract below.
On Ethereum, the SOPH token is
0x6B7774CB12ed7573a7586E7D0e62a2A563dDd3f0.
It is separate from the adapter above. On the other five chains, the SOPH token
and OFT are the same contract.
Before sending, read peers(destinationEid) on the source contract and
peers(sourceEid) on the destination contract. Each must match the other
contract’s address left-padded with zeros to 32 bytes. Stop if either peer is
zero or does not match. Keep enough native currency on the source chain for
both the LayerZero fee and transaction gas.
Manual transfer through a contract explorer
The example below sends 1 SOPH from Ethereum to Base. Change the source contract and destination EID to use another pair from the table.1. Approve SOPH when sending from Ethereum
On the Ethereum SOPH token, open Contract → Write Contract, connect your wallet on Ethereum and callapprove:
Wait for the approval to confirm. You can skip this transaction if
allowance(yourAddress, adapterAddress) already covers the amount. Approve the
adapter, not the LayerZero endpoint or the destination contract.
The other five chains use OFTs with approvalRequired() = false; a direct
send from your own wallet does not need ERC-20 approval there.
2. Build the send parameters
On the Ethereum adapter, prepare this_sendParam tuple. Replace the
recipient with your own address on Base.
For example, address
0x1234567890123456789012345678901234567890 becomes
0x0000000000000000000000001234567890123456789012345678901234567890.
Do not use that example recipient for an actual transfer.
The listed routes already enforce destination receive gas, so extraOptions
can be 0x for a plain SOPH transfer. No compose message is needed. SOPH’s OFTs
use six shared decimals: choose amounts with at most six decimal places to avoid
dust rounding. quoteOFT(_sendParam) can be used to inspect the amounts sent and
received. Do not set minAmountLD to zero just to bypass a failed quote.
3. Query the fee
Under Read Contract on the source adapter/OFT, call:false selects payment in the source chain’s
native currency. The result is a MessagingFee tuple:
lzTokenFee is 0 for this flow.
nativeFee pays LayerZero delivery costs and is separate from the wallet’s
transaction gas fee. Query it again immediately before sending; do not reuse a
fee from an earlier transfer.
4. Send with the quoted fee
Under Write Contract on the same source adapter/OFT, callsend:
The
_fee.nativeFee field takes the integer in base units. An explorer’s
payable ETH / BNB / POL / BEAM amount field typically takes whole native
units: divide nativeFee by 10^18 when that is the field’s unit. For example,
1000000000000000 base units is 0.001 native currency. This is a conversion
example, not a fee quote. Do not add the SOPH amount to the transaction value.Use the official LayerZero CLI
The officialcreate-lz-oapp
OFT example includes the lz:oft:send task. It checks allowance, approves the
source adapter when needed, calls quoteSend, and supplies the fee to send.
It sends real transactions; it is not a quote-only or dry-run command.
1. Set up the official example
Use Node.js 22 LTS and npm. The scaffold command tested for this guide is:tasks
directory unchanged. No contract deployment or route wiring is needed.
Replace hardhat.config.ts with:
layerzero.config.ts with the existing SOPH contract addresses:
2. Send SOPH
SetPRIVATE_KEY locally for the sending wallet, for example in an uncommitted
.env file. Never paste it into documentation, source control or a shared
terminal. Override the RPC_URL_* variables if a public RPC is unavailable or
rate-limited. Use the manual explorer flow above if you prefer a connected wallet.
For Ethereum → Base, replace the recipient below with your own address:
--amount and --min-amount are in whole SOPH, unlike the base-unit
fields on the explorer. This sends 1 SOPH. The task automatically submits an
Ethereum approval first if the existing allowance is insufficient, then quotes
and sends. It may broadcast without a further confirmation prompt.
For the reverse route use --src-eid 30184 --dst-eid 30101. For any other pair,
use its source and destination EIDs from the table. The config resolves each
chain’s contract separately; no --oft-address override is needed. Do not use
--simple-workers on mainnet.
Track the returned transaction on LayerZero Scan and check the destination
balance, just as with the manual flow.
Troubleshooting
- Insufficient allowance: on Ethereum, approve the SOPH token for the source adapter and wait for confirmation. A token balance alone is not an allowance.
- Fee or gas error: keep enough native currency for both costs, re-run
quoteSendwith the exact send tuple, and check the payable field’s units. - Peer, endpoint or quote error: verify both peers, the destination EID and the source contract. Never substitute Sophon’s retired endpoint.
- Minimum amount error: check token units and shared-decimal rounding with
quoteOFT. For 1 SOPH, both amount fields are1000000000000000000. - Source confirmed but destination pending: inspect the message on LayerZero Scan before initiating another transfer. Do not assume the first send failed.