DeFiHardhat
12,000 USDC
View results
Submission Details
Severity: low
Invalid

Truncation of Reserve during storage is not handled properly when reading causing vastly different Values to be returned.

Summary

Reading of stored byte16 reserve values in libLastReserveBytes would return reserves that are smaller than the initially stored reserves. This would result in wrong reserves being returned into the Multiflow pump and cause many problems.

Vulnerability Details

Reserves are bytes16 values that are updated along with timestamp and number of reserve values by a user through the MultiflowPump.update. The method of storing uses a truncation method to fit multiple bytes16 values into a single slot. This works by truncating the last 3 bytes to bytes13 values which are then stored in the reserve slot.

function storeLastReserves(bytes32 slot, uint40 lastTimestamp, bytes16[] memory reserves) internal {
// Potential optimization – shift reserve bytes left to perserve extra decimal precision.
uint8 n = uint8(reserves.length);
if (n == 1) {
assembly {
sstore(slot, or(or(shl(208, lastTimestamp), shl(248, n)), shl(104, shr(152, mload(add(reserves, 32))))))
}
// audit: terminates and returns
return;
} // extra code .....................................................................```
This value can be retrieved through `LibLastReserveBytes.readLastReserveBytes` and is used by functions in the multiflow pump. The issue is the original truncation is not handled during retrieval causing different values than what was initially stored to be retrieved. Most times, this value is alot smaller than what was originally stored by user.
## Impact
Due to improper handling of the original truncation of the reserve values, different values than what was original stored by the original user would lead to issues such as loss of funds and incorrect accounting.
## Proof of Code
1. Insert into `LibLastReserveBytes.t.sol`
function testAuditStoreLastReserveByte() public {
uint40 lastTimestamp = uint40(block.timestamp);
bytes16[] memory reserves = new bytes16[](1);
reserves[0] = 0xffffffffffffffffffffffffffffffff;
RESERVES_STORAGE_SLOT.storeLastReserves(lastTimestamp, reserves);
(uint8 n, uint40 timestamp, bytes16[] memory reserveRes) = RESERVES_STORAGE_SLOT.readLastReserves();
for(uint256 i; i<=reserves.length; ++i) {
assertEq(reserves[i], reserveRes[i]);
}
}
The assertion fails showing that what was originally stored is different from what was retrieved.
## Tools Used
Manual Review
## Recommendations
Account for the original truncation of the bytes16 reserve values to bytes13. During retrieval this value should be corrected to original value stored
Updates

Lead Judging Commences

giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Informational/Invalid

Support

FAQs

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