/** * Compound III: Supply collateral and borrow base asset * * This example demonstrates how to: * 1. Supply collateral to Compound III * 2. Borrow the base asset (e.g., USDC) * * Note: In Compound III, you "borrow" by withdrawing the base asset * after supplying collateral. There's one base asset per market. */ import { createWalletRpcClient } from '../../src/utils/chain-config.js'; import { getCompound3Comet } from '../../src/utils/addresses.js'; import { getTokenMetadata, parseTokenAmount } from '../../src/utils/tokens.js'; import { waitForTransaction } from '../../src/utils/rpc.js'; const CHAIN_ID = 1; // Mainnet const PRIVATE_KEY = process.env.PRIVATE_KEY as `0x${string}`; // Compound III Comet ABI const COMET_ABI = [ { name: 'supply', type: 'function', stateMutability: 'nonpayable', inputs: [ { name: 'asset', type: 'address' }, { name: 'amount', type: 'uint256' }, ], outputs: [], }, { name: 'withdraw', type: 'function', stateMutability: 'nonpayable', inputs: [ { name: 'asset', type: 'address' }, { name: 'amount', type: 'uint256' }, ], outputs: [], }, { name: 'baseToken', type: 'function', stateMutability: 'view', inputs: [], outputs: [{ name: '', type: 'address' }], }, { name: 'getBorrowBalance', type: 'function', stateMutability: 'view', inputs: [{ name: 'account', type: 'address' }], outputs: [{ name: '', type: 'uint256' }], }, { name: 'getCollateralBalance', type: 'function', stateMutability: 'view', inputs: [ { name: 'account', type: 'address' }, { name: 'asset', type: 'address' }, ], outputs: [{ name: '', type: 'uint256' }], }, ] 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' }], }, ] 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 cometAddress = getCompound3Comet(CHAIN_ID); // Get base token (USDC for USDC market) console.log('Querying Comet contract...'); const baseToken = await publicClient.readContract({ address: cometAddress, abi: COMET_ABI, functionName: 'baseToken', }) as `0x${string}`; console.log(`Comet: ${cometAddress}`); console.log(`Base token: ${baseToken}`); // Use WETH as collateral (adjust based on market) const collateralToken = getTokenMetadata(CHAIN_ID, 'WETH'); const baseTokenMetadata = getTokenMetadata(CHAIN_ID, 'USDC'); // Assuming USDC market const collateralAmount = parseTokenAmount('1', collateralToken.decimals); // 1 WETH const borrowAmount = parseTokenAmount('2000', baseTokenMetadata.decimals); // 2000 USDC console.log(`\nSupplying ${collateralAmount} ${collateralToken.symbol} as collateral`); console.log(`Borrowing ${borrowAmount} ${baseTokenMetadata.symbol} (base asset)`); // Step 1: Approve collateral token console.log('\n1. Approving collateral token...'); const approveTx = await walletClient.writeContract({ address: collateralToken.address, abi: ERC20_ABI, functionName: 'approve', args: [cometAddress, collateralAmount], }); await waitForTransaction(publicClient, approveTx); console.log(`Approved: ${approveTx}`); // Step 2: Supply collateral console.log('\n2. Supplying collateral...'); const supplyTx = await walletClient.writeContract({ address: cometAddress, abi: COMET_ABI, functionName: 'supply', args: [collateralToken.address, collateralAmount], }); await waitForTransaction(publicClient, supplyTx); console.log(`Supplied: ${supplyTx}`); // Step 3: "Borrow" by withdrawing base asset // In Compound III, borrowing is done by withdrawing the base asset console.log('\n3. Borrowing base asset (withdrawing)...'); const borrowTx = await walletClient.writeContract({ address: cometAddress, abi: COMET_ABI, functionName: 'withdraw', args: [baseToken, borrowAmount], }); await waitForTransaction(publicClient, borrowTx); console.log(`Borrowed: ${borrowTx}`); // Step 4: Check balances console.log('\n4. Checking positions...'); const borrowBalance = await publicClient.readContract({ address: cometAddress, abi: COMET_ABI, functionName: 'getBorrowBalance', args: [account], }) as bigint; const collateralBalance = await publicClient.readContract({ address: cometAddress, abi: COMET_ABI, functionName: 'getCollateralBalance', args: [account, collateralToken.address], }) as bigint; console.log(`Borrow balance: ${borrowBalance} ${baseTokenMetadata.symbol}`); console.log(`Collateral balance: ${collateralBalance} ${collateralToken.symbol}`); 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 };