import { Agent, type AgentContext, type CurrentPosition } from "@circuitorg/agent-sdk";
import { encodeFunctionData, parseAbi } from "viem";
// Ethereum Mainnet addresses
const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const AAVE_V3_POOL = "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2";
const erc20Abi = parseAbi(["function approve(address spender, uint256 amount)"]);
const aavePoolAbi = parseAbi([
"function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)",
"function withdraw(address asset, uint256 amount, address to)",
]);
async function run(agent: AgentContext): Promise<void> {
// Find USDC balance
const usdc = agent.currentPositions.find(
(p) => p.assetAddress.toLowerCase() === USDC.toLowerCase()
);
if (!usdc || BigInt(usdc.currentQty) === 0n) {
await agent.log("No USDC to deposit");
return;
}
const amount = BigInt(usdc.currentQty);
await agent.log(`Depositing ${usdc.currentQty} USDC (raw) into Aave V3`);
// Step 1: Approve Aave Pool to spend USDC (skip if already approved)
const approvedCheck = await agent.memory.get("aaveApproved");
const alreadyApproved = approvedCheck.success && approvedCheck.data?.value === "true";
if (!alreadyApproved) {
const approveData = encodeFunctionData({
abi: erc20Abi,
functionName: "approve",
args: [AAVE_V3_POOL, 2n ** 256n - 1n], // max uint256 = approve once
});
const approveResult = await agent.signAndSend({
network: "ethereum:1",
request: {
toAddress: USDC,
data: approveData,
value: "0",
},
message: "Approve USDC for Aave V3",
});
if (!approveResult.success) {
await agent.log(`Approve failed: ${approveResult.error}`, { error: true });
return;
}
await agent.memory.set("aaveApproved", "true");
await agent.log("USDC approved for Aave V3");
}
// Step 2: Supply USDC to Aave V3
const supplyData = encodeFunctionData({
abi: aavePoolAbi,
functionName: "supply",
args: [USDC, amount, agent.sessionWalletAddress, 0],
});
const supplyResult = await agent.signAndSend({
network: "ethereum:1",
request: {
toAddress: AAVE_V3_POOL,
data: supplyData,
value: "0",
},
message: "Supply USDC to Aave V3",
});
if (supplyResult.success) {
await agent.log("USDC deposited into Aave V3!");
} else {
await agent.log(`Supply failed: ${supplyResult.error}`, { error: true });
}
}
async function unwind(agent: AgentContext, positions: CurrentPosition[]): Promise<void> {
// Withdraw all USDC from Aave V3
const withdrawData = encodeFunctionData({
abi: aavePoolAbi,
functionName: "withdraw",
args: [USDC, 2n ** 256n - 1n, agent.sessionWalletAddress], // max uint256 = withdraw all
});
const result = await agent.signAndSend({
network: "ethereum:1",
request: {
toAddress: AAVE_V3_POOL,
data: withdrawData,
value: "0",
},
message: "Withdraw all USDC from Aave V3",
});
if (result.success) {
await agent.log("Withdrawn all USDC from Aave V3");
} else {
await agent.log(`Withdraw failed: ${result.error}`, { error: true });
}
}
const agent = new Agent({
runFunction: run,
unwindFunction: unwind,
});
export default agent.getExport();