Nice Basil Panda
Medium
getSettlementsFromIdtoTimestamp
assumes that settlementHistory always sorted by blockTimestamp which is incorrect
getSettlementsFromIdtoTimestamp
is used in updateRewardsForProposalWritingAndVoting
in rewards.sol when calculating rewards which means its not just a view function.
function getSettlementsFromIdtoTimestamp(
uint256 startId,
uint256 endTimestamp,
bool skipEmptyValues
) public view returns (Settlement[] memory settlements) {
uint256 maxId = auctionStorage.nounId;
require(startId <= maxId, 'startId too large');
settlements = new Settlement[](maxId - startId + 1);
uint256 actualCount = 0;
SettlementState memory settlementState;
for (uint256 id = startId; id <= maxId; ++id) {
settlementState = settlementHistory[id];
if (skipEmptyValues && settlementState.blockTimestamp <= 1) continue;
// don't include the currently auctioned noun if it hasn't settled
if ((id == maxId) && (settlementState.blockTimestamp <= 1)) continue;
--> if (settlementState.blockTimestamp > endTimestamp) break;
settlements[actualCount] = Settlement({
blockTimestamp: settlementState.blockTimestamp,
amount: uint64PriceToUint256(settlementState.amount),
winner: settlementState.winner,
nounId: id,
clientId: settlementState.clientId
});
++actualCount;
}
if (settlements.length > actualCount) {
// this assembly trims the settlements array, getting rid of unused cells
assembly {
mstore(settlements, actualCount)
}
}
}
but blockTimestamp can be changed by owner for whatever reason, so settlementHistory will become not sorted
function setPrices(SettlementNoClientId[] memory settlements) external onlyOwner {
for (uint256 i = 0; i < settlements.length; ++i) {
SettlementState storage settlementState = settlementHistory[settlements[i].nounId];
--> settlementState.blockTimestamp = settlements[i].blockTimestamp;
settlementState.amount = ethPriceToUint64(settlements[i].amount);
settlementState.winner = settlements[i].winner;
}
}
contracts/NounsAuctionHouseV3.sol#L393
admin decides to change blockTimestamp for settlementHistory
none
No response
Rewards will be calculated incorrectly
No response
If history becomes unsorted than getSettlementsFromIdtoTimestamp doesn't make sense, seems like need redesign
function getSettlementsFromIdtoTimestamp(
uint256 startId,
uint256 endTimestamp,
bool skipEmptyValues
) public view returns (Settlement[] memory settlements) {
uint256 maxId = auctionStorage.nounId;
require(startId <= maxId, 'startId too large');
settlements = new Settlement[](maxId - startId + 1);
uint256 actualCount = 0;
SettlementState memory settlementState;
for (uint256 id = startId; id <= maxId; ++id) {
settlementState = settlementHistory[id];
if (skipEmptyValues && settlementState.blockTimestamp <= 1) continue;
// don't include the currently auctioned noun if it hasn't settled
if ((id == maxId) && (settlementState.blockTimestamp <= 1)) continue;
- if (settlementState.blockTimestamp > endTimestamp) break;
+ if (settlementState.blockTimestamp > endTimestamp) continue;
settlements[actualCount] = Settlement({
blockTimestamp: settlementState.blockTimestamp,
amount: uint64PriceToUint256(settlementState.amount),
winner: settlementState.winner,
nounId: id,
clientId: settlementState.clientId
});
++actualCount;
}
if (settlements.length > actualCount) {
// this assembly trims the settlements array, getting rid of unused cells
assembly {
mstore(settlements, actualCount)
}
}
}