Native Credit Delegation(CD) 是 Aave v2 中的一项新功能。它允许储户将资金存入协议中以赚取利息,并将借款权(即他们的信用)委托给其他用户。贷款的执行及其条款由存款人和借款人商定,可以通过法律协议在链下或智能合约在链上达成。

这能够使得:

  • 存款人 depositor(委托人 delegator)在他们已经从协议中获得的收益之上赚取额外的收益
  • 借款人 borrowers(受托人 delegatees)获得无抵押贷款

按照以下步骤创建我们的第一个信用委托。

Approving the delegation

approveDelegation()方法必须由 depositor (delegator) 调用,批准 borrower (delegatee) 一定金额。

这是针对需要委托的每个 Debt token 完成的。

depositor (delegator) 不需要已经在协议中存入资金即可 approveDelegation()。但是,在 borrower (delegatee) 执行 borrow()之前,协议中必须有足够的抵押物分配给 depositor (delegator)

// Import relevant interfaces
import './IAaveProtocolDataProvider.sol';
import './IDebtToken.sol';

// ... beginning of your contract. Constructors etc...

// Within a relevant function in your contract:

    // Get the Protocol Data Provider
    IAaveProtocolDataProvider provider = IAaveProtocolDataProvider(address(INSERT_DATA_PROVIDER_ADDRESS));
  
    // Get the relevant debt token address
    (, address stableDebtTokenAddress, address variableDebtTokenAddress) = provider.getReserveTokensAddresses(INSERT_ASSET_ADDRESS);

    // Relevant details for credit delegation
    address borrower = address(INSERT_BORROWER_ADDRESS);
    uint256 amountInWei = INSERT_DELEGATED_AMOUNT;
    
    // For stable debt tokens
    IDebtToken(stableDebtTokenAddress).approveDelegation(borrower, amountInWei);
    
    // For variable debt tokens
    IDebtToken(variableDebtTokenAddress).approveDelegation(borrower, amountInWei);
// Import relevant ABIs
import IAaveProtocolDataProviderABI from './IAaveProtocolDataProviderAbi.json'
import IDebtTokenABI from './IDebtToken.json'

// ... beginning of your code

// Within a relevant function in your code:

    // Get the Aave Protocol Data Provider
    const provider = new web3.eth.Contract(IAaveProtocolDataProviderABI, INSERT_DATA_PROVIDER_ADDRESS)

    // Get the relevant debt token address
    const tokenDetails = await provider.methods
        .getReserveTokensAddresses(INSERT_ASSET_ADDRESS)
        .call()
        .catch((e) => {
            throw Error(`Error getting token details: ${e.message}`)
        })
    
    // Relevant details for credit delegation
    const borrower = INSERT_BORROWER_ADDRESS
    const amountInWei = INSERT_DELEGATED_AMOUNT
    
    // For stable debt tokens
    const stableDebtContract = new web3.eth.Contract(IDebtTokenABI, tokenDetails.stableDebtTokenAddress)
    await stableDebtContract.methods
        .approveDelegation(borrower, amountInWei)
        .send()
        .catch((e) => {
            throw Error(`Error approving delegation: ${e.message}`)
        })
    
    // For variable debt tokens
    const variableDebtContract = new web3.eth.Contract(IDebtTokenABI, tokenDetails.variableDebtTokenAddress)
    await variableDebtContract.methods
        .approveDelegation(borrower, amountInWei)
        .send()
        .catch((e) => {
            throw Error(`Error approving delegation: ${e.message}`)
        })

借入信用 Borrowing the credit

borrower (delegatee) 最终使用参数 onBehalfOf中的 depositor (delegator) 地址,调用LengdingPool上的 borrow()方法。

borrower 的可用信用额度会减少借款金额。

// Import relevant interfaces
import './IAddressesProvider.sol';
import './ILendingPool.sol';

// ... beginning of your contract. Constructors etc...

// Within a relevant function in your contract:

    // Get the latest LendingPool contract for the relevant market
    IAddressesProvider provider = IAddressesProvider(address(INSERT_ADDRESSES_PROVIDER_ADDRESS));
    ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
    
    // Borrow the relevant amount
    address assetToBorrow = address(INSERT_ASSET_ADDRESS); // E.g. the address for Dai
    uint256 amountToBorrowInWei = INSERT_AMOUNT; // must be equal to or less than the amount delegated to the borrower
    uint256 interestRateMode = INSERT_INTEREST_RATE_MODE; // must be of the same type as the debt token that is delegated. I.e. stable = 1, variable = 2.
    uint16 referralCode = INSERT_REFERRAL_CODE;
    address delegatorAddress = INSERT_DELEGATOR_ADDRESS;
    
    lendingPool.borrow(assetToBorrow, amountToBorrowInWei, interestRateMode, referralCode, delegatorAddress);
// Import relevant ABIs
import IAddressProviderABI from './IAddressesProviderAbi.json'
import ILendingPoolABI from './ILendingPool.json'

// ... beginning of your code

// Within a relevant function in your code:

    // Get the latest LendingPool contract for the relevant market
    const provider = new web3.eth.Contract(IAddressProviderABI, INSERT_ADDRESSES_PROVIDER_ADDRESS)
    const lendingPoolAddress = await provider.methods
        .getLendingPool()
        .call()
        .catch((e) => {
            throw Error(`Error getting lendingPool address: ${e.message}`)
        })
    const lendingPoolContract = new web3.eth.Contract(ILendingPoolABI, lendingPoolAddress)
    
    // Borrow the relevant amount
    const assetToBorrow = INSERT_ASSET_ADDRESS; // E.g. the address for Dai
    const amountToBorrowInWei = INSERT_AMOUNT; // must be equal to or less than the amount delegated to the borrower
    const interestRateMode = INSERT_INTERST_RATE_MODE; // must be of the same type as the debt token that is delegated. I.e. stable = 1, variable = 2.
    const referralCode = INSERT_REFERRAL_CODE;
    const delegatorAddress = INSERT_DELEGATOR_ADDRESS;
    
    await lendingPoolContract.methods
        .borrow(
            assetToBorrow,
            amountToBorrowInWei,
            interestRateMode,
            referralCode,
            delegatorAddress
        )
        .send()
        .catch((e) => {
            throw Error(`Error borrowing: ${e.message}`)
        })

偿还贷款 Repaying the credit

borrower (delegatee) 也可以随时调用 repay()来偿还它们的无抵押贷款,通过将 depositor (delegator) 的地址作为 onBehalfOf传递。

还款后,borrower 的可用信用没有变化

// Import relevant interfaces
import './IAddressesProvider.sol';
import './ILendingPool.sol';
import './IERC20.sol';

// ... beginning of your contract. Constructors etc...

// Within a relevant function in your contract:

// Get the latest LendingPool contract for the relevant market
IAddressesProvider provider = IAddressesProvider(address(INSERT_ADDRESSES_PROVIDER_ADDRESS));
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());

// Approve the asset to be repaid  
address assetToRepay = address(INSERT_ASSET_ADDRESS); // E.g. the address for Dai
uint256 amountToRepayInWei = INSERT_AMOUNT; // must be equal to or less than the amount delegated to the borrower

IERC20(assetToRepay).approve(address(lendingPool), amounToRepayInWei);

// Repay the relevant amount
uint256 interestRateMode = INSERT_INTEREST_RATE_MODE; // must be of the same type as the debt token that is delegated. I.e. stable = 1, variable = 2.
address delegatorAddress = INSERT_DELEGATOR_ADDRESS;

lendingPool.repay(assetToRepay, amountToRepayInWei, interestRateMode, delegatorAddress);
    
// Import relevant ABIs
import IAddressProviderABI from './IaddressesProviderAbi.json'
import ILendingPoolABI from './ILendingPool.json'
import IERC20ABI from './IERC20.json'

// ... beginning of your code

// Within a relevant function in your code:

// Get the latest LendingPool contract for the relevant market
const provider = new web3.eth.Contract(IAddressProviderABI, INSERT_ADDRESSES_PROVIDER_ADDRESS)
const lendingPoolAddress = await provider.methods
    .getLendingPool()
    .call()
    .catch((e) => {
        throw Error(`Error getting lendingPool address: ${e.message}`)
    })
const lendingPoolContract = new web3.eth.Contract(ILendingPoolABI, lendingPoolAddress)

const assetToRepay = INSERT_ASSET_ADDRESS; // E.g. the address for Dai
const amountToRepayInWei = INSERT_AMOUNT; // must be equal to or less than the amount delegated to the borrower
const delegatorAddress = INSERT_DELEGATOR_ADDRESS;

// Approve the asset to be repaid
const assetContract = new web3.eth.Contract(IERC20ABI, assetToRepay)
await assetContract.methods
  .approve(provider, amountToRepayInWei)
  .send()
  .catch((e) => {
    throw Error(`Error approving asset allowance: ${e.message}`)
  })

const lendingPoolContract = new web3.eth.Contract(ILendingPoolABI, lendingPoolAddress)
await lendingPoolContract.methods
  .repay(
			assetToRepay, 
			amountToRepayInWei, 
			delegatorAddress
	)
  .send()
  .catch((e) => {
    throw Error(`Error repaying: ${e.message}`)
  })

增加信用委托 Increasing the credit delegation

要增加或减少借款人的可用信用,应再次调用 approveDelegation()方法。这将在(不包括)未偿还借款之上设置新的可供借款金额。

调用后设置的金额是允许借款的上限,但不包括当前未偿还的借款金额。例如,如果借款人已经有未偿还的债务,新的授权额度是基于此之上增加的,并不会覆盖现有的债务。

这是针对每个需要修改的 Debt token 完成的。

// Import relevant interfaces
import './IAaveProtocolDataProvider.sol';
import './IDebtToken.sol';

// ... beginning of your contract. Constructors etc...

// Within a relevant function in your contract:

    // Get the Protocol Data Provider
    IAaveProtocolDataProvider provider = IAaveProtocolDataProvider(address(INSERT_DATA_PROVIDER_ADDRESS));
  
    // Get the relevant debt token address
    (, address stableDebtTokenAddress, address variableDebtTokenAddress) = provider.getReserveTokensAddresses(INSERT_ASSET_ADDRESS);

    // Relevant details for credit delegation
    address borrower = address(INSERT_BORROWER_ADDRESS);
    uint256 amountInWei = INSERT_DELEGATED_AMOUNT; // This is the total amount to be delegated (not just the increase)
    
    // For stable debt tokens
    IDebtToken(stableDebtTokenAddress).approveDelegation(borrower, amountInWei);
    
    // For variable debt tokens
    IDebtToken(variableDebtTokenAddress).approveDelegation(borrower, amountInWei);
// Import relevant ABIs
import IAaveProtocolDataProviderABI from './IAaveProtocolDataProviderAbi.json'
import IDebtTokenABI from './IDebtToken.json'

// ... beginning of your code

// Within a relevant function in your code:

    // Get the Aave Protocol Data Provider
    const provider = new web3.eth.Contract(IAaveProtocolDataProviderABI, INSERT_DATA_PROVIDER_ADDRESS)

    // Get the relevant debt token address
    const tokenDetails = await provider.methods
        .getReserveTokensAddresses(INSERT_ASSET_ADDRESS)
        .call()
        .catch((e) => {
            throw Error(`Error getting token details: ${e.message}`)
        })
    
    // Relevant details for credit delegation
    const borrower = INSERT_BORROWER_ADDRESS
    const amountInWei = INSERT_DELEGATED_AMOUNT // This is the total amount to be delegated (not just the increase)
    
    // For stable debt tokens
    const stableDebtContract = new web3.eth.Contract(IDebtTokenABI, tokenDetails.stableDebtTokenAddress)
    await stableDebtContract.methods
        .approveDelegation(borrower, amountInWei)
        .send()
        .catch((e) => {
            throw Error(`Error approving delegation: ${e.message}`)
        })
    
    // For variable debt tokens
    const variableDebtContract = new web3.eth.Contract(IDebtTokenABI, tokenDetails.variableDebtTokenAddress)
    await variableDebtContract.methods
        .approveDelegation(borrower, amountInWei)
        .send()
        .catch((e) => {
            throw Error(`Error approving delegation: ${e.message}`)
        })

检查委托的金额 checking the amount delegated

要检查用户的当前限额,只需调用 borrowAllowance()并传入 depositor (delegator) 和 borrower (delegatee) 地址

这是针对 delegate 的每个 Debt Token 完成的。

// Import relevant interfaces
import './IAaveProtocolDataProvider.sol';
import './IDebtToken.sol';

// ... beginning of your contract. Constructors etc...

// Within a relevant function in your contract:

    // Get the Protocol Data Provider
    IAaveProtocolDataProvider provider = IAaveProtocolDataProvider(address(INSERT_DATA_PROVIDER_ADDRESS));
  
    // Get the relevant debt token address
    (, address stableDebtTokenAddress, address variableDebtTokenAddress) = provider.getReserveTokensAddresses(INSERT_ASSET_ADDRESS);

    // Relevant details for credit delegation
    address delegator = address(INSERT_DEPOSITOR_ADDRESS)
    address delegatee = address(INSERT_BORROWER_ADDRESS);
    
    // For stable debt tokens
    uint256 stableAllowance = IDebtToken(stableDebtTokenAddress).borrowAllowance(delegator, delegatee);
    
    // For variable debt tokens
    uint256 variableAllowance = IDebtToken(variableDebtTokenAddress).borrowAllowance(delegator, delegatee);
// Import relevant ABIs
import IAaveProtocolDataProviderABI from './IAaveProtocolDataProviderAbi.json'
import IDebtTokenABI from './IDebtToken.json'

// ... beginning of your code

// Within a relevant function in your code:

    // Get the Aave Protocol Data Provider
    const provider = new web3.eth.Contract(IAaveProtocolDataProviderABI, INSERT_DATA_PROVIDER_ADDRESS)

    // Get the relevant debt token address
    const tokenDetails = await provider.methods
        .getReserveTokensAddresses(INSERT_ASSET_ADDRESS)
        .call()
        .catch((e) => {
            throw Error(`Error getting token details: ${e.message}`)
        })
    
    // Relevant details for credit delegation
    const delegator = INSERT_DEPOSITOR_ADDRESS
    const delegatee = INSERT_BORROWER_ADDRESS
    
    // For stable debt tokens
    const stableDebtContract = new web3.eth.Contract(IDebtTokenABI, tokenDetails.stableDebtTokenAddress)
    const stableAllowance = await stableDebtContract.methods
        .borrowAllowance(delegator, delegatee)
        .call()
        .catch((e) => {
            throw Error(`Error approving delegation: ${e.message}`)
        })
    
    // For variable debt tokens
    const variableDebtContract = new web3.eth.Contract(IDebtTokenABI, tokenDetails.variableDebtTokenAddress)
    const variableAllowance = await variableDebtContract.methods
        .borrowAllowance(delegator, delegatee)
        .call()
        .catch((e) => {
            throw Error(`Error approving delegation: ${e.message}`)
        })