HardhatDeFi
15,000 USDC
View results
Submission Details
Severity: medium
Invalid

Protocol Vulnerable to Token Behavior Changes Through Upgrades Risking Collateral Ratio Mismatches

Description

The AaveDIVAWrapper contract assumes consistent token behavior over time but lacks protection against upgradeable tokens (like USDC, USDT) changing their core functionality through upgrades. While these changes won't affect mid-transaction operations, they can break protocol assumptions between transactions.

Current vulnerable implementation:

https://github.com/Cyfrin/2025-01-diva/blob/main/contracts/src/AaveDIVAWrapperCore.sol#L423

function _handleTokenOperations(
address _collateralToken,
uint256 _collateralAmount,
address _wToken
) private {
// No validation of token behavior changes
IERC20Metadata(_collateralToken).safeTransferFrom(
msg.sender,
address(this),
_collateralAmount
);
// Assumes 1:1 transfer without fees
IAave(_aaveV3Pool).supply(
_collateralToken,
_collateralAmount, // Assumes same amount received
address(this),
0
);
// Assumes 1:1 relationship
IWToken(_wToken).mint(address(this), _collateralAmount);
}

Impact

Token upgrades could break protocol in several ways:

  1. Added transfer fees break 1:1 collateral ratio

  2. New transfer restrictions prevent operation completion

  3. Blocklist features could lock protocol funds

  4. Modified balance mechanics break accounting

  5. Changed requirements invalidate protocol assumptions

Proof of Concept

// Scenario: USDC adds 1% transfer fee
contract MockUSDC {
bool public feeEnabled;
uint256 public constant FEE = 100; // 1%
function upgrade() external {
feeEnabled = true;
}
function transfer(address to, uint256 amount) external returns (bool) {
if (feeEnabled) {
uint256 fee = amount * FEE / 10000;
// Recipient gets less than expected
_transfer(msg.sender, to, amount - fee);
return true;
}
_transfer(msg.sender, to, amount);
return true;
}
}
// Protocol breaks because:
// 1. User deposits 100 USDC
// 2. USDC upgrades to add fee
// 3. Internal transfer only moves 99 USDC
// 4. But protocol minted 100 wTokens

Recommended Fix

contract AaveDIVAWrapperCore {
// Track token behavior
struct TokenBehavior {
bool hasFee;
bool hasRestrictions;
bytes32 implementationHash;
uint256 lastCheck;
}
mapping(address => TokenBehavior) public tokenBehaviors;
error TokenBehaviorChanged(address token);
error TokenImplementationChanged(address token);
function validateTokenBehavior(address token) internal {
TokenBehavior storage behavior = tokenBehaviors[token];
// Check implementation hasn't changed
bytes32 currentImpl = getImplementationHash(token);
if (currentImpl != behavior.implementationHash) {
// Update and potentially pause token
behavior.implementationHash = currentImpl;
_handleImplementationChange(token);
}
// Verify expected behavior
if (hasFee(token) != behavior.hasFee) {
revert TokenBehaviorChanged(token);
}
}
function _handleTokenOperations(
address _collateralToken,
uint256 _collateralAmount,
address _wToken
) private {
// Validate before operations
validateTokenBehavior(_collateralToken);
uint256 balanceBefore = IERC20(_collateralToken).balanceOf(address(this));
IERC20Metadata(_collateralToken).safeTransferFrom(
msg.sender,
address(this),
_collateralAmount
);
// Verify actual amount received
uint256 received = IERC20(_collateralToken).balanceOf(address(this)) -
balanceBefore;
if (received != _collateralAmount) {
revert UnexpectedTokenBehavior(_collateralToken, _collateralAmount, received);
}
// Continue with validated amount
IAave(_aaveV3Pool).supply(_collateralToken, received, address(this), 0);
IWToken(_wToken).mint(address(this), received);
}
}

The fix ensures protocol safety against token upgrades while maintaining functionality with trusted tokens.

Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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