QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: low
Invalid

Invalid revert message in quantAMMPackEight32 and quantAMMPack32Array. Creates confusion among devs, users.

Summary

In the QuantAMMStorage.sol::ScalarQuantAMMBaseStorage contract, there's functions called quantAMMPackEight32, quantAMMPack32Array and QuantAMMStorage.sol::ScalarRuleQuantAMMStorage contract has _quantAMMPack128Array which have require checks to check values can't overflow or underflow. However, that require checks have a wrong revert message which is confusing.

Vulnerability Details

QuantAMMStorage.sol::ScalarQuantAMMBaseStorage::quantAMMPackEight32:

function quantAMMPackEight32(
int256 _firstInt,
int256 _secondInt,
int256 _thirdInt,
int256 _fourthInt,
int256 _fifthInt,
int256 _sixthInt,
int256 _seventhInt,
int256 _eighthInt
) internal pure returns (int256 packed) {
@> // @info: invalid revert message,
// revert is happening for both min and max values
// so the message should be "Over/Underflow" not "Overflow"
require(
_firstInt <= MAX32 && _firstInt >= MIN32 && _secondInt <= MAX32 && _secondInt >= MIN32 && _thirdInt <= MAX32
&& _thirdInt >= MIN32 && _fourthInt <= MAX32 && _fourthInt >= MIN32 && _fifthInt <= MAX32
&& _fifthInt >= MIN32 && _sixthInt <= MAX32 && _sixthInt >= MIN32 && _seventhInt <= MAX32
&& _seventhInt >= MIN32 && _eighthInt <= MAX32 && _eighthInt >= MIN32,
@> "Overflow"
);
.
.
.
}

QuantAMMStorage.sol::ScalarQuantAMMBaseStorage::quantAMMPack32Array:

function quantAMMPack32Array(int256[] memory _sourceArray) internal pure returns (int256[] memory targetArray) {
.
.
...
//pack up to 7 sticky ends
uint256 stickyEndElems = _sourceArray.length - nonStickySourceLength;
if (stickyEndElems > 0) {
uint256 offset = 224;
int256 packed;
for (uint256 i = nonStickySourceLength; i < _sourceArray.length;) {
unchecked {
int256 elem = _sourceArray[i] / 1e9;
// @info: wrong error message
@> require(elem <= MAX32 && elem >= MIN32, "Overflow");
packed |= int256(uint256(elem << 224) >> 224) << offset;
offset -= 32;
++i;
}
}
targetArray[storageIndex] = packed;
}
}

QuantAMMStorage.sol::ScalarRuleQuantAMMStorage::_quantAMMPack128Array:

function _quantAMMPack128Array(int256[] memory _sourceArray) internal pure returns (int256[] memory targetArray) {
uint256 sourceArrayLength = _sourceArray.length;
uint256 targetArrayLength = sourceArrayLength;
uint256 storageIndex;
require(_sourceArray.length != 0, "LEN0");
if (_sourceArray.length % 2 == 0) {
unchecked {
targetArrayLength = (targetArrayLength) / 2;
}
targetArray = new int256[](targetArrayLength);
for (uint256 i; i < sourceArrayLength - 1;) {
targetArray[storageIndex] = _quantAMMPackTwo128(_sourceArray[i], _sourceArray[i + 1]);
unchecked {
i += 2;
++storageIndex;
}
}
} else {
int256 lastArrayItem = _sourceArray[_sourceArray.length - 1];
@> // @info: revert message should be "Last array element Over/Underflow" not "Last array element overflow"
@> require(
(lastArrayItem >= int256(type(int128).min)) && (lastArrayItem <= int256(type(int128).max)),
@> "Last array element overflow"
);
.
.
...
}
.
.
...
}

Impact

Revert message creates confusion among devs, auditors, and users.

Tools Used

Manual Review

Recommendations

Please update that wrong revert message to right one "Over/Underflow". Update the message as updated below...

QuantAMMStorage.sol::ScalarQuantAMMBaseStorage::quantAMMPackEight32:

function quantAMMPackEight32(
int256 _firstInt,
int256 _secondInt,
int256 _thirdInt,
int256 _fourthInt,
int256 _fifthInt,
int256 _sixthInt,
int256 _seventhInt,
int256 _eighthInt
) internal pure returns (int256 packed) {
- require(
- _firstInt <= MAX32 && _firstInt >= MIN32 && _secondInt <= MAX32 && _secondInt >= MIN32 && _thirdInt <= MAX32
- && _thirdInt >= MIN32 && _fourthInt <= MAX32 && _fourthInt >= MIN32 && _fifthInt <= MAX32
- && _fifthInt >= MIN32 && _sixthInt <= MAX32 && _sixthInt >= MIN32 && _seventhInt <= MAX32
- && _seventhInt >= MIN32 && _eighthInt <= MAX32 && _eighthInt >= MIN32,
- "Overflow"
- );
+ require(
+ _firstInt <= MAX32 && _firstInt >= MIN32 && _secondInt <= MAX32 && _secondInt >= MIN32 && _thirdInt <= MAX32
+ && _thirdInt >= MIN32 && _fourthInt <= MAX32 && _fourthInt >= MIN32 && _fifthInt <= MAX32
+ && _fifthInt >= MIN32 && _sixthInt <= MAX32 && _sixthInt >= MIN32 && _seventhInt <= MAX32
+ && _seventhInt >= MIN32 && _eighthInt <= MAX32 && _eighthInt >= MIN32,
+ "Over/Underflow"
+ );
.
.
.
}

QuantAMMStorage.sol::ScalarQuantAMMBaseStorage::quantAMMPack32Array:

function quantAMMPack32Array(int256[] memory _sourceArray) internal pure returns (int256[] memory targetArray) {
.
.
...
//pack up to 7 sticky ends
uint256 stickyEndElems = _sourceArray.length - nonStickySourceLength;
if (stickyEndElems > 0) {
uint256 offset = 224;
int256 packed;
for (uint256 i = nonStickySourceLength; i < _sourceArray.length;) {
unchecked {
int256 elem = _sourceArray[i] / 1e9;
// @info: wrong error message
- require(elem <= MAX32 && elem >= MIN32, "Overflow");
+ require(elem <= MAX32 && elem >= MIN32, "Over/Underflow");
packed |= int256(uint256(elem << 224) >> 224) << offset;
offset -= 32;
++i;
}
}
targetArray[storageIndex] = packed;
}
}

QuantAMMStorage.sol::ScalarRuleQuantAMMStorage::_quantAMMPack128Array:

function _quantAMMPack128Array(int256[] memory _sourceArray) internal pure returns (int256[] memory targetArray) {
uint256 sourceArrayLength = _sourceArray.length;
uint256 targetArrayLength = sourceArrayLength;
uint256 storageIndex;
require(_sourceArray.length != 0, "LEN0");
if (_sourceArray.length % 2 == 0) {
unchecked {
targetArrayLength = (targetArrayLength) / 2;
}
targetArray = new int256[](targetArrayLength);
for (uint256 i; i < sourceArrayLength - 1;) {
targetArray[storageIndex] = _quantAMMPackTwo128(_sourceArray[i], _sourceArray[i + 1]);
unchecked {
i += 2;
++storageIndex;
}
}
} else {
int256 lastArrayItem = _sourceArray[_sourceArray.length - 1];
- require(
- (lastArrayItem >= int256(type(int128).min)) && (lastArrayItem <= int256(type(int128).max)),
- "Last array element overflow"
- );
+ require(
+ (lastArrayItem >= int256(type(int128).min)) && (lastArrayItem <= int256(type(int128).max)),
+ "Last array element over/underflow"
);
.
.
...
}
.
.
...
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Informational or Gas / Admin is trusted / Pool creation is trusted / User mistake / Suppositions

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelyhood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Support

FAQs

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

Give us feedback!