DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: high
Invalid

Inconsistent hashing in VaultReader.sol leads the bricking of the vital functions throughout the protocol as wrong values are returned.

Summary

in gamma, VaultReader.sol is used to retrieve vital values from the datastore, These values such as the positioninfo and the pnl are used throughout the protocol to carry out various operations but the functions that hashes the positionkey and retrieves the value from the datastore is not written properly leading to a wrong hash being generated thereby returning zero or wrong values from the datastore

Vulnerability Details

The exact functions that are used in VaultReader.sol to retrieve these values from datastore are;

[Link to sample code](https://github.com/CodeHawks-Contests/2025-02-gamma/blob/84b9da452fc84762378481fa39b4087b10bab5e0/contracts/VaultReader.sol#L192-L209)

/**
* @notice Retrieves the position size in USD for a given key.
* @param key The key representing the position.
* @return sizeInUsd The size of the position in USD.
*/
function getPositionSizeInUsd(bytes32 key) public view returns (uint256 sizeInUsd) {
sizeInUsd = dataStore.getUint(keccak256(abi.encode(key, SIZE_IN_USD))); //@audit the hash will be wrong as it should be the keyword before `key`
}
/**
* @notice Retrieves the position size in tokens for a given key.
* @param key The key representing the position.
* @return sizeInTokens The size of the position in tokens.
*/
function getPositionSizeInTokens(bytes32 key) public view returns (uint256 sizeInTokens) {
sizeInTokens = dataStore.getUint(keccak256(abi.encode(key, SIZE_IN_TOKENS))); //@audit
}

it can be seen that in the hashing the key value is placed before the hash identifier SIZE_IN_USD and SIZE_IN_TOKENS respectively but this is inconsistent with the way hashing for datastore queries are done in other places in the protocol and even with gmx.

It can be seen here that the hash identifier is always before the value being hashed
Sample link

// @dev the min collateral factor key
// @param the market for the min collateral factor
function minCollateralFactorKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode( //@audit the identifier is before the value being hashed
MIN_COLLATERAL_FACTOR,
market
));
}
}

The hashes generated in VaultReader.sol will therefore be wrong as it doesn't match the with way it were hashed and stored in datastore leading to zero values constantly being returned (as datastore is a mapping)

Impact

The VaultReader.sol itself becomes useless as wrong values are always returned
The values returned by these flawed functions are further to used to generate very important data used throughout the perpetualvault and protocol, leading to wrong states and bricking of vital operations.

Tools Used

Manual Review

Recommendations

write the mentioned functions to have the identifier first, ensuring correct hash results.

/**
* @notice Retrieves the position size in USD for a given key.
* @param key The key representing the position.
* @return sizeInUsd The size of the position in USD.
*/
function getPositionSizeInUsd(bytes32 key) public view returns (uint256 sizeInUsd) {
-- sizeInUsd = dataStore.getUint(keccak256(abi.encode(key, SIZE_IN_USD))); //@audit
++ sizeInUsd = dataStore.getUint(keccak256(abi.encode(SIZE_IN_USD, key)));
}
/**
* @notice Retrieves the position size in tokens for a given key.
* @param key The key representing the position.
* @return sizeInTokens The size of the position in tokens.
*/
function getPositionSizeInTokens(bytes32 key) public view returns (uint256 sizeInTokens) {
-- sizeInTokens = dataStore.getUint(keccak256(abi.encode(key, SIZE_IN_TOKENS))); //@audit
++ sizeInTokens = dataStore.getUint(keccak256(abi.encode(SIZE_IN_TOKENS, key)));
}
Updates

Lead Judging Commences

n0kto Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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