Native Credit Delegation (CD) is a new feature in Aave v2. It allows a depositor to deposit funds in the protocol to earn interest, and delegate borrowing power (i.e. their credit) to other users. The enforcement of the loan and its terms are agreed upon between the depositor and borrowers, which can be either off-chain via legal agreements or on-chain via smart contracts.
This enables:
The depositor (delegator) to earn extra yield on top of the yield they already earn from the protocol,
The borrowers (delegatees) to access an uncollateralized loan.
Follow the below steps to create your first Credit Delegation.
In the following guide, we refer to borrower and delegatee. However credit delegation allows the delegation to multiple users, so it can also be read as borrowers and delegatees.
Approving the delegation
The approveDelegation() method must be called by the depositor (delegator), approving the borrower (delegatee) a certain amount.
This is done for each debt token that needs to be delegated.
The depositor (delegator) does not need to already have deposited funds in the protocol to approveDelegation(). However, before the borrower (delegatee) executes borrow(), there must be sufficient collateral assigned to the depositor (delegator) in the protocol.
// Import relevant interfacesimport'./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 tokensIDebtToken(stableDebtTokenAddress).approveDelegation(borrower, amountInWei);// For variable debt tokensIDebtToken(variableDebtTokenAddress).approveDelegation(borrower, amountInWei);
// Import relevant ABIsimport 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 Providerconstprovider=newweb3.eth.Contract(IAaveProtocolDataProviderABI,INSERT_DATA_PROVIDER_ADDRESS)// Get the relevant debt token addressconsttokenDetails=awaitprovider.methods.getReserveTokensAddresses(INSERT_ASSET_ADDRESS).call().catch((e) => {throwError(`Error getting token details: ${e.message}`) })// Relevant details for credit delegationconstborrower=INSERT_BORROWER_ADDRESSconstamountInWei=INSERT_DELEGATED_AMOUNT// For stable debt tokensconststableDebtContract=newweb3.eth.Contract(IDebtTokenABI,tokenDetails.stableDebtTokenAddress)awaitstableDebtContract.methods.approveDelegation(borrower, amountInWei).send().catch((e) => {throwError(`Error approving delegation: ${e.message}`) })// For variable debt tokensconstvariableDebtContract=newweb3.eth.Contract(IDebtTokenABI,tokenDetails.variableDebtTokenAddress)awaitvariableDebtContract.methods.approveDelegation(borrower, amountInWei).send().catch((e) => {throwError(`Error approving delegation: ${e.message}`) })
Borrowing the credit
The borrower (delegatee) calls the borrow() method on the LendingPool, using the depositor's (delegator's) address in final parameter onBehalfOf.
The borrower's available credit is reduced by the borrowed amount.
// Import relevant interfacesimport'./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 ABIsimport 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 marketconstprovider=newweb3.eth.Contract(IAddressProviderABI,INSERT_ADDRESSES_PROVIDER_ADDRESS)constlendingPoolAddress=awaitprovider.methods.getLendingPool().call().catch((e) => {throwError(`Error getting lendingPool address: ${e.message}`) })constlendingPoolContract=newweb3.eth.Contract(ILendingPoolABI, lendingPoolAddress)// Borrow the relevant amountconstassetToBorrow=INSERT_ASSET_ADDRESS; // E.g. the address for DaiconstamountToBorrowInWei=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.
constreferralCode=INSERT_REFERRAL_CODE;constdelegatorAddress=INSERT_DELEGATOR_ADDRESS;awaitlendingPoolContract.methods.borrow( assetToBorrow, amountToBorrowInWei, interestRateMode, referralCode, delegatorAddress ).send().catch((e) => {throwError(`Error borrowing: ${e.message}`) })
Repaying the credit
The borrower (delegatee) can also call repay() at anytime to repay their uncollateralized loan, passing in the depositor's (delegator's) address as the final parameter onBehalfOf.
There is no change to the borrower's available credit after repayment.
// Import relevant interfacesimport'./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 marketIAddressesProvider 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 Daiuint256 amountToRepayInWei =INSERT_AMOUNT; // must be equal to or less than the amount delegated to the borrowerIERC20(assetToRepay).approve(address(lendingPool), amounToRepayInWei);// Repay the relevant amountuint256 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 ABIsimport 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 marketconstprovider=newweb3.eth.Contract(IAddressProviderABI,INSERT_ADDRESSES_PROVIDER_ADDRESS)constlendingPoolAddress=awaitprovider.methods.getLendingPool().call().catch((e) => {throwError(`Error getting lendingPool address: ${e.message}`) })constlendingPoolContract=newweb3.eth.Contract(ILendingPoolABI, lendingPoolAddress)constassetToRepay=INSERT_ASSET_ADDRESS; // E.g. the address for DaiconstamountToRepayInWei=INSERT_AMOUNT; // must be equal to or less than the amount delegated to the borrowerconstdelegatorAddress=INSERT_DELEGATOR_ADDRESS;// Approve the asset to be repaidconstassetContract=newweb3.eth.Contract(IERC20ABI, assetToRepay)awaitassetContract.methods.approve(provider, amountToRepayInWei).send().catch((e) => {throwError(`Error approving asset allowance: ${e.message}`) })constlendingPoolContract=newweb3.eth.Contract(ILendingPoolABI, lendingPoolAddress)awaitlendingPoolContract.methods.repay( assetToRepay, amountToRepayInWei, delegatorAddress ).send().catch((e) => {throwError(`Error repaying: ${e.message}`) })
Increasing the credit delegation
To increase or decrease a borrower's available credit, the approveDelegation() method should be called again. This sets that new amount available to borrow on top of (not including) outstanding borrows.
This is done for each debt token that requires a modification.
// Import relevant interfacesimport'./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 tokensIDebtToken(stableDebtTokenAddress).approveDelegation(borrower, amountInWei);// For variable debt tokensIDebtToken(variableDebtTokenAddress).approveDelegation(borrower, amountInWei);
// Import relevant ABIsimport 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 Providerconstprovider=newweb3.eth.Contract(IAaveProtocolDataProviderABI,INSERT_DATA_PROVIDER_ADDRESS)// Get the relevant debt token addressconsttokenDetails=awaitprovider.methods.getReserveTokensAddresses(INSERT_ASSET_ADDRESS).call().catch((e) => {throwError(`Error getting token details: ${e.message}`) })// Relevant details for credit delegationconstborrower=INSERT_BORROWER_ADDRESSconstamountInWei=INSERT_DELEGATED_AMOUNT// This is the total amount to be delegated (not just the increase)// For stable debt tokensconststableDebtContract=newweb3.eth.Contract(IDebtTokenABI,tokenDetails.stableDebtTokenAddress)awaitstableDebtContract.methods.approveDelegation(borrower, amountInWei).send().catch((e) => {throwError(`Error approving delegation: ${e.message}`) })// For variable debt tokensconstvariableDebtContract=newweb3.eth.Contract(IDebtTokenABI,tokenDetails.variableDebtTokenAddress)awaitvariableDebtContract.methods.approveDelegation(borrower, amountInWei).send().catch((e) => {throwError(`Error approving delegation: ${e.message}`) })
Checking the amount delegated
To check the current allowance of a user, simply call borrowAllowance() passing in the depositor (delegator) and borrower (delegatee) addresses.
This is done for each debt token that is delegated.
// Import relevant interfacesimport'./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 ABIsimport 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 Providerconstprovider=newweb3.eth.Contract(IAaveProtocolDataProviderABI,INSERT_DATA_PROVIDER_ADDRESS)// Get the relevant debt token addressconsttokenDetails=awaitprovider.methods.getReserveTokensAddresses(INSERT_ASSET_ADDRESS).call().catch((e) => {throwError(`Error getting token details: ${e.message}`) })// Relevant details for credit delegationconstdelegator=INSERT_DEPOSITOR_ADDRESSconstdelegatee=INSERT_BORROWER_ADDRESS// For stable debt tokensconststableDebtContract=newweb3.eth.Contract(IDebtTokenABI,tokenDetails.stableDebtTokenAddress)conststableAllowance=awaitstableDebtContract.methods.borrowAllowance(delegator, delegatee).call().catch((e) => {throwError(`Error approving delegation: ${e.message}`) })// For variable debt tokensconstvariableDebtContract=newweb3.eth.Contract(IDebtTokenABI,tokenDetails.variableDebtTokenAddress)constvariableAllowance=awaitvariableDebtContract.methods.borrowAllowance(delegator, delegatee).call().catch((e) => {throwError(`Error approving delegation: ${e.message}`) })