Manage through ABI
Bolarity enables you to interact with any smart contract. This section demonstrates how to construct your interaction data using Aave USDT vault as an example.
Step 1: Generate the payload for your requirement
// Call Aave contract methods
// Encode the user's Solana address as a bytes32 format for compatibility with Ethereum.
const userAddress = coder.encode(
["bytes32"],
[Buffer.from(new PublicKey("6v9YRMJbiXSjwco3evS2XdNuqPbwzKf3ykmn5iQJ4UyF").toBytes())]
); // Your Solana address
// Define the user's Ethereum proxy address.
const proxyAddress = '0xD00c212f8Cc24CdB897D5CE4eD1962Ca0A52f709'; // Your generated Ethereum address
// *** Approve USDT ***
const usdtContractAddress = coder.encode(
["bytes32"],
[ethers.utils.zeroPad(Buffer.from(hexStringToUint8Array('0xaA8E23Fb1079EA71e0a56F48a2aA51851D8433D0')), 32)]
); // USDT contract address
let ABI = ["function approve(address to, uint256 tokenId)"];
let iface = new ethers.utils.Interface(ABI);
// Encode the approval function call to allow infinite USDT approval to a specific address.
let paras = iface.encodeFunctionData("approve", [
'0x6ae43d3271ff6888e7fc43fd7321a503ff738951', // Address to approve
BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") // Maximum token approval
]);
// Assemble the payload for the approval transaction.
let payloadPart = coder.encode(
["bytes32", "uint256", "bytes"],
[usdtContractAddress, 0, paras]
);
let payload = coder.encode(
["bytes32", "bytes"],
[userAddress, payloadPart]
);
console.log("Approve USDT Payload:", payload);
// *** Deposit USDT ***
// Ensure USDT is approved before proceeding with the deposit.
const depositContractAddress = coder.encode(
["bytes32"],
[ethers.utils.zeroPad(Buffer.from(hexStringToUint8Array('0x6Ae43d3271ff6888e7Fc43Fd7321a503ff738951')), 32)]
); // Aave lending pool contract address
ABI = ["function supply(address asset,uint256 amount,address onBehalfOf,uint16 referralCode)"];
iface = new ethers.utils.Interface(ABI);
// Encode the supply function call to deposit USDT into Aave.
paras = iface.encodeFunctionData("supply", [
'0xaa8e23fb1079ea71e0a56f48a2aa51851d8433d0', // USDT contract address
100000000, // Amount to deposit (100 USDT, 6 decimal precision)
proxyAddress, // Deposit on behalf of the proxy address
0 // Referral code
]);
// Assemble the payload for the deposit transaction.
payloadPart = coder.encode(
["bytes32", "uint256", "bytes"],
[depositContractAddress, 0, paras]
);
payload = coder.encode(
["bytes32", "bytes"],
[userAddress, payloadPart]
);
console.log("Deposit USDT Payload:", payload);
// *** Withdraw USDT ***
const withdrawContractAddress = coder.encode(
["bytes32"],
[ethers.utils.zeroPad(Buffer.from(hexStringToUint8Array('0x6Ae43d3271ff6888e7Fc43Fd7321a503ff738951')), 32)]
); // Aave lending pool contract address
ABI = ["function withdraw(address asset,uint256 amount,address to)"];
iface = new ethers.utils.Interface(ABI);
// Encode the withdraw function call to remove USDT from Aave.
paras = iface.encodeFunctionData("withdraw", [
'0xaa8e23fb1079ea71e0a56f48a2aa51851d8433d0', // USDT contract address
BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), // Withdraw maximum amount
proxyAddress // Withdraw to the proxy address
]);
// Assemble the payload for the withdrawal transaction.
payloadPart = coder.encode(
["bytes32", "uint256", "bytes"],
[withdrawContractAddress, 0, paras]
);
payload = coder.encode(
["bytes32", "bytes"],
[userAddress, payloadPart]
);
console.log("Withdraw USDT Payload:", payload);
Step 2: Call Ethereum smart contract using this payload
// Encode the Solana address as a bytes32 format, compatible with Ethereum.
const solanaAddress = coder.encode(
["bytes32"],
[Buffer.from(new PublicKey("your-solana-account").toBytes())]
);
// Encode the target Ethereum contract address, padded to 32 bytes for consistency.
const contractAddress = coder.encode(
["bytes32"],
[ethers.utils.zeroPad(Buffer.from([contractAddressYouWantToCall]), 32)]
);
// Define the ABI for the Ethereum contract's "store" function, which accepts a uint256 parameter.
let ABI = ["function store(uint256 num)"];
// Create an ethers Interface instance to encode the function call data.
let iface = new ethers.utils.Interface(ABI);
// Encode the function call for the "store" function with a parameter value of 2.
let params = iface.encodeFunctionData("store", [2]);
// Assemble the payload part by encoding the contract address, a placeholder value (0), and the encoded function data.
let payloadPart = coder.encode(
["bytes32", "uint256", "bytes"],
[contractAddress, 0, params]
);
// Final payload: combine the Solana address and the payload part into a single message.
const payload = coder.encode(
["bytes32", "bytes"],
[solanaAddress, payloadPart]
);
// Send the message using the Solana program (via the Anchor framework).
const programID = new PublicKey("solana-program-address"); // The Solana program ID.
const program = new anchor.Program(idl, programID); // Anchor program instance.
const message = hexStringToUint8Array(payload); // Convert payload to a byte array.
// Create the instruction to send the message to the Solana program.
const ix3 = program.methods
.sendMessage(Buffer.from(message)) // Pass the message as a buffer.
.accounts({
config: realConfig, // Real configuration for the program.
wormholeProgram: CORE_BRIDGE_PID, // Wormhole program ID for cross-chain communication.
...wormholeAccounts2, // Additional necessary accounts for the transaction.
})
.instruction();
// Create a new transaction and add the instruction.
const tx3 = new Transaction().add(await ix3);
try {
const commitment: Commitment = 'confirmed'; // Set the commitment level for transaction confirmation.
// Send the transaction and await confirmation.
await sendAndConfirmTransaction(provider.connection, tx3, [yourSolanaAccount], { commitment });
} catch (error) {
// Catch and log any errors during the transaction submission process.
console.error("Error submitting transaction:", error);
}
Last updated