HardhatDeFi
15,000 USDC
View results
Submission Details
Severity: low
Valid

Protocol is unusable

Summary

Inverted constructor input values of AaveDivaWrapper and AaveDivaWrapperCore contracts will cause frequent reverts and deem the protocol unusable

Vulnerability Details

The AaveDivaWrapper sets in it's constructor the state of the core contract as well:

constructor(address _aaveV3Pool, address _diva, address _owner) AaveDIVAWrapperCore(_aaveV3Pool, _diva, _owner) {}

Note the order of the passed in input values:

  1. Address of the aave pool

  2. Address of the diva protocol diamond

  3. Address of the owner

Now lets take a look at AaveDivaWrapperCore contract's storage and costructor:

abstract contract AaveDIVAWrapperCore is IAaveDIVAWrapper, Ownable2Step {
using SafeERC20 for IERC20Metadata;
/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/
// Addresses of DIVA Protocol and Aave V3 (Pool contract) that this contract interacts with.
// Set in the constructor and retrievable via `getContractDetails`.
address private immutable _diva; //AUDIT - these declarations should be inverted. _aaveV3Pool first
address private immutable _aaveV3Pool; // Pool contract address
constructor(address diva_, address aaveV3Pool_, address owner_) Ownable(owner_) {
//...............}

Notice the order of the inputs here:

  1. Address of the DIVA diamond

  2. Address of the aave pool

  3. Address of the owner

So now what happens is that pool functions will be called on the Diva protocol and vice versa. Since non existent functions are called on these contracts, a revert will follow.

This issue deems the whole wrapper project unusable, because as stated in the known issues:
The AaveDIVAWrapper contract becomes useable only after the owner has registered collateral tokens post contract deployment.

registerCollateralToken will always revert in the core contract at line80 in its call to _getAToken

The below PoC shows that when execution gets to _getAToken(collateralToken), instead of calling getReserveData on the aave pool, it is called on the diva protocol and execution reverts with the signature 0x5416eb98 (check here that this signature corresponds to FunctionNotFound(bytes4)

PoC

Below is the output from the console, when running the testRegisterCollateralWorks

[27007] TestAaveDivaWrapper::testRegisterCollateralWorks()
├─ [0] VM::prank(owner: [0x7c8999dC9a822c1f0Df42023113EDB4FDd543266])
│ └─ ← [Return]
├─ [14903] AaveDIVAWrapper::registerCollateralToken(0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8)
│ ├─ [2338] 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D::getReserveData(0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8) [staticcall]
│ │ └─ ← [Revert] custom error 0x5416eb98: 35ea6a7500000000000000000000000000000000000000000000000000000000
│ └─ ← [Revert] custom error 0x5416eb98: 35ea6a7500000000000000000000000000000000000000000000000000000000
└─ ← [Revert] custom error 0x5416eb98: 35ea6a7500000000000000000000000000000000000000000000000000000000
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 2.11s (346.58ms CPU time)

It is visible that getReserveData gets called on the DIVA protocol address (0x2C9c47E7d254e493f02acfB410864b9a86c28e1D - check the test file state to compare the addresses) instead of the pool and execution reverts with 0x5416eb98 - FunctionNotFound(bytes4).

Impact

registerCollateralToken will always revert because of wrong input parameter order in the cosntructor of the core contract, hence the protocol is unusable and will need to get redeployed at the expense of the gas used for the first deploy.

Tools Used

Foundry

Recommendations

Invert the order in which _diva and _aaveV3Pool are passed in to the constructor of the core. Also for better verbosity invert their immutable declarations above the constructor in the core contract (this is just for better verbosity, as immutables are stored directly in the bytecode) After this the contract should look like this:

abstract contract AaveDIVAWrapperCore is IAaveDIVAWrapper, Ownable2Step {
using SafeERC20 for IERC20Metadata;
/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/
// Addresses of DIVA Protocol and Aave V3 (Pool contract) that this contract interacts with.
// Set in the constructor and retrievable via `getContractDetails`.
address private immutable _aaveV3Pool;
address private immutable _diva;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(address aaveV3Pool_, address diva_, address owner_) Ownable(owner_) {
Updates

Lead Judging Commences

bube Lead Judge 5 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Constructor arguments mismatch

Support

FAQs

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