/** * Aave v3: Supply collateral, enable as collateral, and borrow * * This example demonstrates: * 1. Supplying assets to Aave v3 * 2. Enabling supplied asset as collateral * 3. Borrowing against collateral * * Note: In Aave v3.3+, stable-rate borrowing has been deprecated. Use variable rate (mode = 2). */ import { createWalletRpcClient } from '../../src/utils/chain-config.js'; import { getAavePoolAddress } from '../../src/utils/addresses.js'; import { getTokenMetadata, parseTokenAmount } from '../../src/utils/tokens.js'; import { waitForTransaction } from '../../src/utils/rpc.js'; import { parseUnits } from 'viem'; const CHAIN_ID = 1; // Mainnet (change to 8453 for Base, 42161 for Arbitrum, etc.) const PRIVATE_KEY = process.env.PRIVATE_KEY as `0x${string}`; // ABI for Aave Pool const POOL_ABI = [ { name: 'supply', type: 'function', stateMutability: 'nonpayable', inputs: [ { name: 'asset', type: 'address' }, { name: 'amount', type: 'uint256' }, { name: 'onBehalfOf', type: 'address' }, { name: 'referralCode', type: 'uint16' }, ], outputs: [], }, { name: 'setUserUseReserveAsCollateral', type: 'function', stateMutability: 'nonpayable', inputs: [ { name: 'asset', type: 'address' }, { name: 'useAsCollateral', type: 'bool' }, ], outputs: [], }, { name: 'borrow', type: 'function', stateMutability: 'nonpayable', inputs: [ { name: 'asset', type: 'address' }, { name: 'amount', type: 'uint256' }, { name: 'interestRateMode', type: 'uint256' }, { name: 'referralCode', type: 'uint16' }, { name: 'onBehalfOf', type: 'address' }, ], outputs: [], }, ] as const; // ERC20 ABI for approvals const ERC20_ABI = [ { name: 'approve', type: 'function', stateMutability: 'nonpayable', inputs: [ { name: 'spender', type: 'address' }, { name: 'amount', type: 'uint256' }, ], outputs: [{ name: '', type: 'bool' }], }, { name: 'allowance', type: 'function', stateMutability: 'view', inputs: [ { name: 'owner', type: 'address' }, { name: 'spender', type: 'address' }, ], outputs: [{ name: '', type: 'uint256' }], }, ] as const; async function supplyAndBorrow() { const walletClient = createWalletRpcClient(CHAIN_ID, PRIVATE_KEY); const publicClient = walletClient as any; const account = walletClient.account?.address; if (!account) { throw new Error('No account available'); } const poolAddress = getAavePoolAddress(CHAIN_ID); // Token configuration const collateralToken = getTokenMetadata(CHAIN_ID, 'USDC'); const debtToken = getTokenMetadata(CHAIN_ID, 'USDT'); // Amounts const supplyAmount = parseTokenAmount('1000', collateralToken.decimals); const borrowAmount = parseTokenAmount('500', debtToken.decimals); console.log(`Supplying ${supplyAmount} ${collateralToken.symbol}`); console.log(`Borrowing ${borrowAmount} ${debtToken.symbol}`); console.log(`Pool: ${poolAddress}`); console.log(`Account: ${account}`); // Step 1: Approve token spending console.log('\n1. Approving token spending...'); const approveTx = await walletClient.writeContract({ address: collateralToken.address, abi: ERC20_ABI, functionName: 'approve', args: [poolAddress, supplyAmount], }); await waitForTransaction(publicClient, approveTx); console.log(`Approved: ${approveTx}`); // Step 2: Supply collateral console.log('\n2. Supplying collateral...'); const supplyTx = await walletClient.writeContract({ address: poolAddress, abi: POOL_ABI, functionName: 'supply', args: [collateralToken.address, supplyAmount, account, 0], }); await waitForTransaction(publicClient, supplyTx); console.log(`Supplied: ${supplyTx}`); // Step 3: Enable as collateral console.log('\n3. Enabling as collateral...'); const enableCollateralTx = await walletClient.writeContract({ address: poolAddress, abi: POOL_ABI, functionName: 'setUserUseReserveAsCollateral', args: [collateralToken.address, true], }); await waitForTransaction(publicClient, enableCollateralTx); console.log(`Enabled collateral: ${enableCollateralTx}`); // Step 4: Borrow (variable rate = 2, stable rate is deprecated) console.log('\n4. Borrowing...'); const borrowTx = await walletClient.writeContract({ address: poolAddress, abi: POOL_ABI, functionName: 'borrow', args: [debtToken.address, borrowAmount, 2, 0, account], // mode 2 = variable }); await waitForTransaction(publicClient, borrowTx); console.log(`Borrowed: ${borrowTx}`); console.log('\n✅ Supply and borrow completed successfully!'); } // Run if executed directly if (import.meta.url === `file://${process.argv[1]}`) { supplyAndBorrow().catch(console.error); } export { supplyAndBorrow };