First Flight #21: KittyFi

First Flight #21
Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: low
Valid

Collateral deposited won't earn additional yield when hits supply limitation in Aave pool

Summary

Additional collateral deposited in KittyPool will just serve as backing the KittyCoin but won't get extra yield when the supply limitation is hit in Aave pool causing user to mistakenly think their deposits earn them additional interest.

Vulnerability Details

User will be able to earn yield from their deposits only when meowntainer perform KittyValut:purrrCollateralToAave function. However, there is a supply limitation which is not clearly known to the end user. If the total supply handled in Aepool is exceeded, meowntainer will no longer be able to perform the KittyValut:purrrCollateralToAave function, resulting any extra collateral deposited to KittyPool that has yet to transfer to Aave pool won't be earning any yield.

Proof of Concept:
In test/KittyFiTest.t.sol, add usdc related setup and run test on test_audit_purrrCollateralToAave_supplyLimitation()

function setUp() external {
HelperConfig helperConfig = new HelperConfig();
config = helperConfig.getNetworkConfig();
weth = config.weth;
usdc = config.usdc;
deal(weth, user, AMOUNT);
deal(usdc, user, AMOUNT);
kittyPool = new KittyPool(meowntainer, config.euroPriceFeed, config.aavePool);
vm.startPrank(meowntainer);
kittyPool.meownufactureKittyVault(config.weth, config.ethUsdPriceFeed);
kittyPool.meownufactureKittyVault(config.usdc, config.ethUsdPriceFeed);
vm.stopPrank();
kittyCoin = KittyCoin(kittyPool.getKittyCoin());
wethVault = KittyVault(kittyPool.getTokenToVault(config.weth));
usdcVault = KittyVault(kittyPool.getTokenToVault(config.usdc));
}
function test_audit_purrrCollateralToAave_supplyLimitation() public {
uint256 toDeposit = 5 ether;
vm.startPrank(user);
IERC20(usdc).approve(address(usdcVault), toDeposit);
kittyPool.depawsitMeowllateral(usdc, toDeposit);
vm.stopPrank();
// first xfer of usdc from usdcVault to aavePool
vm.startPrank(meowntainer);
uint256 xferAmount = 1e14;
usdcVault.purrrCollateralToAave(xferAmount);
assert(usdcVault.getTotalMeowllateralInAave() > 0);
// second transfer of bigger amount from usdcVault to aavePool
uint256 xferBiggerAmount = 1e16;
vm.expectRevert();
usdcVault.purrrCollateralToAave(xferBiggerAmount);
vm.stopPrank();
}

The test will pass with forge test --via-ir --fork-url $SEPOLIA_RPC_URL --match-test test_audit_purrrCollateralToAave_supplyLimitation -vvvv

In the console, the followings will be displayed:

Ran 1 test for test/KittyFiTest.t.sol:KittyFiTest
[PASS] test_audit_purrrCollateralToAave_supplyLimitation() (gas: 479253)
Traces:
[479253] KittyFiTest::test_audit_purrrCollateralToAave_supplyLimitation()
├─ [0] VM::startPrank(user: [0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D])
│ └─ ← [Return]
├─ [24619] TestnetERC20::approve(KittyVault: [0xE84c9bd544D87642DD01E7415f2a54fc08061FB0], 5000000000000000000 [5e18])
│ ├─ emit Approval(owner: user: [0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D], spender: KittyVault: [0xE84c9bd544D87642DD01E7415f2a54fc08061FB0], value: 5000000000000000000 [5e18])
│ └─ ← [Return] true
.......
│ │ │ │ ├─ [3176] InitializableImmutableAdminUpgradeabilityProxy::getSupplyData() [staticcall]
│ │ │ │ │ ├─ [2615] StableDebtToken::getSupplyData() [delegatecall]
│ │ │ │ │ │ └─ ← [Return] 3246908447782 [3.246e12], 3249282345040 [3.249e12], 55884533678440988670555868 [5.588e25], 1722520872 [1.722e9]
│ │ │ │ │ └─ ← [Return] 3246908447782 [3.246e12], 3249282345040 [3.249e12], 55884533678440988670555868 [5.588e25], 1722520872 [1.722e9]
│ │ │ │ ├─ [924] InitializableImmutableAdminUpgradeabilityProxy::scaledTotalSupply() [staticcall]
│ │ │ │ │ ├─ [375] AToken::scaledTotalSupply() [delegatecall]
│ │ │ │ │ │ └─ ← [Return] 116924875644443 [1.169e14]
│ │ │ │ │ └─ ← [Return] 116924875644443 [1.169e14]
│ │ │ │ └─ ← [Revert] revert: 51
│ │ │ └─ ← [Revert] revert: 51
│ │ └─ ← [Revert] revert: 51
│ └─ ← [Revert] revert: 51
├─ [0] VM::stopPrank()
│ └─ ← [Return]
└─ ← [Return]

In the first transfer of 1e14 usdc, the process will go through and successfully move collateral to Aavepool. However, the second transfer of 1e16 usdc will revert with error code 51 which is related to ReserveLogic - Liquidity index overflows (doc). In the Aave protocol github repo related to ValidationLogic.sol(ref), there is a maximum supply for a given type of collateral which cannot be exceeded.

Impact

Any additional collateral deposited to KittyPool which exceeds the Aaeve supply limit, can't be moved to Aave to earn yield and just stay in the KittyVault serving solely as a backing to KittyCoin, deviating from the protocol statement to enable user to earn yield from their deposits.

Tools Used

Manual review with forge test

Recommendations

To implement control check on the collateral supply limit to Aave pool and additional functions enable both meowntainer and user to know the state of the current supply.

Updates

Lead Judging Commences

shikhar229169 Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Collateral deposited won't earn additional yield when hits supply limitation in Aave pool

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.