Skip to content

开发指南

环境准备

安装依赖

bash
# npm
npm install @aave/v4-core @aave/v4-periphery

# yarn
yarn add @aave/v4-core @aave/v4-periphery

# Foundry
forge install aave/aave-v4-core

配置文件

javascript
// hardhat.config.js
module.exports = {
  solidity: {
    version: "0.8.20",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200
      },
      viaIR: true
    }
  }
};

核心接口

Pool 接口

solidity
interface IPoolV4 {
    // 供应资产
    function supply(
        address asset,
        uint256 amount,
        address onBehalfOf,
        uint16 referralCode
    ) external;
    
    // 提取资产
    function withdraw(
        address asset,
        uint256 amount,
        address to
    ) external returns (uint256);
    
    // 借贷资产
    function borrow(
        address asset,
        uint256 amount,
        uint256 interestRateMode,
        uint16 referralCode,
        address onBehalfOf
    ) external;
    
    // 偿还借款
    function repay(
        address asset,
        uint256 amount,
        uint256 interestRateMode,
        address onBehalfOf
    ) external returns (uint256);
    
    // 批量操作
    function executeBatch(
        BatchOperation[] calldata operations
    ) external;
    
    // 获取用户账户数据
    function getUserAccountData(address user) external view returns (
        uint256 totalCollateralBase,
        uint256 totalDebtBase,
        uint256 availableBorrowsBase,
        uint256 currentLiquidationThreshold,
        uint256 ltv,
        uint256 healthFactor
    );
}

流动性层接口

solidity
interface ILiquidityLayer {
    struct LiquidityAllocation {
        address market;
        uint256 allocation;
    }
    
    // 获取资产的流动性分配
    function getLiquidityAllocation(address asset) 
        external view returns (LiquidityAllocation[] memory);
    
    // 优化流动性分配
    function optimizeLiquidity(address asset) external;
    
    // 获取总可用流动性
    function getTotalAvailableLiquidity(address asset) 
        external view returns (uint256);
}

自动化模块接口

solidity
interface IAutomationModule {
    enum TriggerType {
        HEALTH_FACTOR,
        PRICE,
        TIME,
        UTILIZATION
    }
    
    enum ActionType {
        REPAY,
        WITHDRAW,
        SUPPLY,
        SWAP_COLLATERAL
    }
    
    struct AutomationRule {
        TriggerType triggerType;
        uint256 triggerValue;
        ActionType actionType;
        address actionAsset;
        uint256 actionAmount;
        bool isActive;
    }
    
    function createRule(AutomationRule calldata rule) 
        external returns (uint256 ruleId);
    
    function executeRule(uint256 ruleId) external;
    
    function cancelRule(uint256 ruleId) external;
    
    function getUserRules(address user) 
        external view returns (uint256[] memory);
}

基础集成

供应和借贷

solidity
pragma solidity ^0.8.20;

import {IPoolV4} from "@aave/v4-core/contracts/interfaces/IPoolV4.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract AaveV4Integration {
    IPoolV4 public immutable POOL;
    
    constructor(address pool) {
        POOL = IPoolV4(pool);
    }
    
    function supply(address asset, uint256 amount) external {
        IERC20(asset).transferFrom(msg.sender, address(this), amount);
        IERC20(asset).approve(address(POOL), amount);
        POOL.supply(asset, amount, msg.sender, 0);
    }
    
    function borrow(address asset, uint256 amount) external {
        POOL.borrow(asset, amount, 2, 0, msg.sender);
    }
    
    function repay(address asset, uint256 amount) external {
        IERC20(asset).transferFrom(msg.sender, address(this), amount);
        IERC20(asset).approve(address(POOL), amount);
        POOL.repay(asset, amount, 2, msg.sender);
    }
}

批量操作

solidity
pragma solidity ^0.8.20;

import {IPoolV4} from "@aave/v4-core/contracts/interfaces/IPoolV4.sol";

contract BatchOperationsExample {
    IPoolV4 public immutable POOL;
    
    constructor(address pool) {
        POOL = IPoolV4(pool);
    }
    
    /**
     * @notice 一键开仓:供应抵押品并借贷
     */
    function openPosition(
        address collateralAsset,
        uint256 collateralAmount,
        address borrowAsset,
        uint256 borrowAmount
    ) external {
        // 转入抵押品
        IERC20(collateralAsset).transferFrom(
            msg.sender, 
            address(this), 
            collateralAmount
        );
        IERC20(collateralAsset).approve(address(POOL), collateralAmount);
        
        // 构建批量操作
        IPoolV4.BatchOperation[] memory ops = new IPoolV4.BatchOperation[](2);
        
        ops[0] = IPoolV4.BatchOperation({
            operationType: 0, // Supply
            asset: collateralAsset,
            amount: collateralAmount,
            interestRateMode: 0,
            onBehalfOf: msg.sender
        });
        
        ops[1] = IPoolV4.BatchOperation({
            operationType: 2, // Borrow
            asset: borrowAsset,
            amount: borrowAmount,
            interestRateMode: 2, // Variable
            onBehalfOf: msg.sender
        });
        
        // 执行批量操作
        POOL.executeBatch(ops);
        
        // 将借出的资产发送给用户
        IERC20(borrowAsset).transfer(msg.sender, borrowAmount);
    }
    
    /**
     * @notice 一键平仓:偿还借款并提取抵押品
     */
    function closePosition(
        address collateralAsset,
        uint256 collateralAmount,
        address debtAsset,
        uint256 debtAmount
    ) external {
        // 转入债务资产
        IERC20(debtAsset).transferFrom(msg.sender, address(this), debtAmount);
        IERC20(debtAsset).approve(address(POOL), debtAmount);
        
        // 构建批量操作
        IPoolV4.BatchOperation[] memory ops = new IPoolV4.BatchOperation[](2);
        
        ops[0] = IPoolV4.BatchOperation({
            operationType: 3, // Repay
            asset: debtAsset,
            amount: debtAmount,
            interestRateMode: 2,
            onBehalfOf: msg.sender
        });
        
        ops[1] = IPoolV4.BatchOperation({
            operationType: 1, // Withdraw
            asset: collateralAsset,
            amount: collateralAmount,
            interestRateMode: 0,
            onBehalfOf: msg.sender
        });
        
        POOL.executeBatch(ops);
        
        // 将抵押品发送给用户
        IERC20(collateralAsset).transfer(msg.sender, collateralAmount);
    }
}

自动化集成

健康因子保护

solidity
pragma solidity ^0.8.20;

import {IAutomationModule} from "@aave/v4-core/contracts/interfaces/IAutomationModule.sol";
import {IPoolV4} from "@aave/v4-core/contracts/interfaces/IPoolV4.sol";

contract HealthFactorProtection {
    IAutomationModule public immutable automation;
    IPoolV4 public immutable pool;
    
    constructor(address _automation, address _pool) {
        automation = IAutomationModule(_automation);
        pool = IPoolV4(_pool);
    }
    
    /**
     * @notice 设置健康因子保护
     * @param triggerHF 触发健康因子
     * @param repayAsset 偿还资产
     * @param repayAmount 偿还数量
     */
    function setupProtection(
        uint256 triggerHF,
        address repayAsset,
        uint256 repayAmount
    ) external returns (uint256 ruleId) {
        IAutomationModule.AutomationRule memory rule = IAutomationModule.AutomationRule({
            triggerType: IAutomationModule.TriggerType.HEALTH_FACTOR,
            triggerValue: triggerHF,
            actionType: IAutomationModule.ActionType.REPAY,
            actionAsset: repayAsset,
            actionAmount: repayAmount,
            isActive: true
        });
        
        return automation.createRule(rule);
    }
    
    /**
     * @notice 设置止损
     * @param asset 监控资产
     * @param stopLossPrice 止损价格
     * @param withdrawAmount 提取数量
     */
    function setupStopLoss(
        address asset,
        uint256 stopLossPrice,
        uint256 withdrawAmount
    ) external returns (uint256 ruleId) {
        IAutomationModule.AutomationRule memory rule = IAutomationModule.AutomationRule({
            triggerType: IAutomationModule.TriggerType.PRICE,
            triggerValue: stopLossPrice,
            actionType: IAutomationModule.ActionType.WITHDRAW,
            actionAsset: asset,
            actionAmount: withdrawAmount,
            isActive: true
        });
        
        return automation.createRule(rule);
    }
}

定期再平衡

solidity
contract RebalanceAutomation {
    IAutomationModule public immutable automation;
    
    struct RebalanceConfig {
        address[] assets;
        uint256[] targetAllocations; // basis points
        uint256 rebalanceThreshold;  // 触发再平衡的偏差阈值
    }
    
    mapping(address => RebalanceConfig) public userConfigs;
    
    function setupRebalance(
        address[] calldata assets,
        uint256[] calldata allocations,
        uint256 threshold
    ) external {
        require(assets.length == allocations.length, "Length mismatch");
        
        uint256 totalAllocation;
        for (uint i = 0; i < allocations.length; i++) {
            totalAllocation += allocations[i];
        }
        require(totalAllocation == 10000, "Must equal 100%");
        
        userConfigs[msg.sender] = RebalanceConfig({
            assets: assets,
            targetAllocations: allocations,
            rebalanceThreshold: threshold
        });
    }
    
    function executeRebalance(address user) external {
        RebalanceConfig memory config = userConfigs[user];
        
        // 计算当前分配
        uint256[] memory currentAllocations = _calculateCurrentAllocations(
            user, 
            config.assets
        );
        
        // 检查是否需要再平衡
        bool needsRebalance = false;
        for (uint i = 0; i < config.assets.length; i++) {
            uint256 deviation = _abs(
                int256(currentAllocations[i]) - int256(config.targetAllocations[i])
            );
            if (deviation > config.rebalanceThreshold) {
                needsRebalance = true;
                break;
            }
        }
        
        require(needsRebalance, "Rebalance not needed");
        
        // 执行再平衡
        _executeRebalance(user, config, currentAllocations);
    }
    
    function _calculateCurrentAllocations(
        address user,
        address[] memory assets
    ) internal view returns (uint256[] memory) {
        // 实现分配计算逻辑
    }
    
    function _executeRebalance(
        address user,
        RebalanceConfig memory config,
        uint256[] memory currentAllocations
    ) internal {
        // 实现再平衡逻辑
    }
    
    function _abs(int256 x) internal pure returns (uint256) {
        return x >= 0 ? uint256(x) : uint256(-x);
    }
}

智能账户集成

ERC-4337 账户

solidity
pragma solidity ^0.8.20;

import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
import {BaseAccount} from "@account-abstraction/contracts/core/BaseAccount.sol";

contract AaveSmartAccount is BaseAccount {
    IPoolV4 public immutable aavePool;
    IEntryPoint private immutable _entryPoint;
    address public owner;
    
    constructor(address entryPoint_, address pool_, address owner_) {
        _entryPoint = IEntryPoint(entryPoint_);
        aavePool = IPoolV4(pool_);
        owner = owner_;
    }
    
    function entryPoint() public view override returns (IEntryPoint) {
        return _entryPoint;
    }
    
    function _validateSignature(
        UserOperation calldata userOp,
        bytes32 userOpHash
    ) internal view override returns (uint256 validationData) {
        bytes32 hash = keccak256(
            abi.encodePacked("\x19Ethereum Signed Message:\n32", userOpHash)
        );
        
        (bytes32 r, bytes32 s, uint8 v) = _splitSignature(userOp.signature);
        address signer = ecrecover(hash, v, r, s);
        
        if (signer != owner) {
            return SIG_VALIDATION_FAILED;
        }
        return 0;
    }
    
    /**
     * @notice 执行 Aave 操作
     */
    function executeAaveOperation(
        uint8 operationType,
        address asset,
        uint256 amount
    ) external {
        require(msg.sender == address(_entryPoint) || msg.sender == owner, "Unauthorized");
        
        if (operationType == 0) {
            // Supply
            IERC20(asset).approve(address(aavePool), amount);
            aavePool.supply(asset, amount, address(this), 0);
        } else if (operationType == 1) {
            // Withdraw
            aavePool.withdraw(asset, amount, address(this));
        } else if (operationType == 2) {
            // Borrow
            aavePool.borrow(asset, amount, 2, 0, address(this));
        } else if (operationType == 3) {
            // Repay
            IERC20(asset).approve(address(aavePool), amount);
            aavePool.repay(asset, amount, 2, address(this));
        }
    }
    
    /**
     * @notice 批量执行 Aave 操作
     */
    function executeBatchAaveOperations(
        IPoolV4.BatchOperation[] calldata operations
    ) external {
        require(msg.sender == address(_entryPoint) || msg.sender == owner, "Unauthorized");
        
        // 批准所有需要的代币
        for (uint i = 0; i < operations.length; i++) {
            if (operations[i].operationType == 0 || operations[i].operationType == 3) {
                IERC20(operations[i].asset).approve(
                    address(aavePool), 
                    operations[i].amount
                );
            }
        }
        
        aavePool.executeBatch(operations);
    }
    
    function _splitSignature(bytes memory sig) internal pure returns (
        bytes32 r, bytes32 s, uint8 v
    ) {
        require(sig.length == 65, "Invalid signature length");
        assembly {
            r := mload(add(sig, 32))
            s := mload(add(sig, 64))
            v := byte(0, mload(add(sig, 96)))
        }
    }
}

TypeScript SDK

基础使用

typescript
import { AaveV4SDK, BatchOperation } from '@aave/v4-sdk';
import { ethers } from 'ethers';

// 初始化 SDK
const provider = new ethers.providers.JsonRpcProvider('YOUR_RPC_URL');
const signer = new ethers.Wallet('YOUR_PRIVATE_KEY', provider);

const aave = new AaveV4SDK({
    provider,
    signer,
    chainId: 1,
});

// 供应资产
async function supply() {
    const tx = await aave.supply({
        asset: 'USDC',
        amount: '1000',
    });
    await tx.wait();
    console.log('Supply successful:', tx.hash);
}

// 批量操作
async function batchOperations() {
    const operations: BatchOperation[] = [
        { type: 'supply', asset: 'USDC', amount: '1000' },
        { type: 'supply', asset: 'WETH', amount: '1' },
        { type: 'borrow', asset: 'DAI', amount: '500' },
    ];
    
    const tx = await aave.executeBatch(operations);
    await tx.wait();
    console.log('Batch successful:', tx.hash);
}

// 创建自动化规则
async function setupAutomation() {
    const ruleId = await aave.automation.createRule({
        triggerType: 'healthFactor',
        triggerValue: 1.2,
        actionType: 'repay',
        actionAsset: 'USDC',
        actionAmount: '500',
    });
    console.log('Rule created:', ruleId);
}

// 获取用户数据
async function getUserData() {
    const userAddress = await signer.getAddress();
    const data = await aave.getUserAccountData(userAddress);
    
    console.log('Total Collateral:', data.totalCollateralBase);
    console.log('Total Debt:', data.totalDebtBase);
    console.log('Health Factor:', data.healthFactor);
}

高级功能

typescript
// 监听事件
aave.on('Supply', (reserve, user, amount) => {
    console.log(`${user} supplied ${amount} of ${reserve}`);
});

aave.on('Borrow', (reserve, user, amount) => {
    console.log(`${user} borrowed ${amount} of ${reserve}`);
});

// 获取流动性数据
async function getLiquidityData() {
    const liquidity = await aave.liquidityLayer.getTotalLiquidity('USDC');
    console.log('Total USDC Liquidity:', liquidity);
    
    const allocation = await aave.liquidityLayer.getAllocation('USDC');
    console.log('Liquidity Allocation:', allocation);
}

// 模拟交易
async function simulateTransaction() {
    const simulation = await aave.simulate.supply({
        asset: 'USDC',
        amount: '1000',
    });
    
    console.log('Estimated Gas:', simulation.gasEstimate);
    console.log('New Health Factor:', simulation.newHealthFactor);
}

测试

单元测试

typescript
import { expect } from 'chai';
import { ethers } from 'hardhat';

describe('Aave V4 Integration', () => {
    let pool: any;
    let usdc: any;
    let user: any;
    
    beforeEach(async () => {
        [user] = await ethers.getSigners();
        
        // 部署或连接合约
        pool = await ethers.getContractAt('IPoolV4', POOL_ADDRESS);
        usdc = await ethers.getContractAt('IERC20', USDC_ADDRESS);
    });
    
    it('should supply assets', async () => {
        const amount = ethers.utils.parseUnits('1000', 6);
        
        await usdc.approve(pool.address, amount);
        await pool.supply(usdc.address, amount, user.address, 0);
        
        const accountData = await pool.getUserAccountData(user.address);
        expect(accountData.totalCollateralBase).to.be.gt(0);
    });
    
    it('should execute batch operations', async () => {
        const supplyAmount = ethers.utils.parseUnits('1000', 6);
        
        await usdc.approve(pool.address, supplyAmount);
        
        const operations = [
            {
                operationType: 0,
                asset: usdc.address,
                amount: supplyAmount,
                interestRateMode: 0,
                onBehalfOf: user.address,
            },
        ];
        
        await pool.executeBatch(operations);
        
        const accountData = await pool.getUserAccountData(user.address);
        expect(accountData.totalCollateralBase).to.be.gt(0);
    });
});

最佳实践

批量操作

solidity
// ❌ 多次单独调用
pool.supply(asset1, amount1, user, 0);
pool.supply(asset2, amount2, user, 0);
pool.borrow(asset3, amount3, 2, 0, user);

// ✅ 使用批量操作
BatchOperation[] memory ops = new BatchOperation[](3);
ops[0] = BatchOperation(0, asset1, amount1, 0, user);
ops[1] = BatchOperation(0, asset2, amount2, 0, user);
ops[2] = BatchOperation(2, asset3, amount3, 2, user);
pool.executeBatch(ops);

自动化保护

solidity
// 设置健康因子保护,避免清算
automation.createRule(AutomationRule({
    triggerType: TriggerType.HEALTH_FACTOR,
    triggerValue: 1.2e18,
    actionType: ActionType.REPAY,
    actionAsset: USDC,
    actionAmount: 1000e6,
    isActive: true
}));

流动性检查

typescript
// 在执行大额操作前检查流动性
const liquidity = await aave.liquidityLayer.getTotalLiquidity('USDC');
if (liquidity < requiredAmount) {
    console.warn('Insufficient liquidity');
}

注意事项

  • 批量操作中任一步骤失败会导致整体回滚
  • 自动化规则需要预先授权足够的代币额度
  • 大额操作前务必检查流动性和滑点

基于 MIT 许可发布