Summary
The _aaveV3Pool
address and _diva
address received by the AaveDIVAWrapper
contract and the AaveDIVAWrapperCore
constructor are inconsistent, resulting in the _diva
address and _aaveV3Pool
address set in the AaveDIVAWrapperCore
contract being reversed, and the contract cannot work properly.
Vulnerability Details
The constructor of the AaveDIVAWrapper
contract is implemented as follows:
constructor(address _aaveV3Pool, address _diva, address _owner) AaveDIVAWrapperCore(_aaveV3Pool, _diva, _owner) {}
Here the AaveDIVAWrapper
contract constructor receives the following parameters in order:
_aaveV3Pool
_diva
_owner
And it is also passed to the constructor of the AaveDIVAWrapperCore
contract in this order.
However, the AaveDIVAWrapperCore constructor code is as follows:
constructor(address diva_, address aaveV3Pool_, address owner_) Ownable(owner_) {
if (diva_ == address(0) || aaveV3Pool_ == address(0)) {
revert ZeroAddress();
}
_diva = diva_;
_aaveV3Pool = aaveV3Pool_;
}
However, the order of parameters received by the constructor of the AaveDIVAWrapperCore contract is:
diva_
aaveV3Pool_
owner_
This will cause the diva_
address and aaveV3Pool_
address to be reversed in the AaveDIVAWrapper
contract and AaveDIVAWrapperCore
.
Impact
In this case, all function calls to the _diva
address in the AaveDIVAWrapperCore
contract actually call functions of aaveV3Pool_
, and all function calls to the aaveV3Pool_
address actually call functions of _diva
. This will revert and cause all related functions of the contract to be unable to work properly.
Tools Used
Foundry
POC
import "forge-std/Test.sol";
import "../src/AaveDIVAWrapper.sol";
import "forge-std/console2.sol";
contract AuditAaveDIVAWrapper is Test {
address aave_v3_pool_eth;
address diva_addr_eth;
address owner;
AaveDIVAWrapper public aave_diva_wrapper;
function setUp() public {
vm.createSelectFork("https://rpc.ankr.com/eth");
aave_v3_pool_eth = 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2;
diva_addr_eth = 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D;
owner = makeAddr("owner");
console2.log("in setUp function, aave_v3_pool_eth: ", aave_v3_pool_eth);
console2.log("in setUp function, diva_addr_eth: ", diva_addr_eth);
console2.log("------");
aave_diva_wrapper = new AaveDIVAWrapper(aave_v3_pool_eth, diva_addr_eth, owner);
}
function test_poc1() public{
address diva;
address aaveV3Pool;
(diva, aaveV3Pool, ) = aave_diva_wrapper.getContractDetails();
console2.log("in getContractDetails function, diva_addr_eth: ",diva);
console2.log("in getContractDetails function, aave_v3_pool_eth: ",aaveV3Pool);
}
}
cd 2025-01-diva/contracts
forge init --force
forge install openzeppelin/openzeppelin-contracts --no-commit
forge install openzeppelin/openzeppelin-contracts-upgradeable --no-commit
cd test/
# Save the above solidity code to the Audit.t.sol file under test
forge test --mt "test_poc1" -vvv
Ran 1 test for test/AuditAaveDIVAWrapper.t.sol:AuditAaveDIVAWrapper
[PASS] test_poc1() (gas: 11923)
Logs:
in setUp function, aave_v3_pool_eth: 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2
in setUp function, diva_addr_eth: 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D
------
in getContractDetails function, diva_addr_eth: 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2
in getContractDetails function, aave_v3_pool_eth: 0x2C9c47E7d254e493f02acfB410864b9a86c28e1D
Recommendations
In the constructor of the AaveDIVAWrapperCore
contract, just change the order of _aaveV3Pool
and _diva
:
@@ -49,7 +49,7 @@ abstract contract AaveDIVAWrapperCore is IAaveDIVAWrapper, Ownable2Step {
* @param owner_ Address of the owner for the contract, who will be entitled to claim the yield.
* Retrievable via Ownable's `owner()` function or this contract's `getContractDetails` functions.
*/
- constructor(address diva_, address aaveV3Pool_, address owner_) Ownable(owner_) {
+ constructor(address aaveV3Pool_ , address diva_, address owner_) Ownable(owner_) {
// Validate that none of the input addresses is zero to prevent unintended initialization with default addresses.
// Zero address check on `owner_` is performed in the OpenZeppelin's `Ownable` contract.
if (diva_ == address(0) || aaveV3Pool_ == address(0)) {