Skip to content

Instantly share code, notes, and snippets.

@sedhu-orbitx
Created October 10, 2025 05:37
Show Gist options
  • Select an option

  • Save sedhu-orbitx/07c5e82327bc91277eb76e23f1ddf2b4 to your computer and use it in GitHub Desktop.

Select an option

Save sedhu-orbitx/07c5e82327bc91277eb76e23f1ddf2b4 to your computer and use it in GitHub Desktop.
evm usdt0 poc
import { Options } from "@layerzerolabs/lz-v2-utilities";
import { ethers, MaxUint256, parseEther, parseUnits, zeroPadValue } from "ethers";
import { LAYERZERO_EIDS, USDT0_CONTRACTS } from "./constants";
const MAX_UINT256 = MaxUint256;
// Helper function to calculate minimum amount with slippage
function calculateMinAmount(amountLD: bigint, slippageBps: number): bigint {
if (slippageBps >= 10000) {
throw new Error("Slippage cannot be 100% or more");
}
const slippageAmount = (amountLD * BigInt(slippageBps)) / 10000n;
return amountLD - slippageAmount;
}
// Helper function to build LayerZero transfer options
function buildTransferOptions(
recipient: string,
options?: {
nativeDropAmount?: string;
composeGasLimit?: number;
lzReceiveGasLimit?: number;
}
): string {
const builder = Options.newOptions();
// Add lzReceive option with gas limit
const lzReceiveGasLimit = options?.lzReceiveGasLimit || 200_000;
builder.addExecutorLzReceiveOption(lzReceiveGasLimit, 0);
// Add compose option if needed (for multi-hop scenarios)
const composeGasLimit = options?.composeGasLimit || 500_000;
builder.addExecutorComposeOption(0, composeGasLimit, 0);
// Add native drop option if specified
if (options?.nativeDropAmount && options.nativeDropAmount !== "0") {
const nativeDropWei = parseEther(options.nativeDropAmount);
const recipientBytes32 = zeroPadValue(recipient, 32);
builder.addExecutorNativeDropOption(nativeDropWei, recipientBytes32);
}
return builder.toHex();
}
const OFT_ABI = [
"function quoteOFT(tuple(uint32,bytes32,uint256,uint256,bytes,bytes,bytes)) view returns (tuple(uint256,uint256), tuple(int256,string)[], tuple(uint256,uint256))",
"function quoteSend(tuple(uint32,bytes32,uint256,uint256,bytes,bytes,bytes), bool) view returns (tuple(uint256,uint256))",
"function send(tuple(uint32,bytes32,uint256,uint256,bytes,bytes,bytes), tuple(uint256,uint256), address) payable returns (tuple(bytes32,uint64,tuple(uint256,uint256)), tuple(uint256,uint256))"
];
async function sendUSDT0ToAnyEVM(
signer: ethers.Signer,
amount: string,
recipient: string,
eid: number,
srcOftAddress: string,
usdtAddress: string,
options?: {
slippageBps?: number; // Default: 50 (0.5%)
nativeDropAmount?: string; // Default: undefined (disabled)
composeGasLimit?: number; // Default: 500_000 (only if compose needed)
lzReceiveGasLimit?: number; // Default: 200_000
}
) {
const usdt = new ethers.Contract(usdtAddress, ["function approve(address,uint256)"], signer);
const oft = new ethers.Contract(srcOftAddress, OFT_ABI, signer);
const amountWei = parseUnits(amount, 6);
const slippageBps = options?.slippageBps || 50; // Default 0.5%
// Approve max amount
// const approveTx = await usdt.approve(srcOftAddress, MAX_UINT256);
// await approveTx.wait();
// console.log(`Approved ${amount} USDT for ${approveTx.hash}`);
// Step 1: Create initial sendParam with minAmountLD = 0, extraOptions = "0x"
const initialSendParam = [
eid, // βœ… Correct destination
zeroPadValue(recipient, 32),
amountWei,
0, // minAmountLD = 0 for initial quote
"0x", // extraOptions = "0x" for initial quote
"0x", // composeMsg = "0x"
"0x" // oftCmd = "0x"
];
// Step 2: Call quoteOFT to get oftReceipt
const [, , oftReceipt] = await oft.quoteOFT(initialSendParam);
// Step 3: Calculate slippage-adjusted minAmountLD from oftReceipt.amountReceivedLD
// This ensures we apply slippage to the actual amount that will be received
const minAmountLD = calculateMinAmount(oftReceipt[1], slippageBps);
// Step 4: Build extraOptions with native drop to recipient
const extraOptions = buildTransferOptions(recipient, {
nativeDropAmount: options?.nativeDropAmount,
composeGasLimit: options?.composeGasLimit,
lzReceiveGasLimit: options?.lzReceiveGasLimit
});
console.log(`πŸ“Š Transfer Details:`);
console.log(` Amount Sent: ${amount} USDT0 (${amountWei.toString()} wei)`);
console.log(` Amount Received: ${ethers.formatUnits(oftReceipt[1], 6)} USDT`);
console.log(` Min Amount: ${ethers.formatUnits(minAmountLD, 6)} USDT0 (${minAmountLD.toString()} wei)`);
console.log(` Slippage: ${slippageBps / 100}%`);
console.log(` Native Drop: ${options?.nativeDropAmount || 'disabled'}`);
console.log(` Extra Options: ${extraOptions}`);
// Step 5: Update sendParam with minAmountLD and extraOptions
const finalSendParam = [
eid,
zeroPadValue(recipient, 32),
amountWei,
minAmountLD,
extraOptions,
"0x", // composeMsg
"0x" // oftCmd
];
// Step 6: Call quoteSend with updated sendParam to get final msgFee
let msgFee = await oft.quoteSend(finalSendParam, false);
msgFee = [msgFee[0].toString(), msgFee[1].toString()];
// Step 7: Execute send() with final sendParam, msgFee, and recipient
console.log(`πŸš€ Executing transfer...`);
const tx = await oft.send(
finalSendParam,
msgFee,
recipient,
{ value: msgFee[0] } // Add native fee payment
);
// const tx = await oft.send.populateTransaction(
// finalSendParam,
// msgFee,
// recipient
// );
// console.log(tx);
console.log(`βœ… Transfer initiated!`);
console.log(` Transaction Hash: ${tx.hash}`);
console.log(` Native Fee: ${ethers.formatEther(msgFee[0])} ETH`);
console.log(` LZ Token Fee: ${ethers.formatEther(msgFee[1])} LZ`);
return tx;
}
async function main() {
try {
if (!process.env.EVM_PRIVATE_KEY || !process.env.POLYGON_RPC_URL) {
throw new Error("EVM_PRIVATE_KEY and POLYGON_RPC_URL must be set");
}
const provider = new ethers.JsonRpcProvider(process.env.POLYGON_RPC_URL);
provider.on("debug", (log) => {
console.log(JSON.stringify(log, null, 2));
});
const signer = new ethers.Wallet(process.env.EVM_PRIVATE_KEY, provider);
// Transfer USDT0 from Polygon to Optimism with configurable options
await sendUSDT0ToAnyEVM(
signer,
"0.1", // Amount: 0.1 USDT0
"0x3C351B147B578E65078626eCfa4606dDC6990318", // Recipient
LAYERZERO_EIDS.OPTIMISM, // Destination: Optimism
USDT0_CONTRACTS.POLYGON.OUpgradeable, // Source OFT contract
USDT0_CONTRACTS.POLYGON.UChildUSDT0, // USDT contract
{
slippageBps: 50, // 0.5% slippage protection
nativeDropAmount: "0.00001", // Drop 0.001 ETH to recipient on Optimism
lzReceiveGasLimit: 200_000, // Gas for lzReceive
composeGasLimit: 500_000 // Gas for compose (if needed)
}
);
} catch (error) {
console.error(error);
}
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment