There is an issue with the order of operations in the refresh() function lastRefresh variable, which stores the timestamp of the last successful refresh, which is updated after calling basketHandler.trackStatus(). This can lead to inconsistencies if basketHandler.trackStatus() reverts due to an exception.
function refresh() public {
// ...
basketHandler.trackStatus();
lastRefresh = uint48(block.timestamp); // <@
}
Impact
If basketHandler.trackStatus() reverts, the lastRefresh variable will not be updated. lastRefresh will not reflect the actual timestamp of the last successful refresh, leading to an inconsistent state within the AssetRegistry contract.
If issues arise related to the lastRefresh value, it may be challenging to identify and debug the root cause, as the value may not accurately represent the last successful refresh timestamp.
Proof of Concept
Ccenario:
The refresh() function is called on the AssetRegistry contract.
The function iterates over the registered assets and calls refresh() on each asset.
The lastRefresh update should be moved before the call to basketHandler.trackStatus(). This ensures that lastRefresh is always updated with the current block timestamp, even if basketHandler.trackStatus() reverts.
function refresh() public {
// ...
+ lastRefresh = uint48(block.timestamp);
basketHandler.trackStatus();
- lastRefresh = uint48(block.timestamp);
}
Updating lastRefresh before calling basketHandler.trackStatus(), we guarantee that the lastRefresh value accurately reflects the timestamp of the last successful refresh, regardless of any exceptions that may occur in basketHandler.trackStatus().
Lines of code
https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/BasketHandler.sol#L175-L191 https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/p1/AssetRegistry.sol#L58-L69
Vulnerability details
There is an issue with the order of operations in the
refresh()
functionlastRefresh
variable, which stores the timestamp of the last successful refresh, which is updated after calling basketHandler.trackStatus(). This can lead to inconsistencies ifbasketHandler.trackStatus()
reverts due to an exception.AssetRegistry.refresh()
Impact
If
basketHandler.trackStatus()
reverts, thelastRefresh
variable will not be updated.lastRefresh
will not reflect the actual timestamp of the last successful refresh, leading to an inconsistent state within the AssetRegistry contract.If issues arise related to the
lastRefresh
value, it may be challenging to identify and debug the root cause, as the value may not accurately represent the last successful refresh timestamp.Proof of Concept
Ccenario:
refresh()
function is called on the AssetRegistry contract.refresh()
on each asset.This scenario demonstrates how the lastRefresh variable can remain outdated if basketHandler.trackStatus() reverts.
Tools Used
Manual review
Recommended Mitigation Steps
The
lastRefresh
update should be moved before the call tobasketHandler.trackStatus()
. This ensures thatlastRefresh
is always updated with the current block timestamp, even ifbasketHandler.trackStatus()
reverts.Updating
lastRefresh
before callingbasketHandler.trackStatus()
, we guarantee that thelastRefresh
value accurately reflects the timestamp of the last successful refresh, regardless of any exceptions that may occur inbasketHandler.trackStatus()
.Assessed type
Context