How to calculate AAVE yield on chain

I’m working on a project which involves tracking and withdrawing AAVE yield on chain while maintaining the original deposit balance. I’m confused as to how to accurately calculate AAVE yield at a specific point in time. My initial approach was to just save the deposited amount, and then calculate yield by:

Yield = aToken_balance - deposited_amount

But this doesn’t seem to work. I’ve found that after calculating this yield value, if we attempt to withdraw that value our resulting aToken balance will be off (either above or below) our initial deposit amount. I’m aware that aTokens have dynamic supply/balanceOf, but there must be a way to accurately calculate: “I have X money at this point in time”

I'm testing on a fork of the Polygon Mainnet, I'm wondering if it has something to do with my test environment (i.e. simulating time passing on a fork of mainnet where nobody is actually interacting with AAVE)? A test contract and Screenshots of the issue are below. Any insights are much appreciated.

``````pragma solidity ^0.8.4;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IPool.sol";

contract AaveTest2 {
IPool public aavePoolManager = IPool(0x794a61358D6845594F94dc1DB02A252b5b4814aD);
address public usdc = 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174;
address public ausdc = 0x625E7708f30cA75bfd92586e17077590C60eb4cD;

uint public totalStakedUSDC;
uint public totalStakedDAI;

constructor() {}

function aaveDepositUSDC(uint amount) public {
aavePoolManager.supply(usdc, amount, address(this), 0);
totalStakedUSDC += amount;
}

function calculateYieldUSDC() public view returns (uint) {
uint yield = IERC20(ausdc).balanceOf(address(this)) - totalStakedUSDC;
return yield;
}

function withdrawYieldUSDC() public {
uint yield = calculateYieldUSDC();
}

function withdrawUSDC(uint amount) public {
totalStakedUSDC -= amount;
}

function aaveDepositDAI(uint amount) public {
aavePoolManager.supply(dai, amount, address(this), 0);
totalStakedDAI += amount;
}

function calculateYieldDAI() public view returns (uint) {
return yield;
}

function withdrawYieldDAI() public {
uint yield = calculateYieldDAI();
}

function withdrawDAI(uint amount) public {
totalStakedDAI -= amount;
}
}
``````

If I remember correctly. Aave uses an index to track the value of your aToken.

Step 1, retreive the index

``````(, , , , , , ,uint256 liquidityIndex, , ) = IdataProvider.getReserveData(asset_address);
``````

This should return a number in ray

Step 2, retrieve your scaled balance

``````uint256 scaledBalance = AToken(asset_address).scaledBalanceOf(address(this));
``````

Step 3, do the maths to get your current value

``````uint256 value_now = (scaledBalance * liquidityIndex) * 1e18 / 1e27;
``````
• Exactly what I needed thank you!
– xde
Sep 29, 2022 at 16:29