import { playgroundHelper } from "../../helpers/helpers"; import { createPublicClient, encodeFunctionData, http, parseUnits, serializeTransaction, } from "viem"; import { arbitrum } from "viem/chains"; import { chainAdapters, contracts, MPCSignature, utils } from "chainsig.js"; import { stablecoinVaultConstants } from "../constants"; // Two-phase ERC4626 vault deposit process: // 1. Approve USDC spending by the vault contract (approve policy) // 2. Deposit USDC into the vault to receive vault shares (deposit policy) const DEPOSIT_AMOUNT = "200000000"; // 1000 USDC with 6 decimals const VAULT_ADDRESS = stablecoinVaultConstants.MORPHO_BLUE_ARB_VAULT_ADDRESS; const APPROVE_POLICY_ID = "morpho_blue_arb_usdc_approve"; const DEPOSIT_POLICY_ID = "morpho_blue_arb_usdc_deposit"; const USDC_ADDRESS = stablecoinVaultConstants.USDC_ARB_ADDRESS; const CHAIN_SIG_DERIVED_ADDRESS = stablecoinVaultConstants.ARBITRUM_CHAINSIG_DERIVED_ADDRESS; // Create Arbitrum client const client = createPublicClient({ chain: arbitrum, transport: http(), }); // Setup chain signature contract and adapter for transaction broadcasting const chainSigContract = new contracts.ChainSignatureContract({ networkId: "mainnet", contractId: "v1.signer", }); // setup chain adapter const evmChain = new chainAdapters.evm.EVM({ publicClient: client, contract: chainSigContract, }); async function phase1Approve(): Promise { console.log("=== Phase 1: USDC Approve ==="); const approveTxRequest = await client.prepareTransactionRequest({ account: CHAIN_SIG_DERIVED_ADDRESS, to: USDC_ADDRESS, data: encodeFunctionData({ abi: stablecoinVaultConstants.erc20Abi, functionName: "approve", args: [VAULT_ADDRESS, DEPOSIT_AMOUNT], }), type: "eip1559", }); const approveSerializedTx = serializeTransaction(approveTxRequest); console.log("Proposing USDC approve transaction..."); // Execute approve transaction via chain signature policy const approveSignatures = await playgroundHelper.account.callFunction({ contractId: playgroundHelper.vaultContractId, methodName: "propose_execution", args: { policy_id: APPROVE_POLICY_ID, function_args: approveSerializedTx, deadline_hours: 0, }, gas: 50000000000000n, // 50 TGas }); // Sign and broadcast approve transaction console.log("Broadcasting approve transaction..."); const signedApproveTx = evmChain.finalizeTransactionSigning({ transaction: approveTxRequest, rsvSignatures: approveSignatures.map((v) => utils.cryptography.toRSV(v)), }); const { hash: approveHash } = await evmChain.broadcastTx(signedApproveTx); console.log("Approve transaction hash:", approveHash); // Wait for approve transaction confirmation console.log("Waiting for approve transaction confirmation..."); await client.waitForTransactionReceipt({ hash: approveHash }); return approveHash; } async function phase2Deposit(): Promise { console.log("=== Phase 2: Vault Deposit ==="); const depositTxRequest = await client.prepareTransactionRequest({ account: CHAIN_SIG_DERIVED_ADDRESS, to: VAULT_ADDRESS, data: encodeFunctionData({ abi: stablecoinVaultConstants.vaultAbi, functionName: "deposit", args: [DEPOSIT_AMOUNT, CHAIN_SIG_DERIVED_ADDRESS], // deposit assets, receive shares }), type: "eip1559", }); const depositSerializedTx = serializeTransaction(depositTxRequest); console.log("Proposing vault deposit transaction..."); // Execute deposit transaction via chain signature policy const depositSignatures = await playgroundHelper.account.callFunction({ contractId: playgroundHelper.vaultContractId, methodName: "propose_execution", args: { policy_id: DEPOSIT_POLICY_ID, function_args: depositSerializedTx, deadline_hours: 0, }, gas: 50000000000000n, // 50 TGas }); // Sign and broadcast deposit transaction console.log("Broadcasting deposit transaction..."); const signedDepositTx = evmChain.finalizeTransactionSigning({ transaction: depositTxRequest, rsvSignatures: depositSignatures.map((v) => utils.cryptography.toRSV(v)), }); const { hash: depositHash } = await evmChain.broadcastTx(signedDepositTx); console.log("Deposit transaction hash:", depositHash); return depositHash; } async function main() { console.log("Starting ERC4626 vault deposit process..."); console.log("Derived Arbitrum address:", CHAIN_SIG_DERIVED_ADDRESS); try { // Phase 1: Approve USDC spending // const approveHash = await phase1Approve(); // Phase 2: Deposit USDC into vault const depositHash = await phase2Deposit(); console.log("\n=== ERC4626 vault deposit process completed successfully! ==="); console.log(`Deposited ${DEPOSIT_AMOUNT} USDC into ${VAULT_ADDRESS}`); // console.log(`Approve tx: ${approveHash}`); console.log(`Deposit tx: ${depositHash}`); } catch (error) { console.error("Error during deposit process:", error); throw error; } } // Execute the main function main().catch(console.error);