Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: low
Invalid

Missing events in ```HorseStore.huff``` macros and ```HorseStore.sol``` functions.

Summary

HorseStore.huff::FEED_HORSE, HorseStore.huff::IS_HAPPY_HORSE macros and HorseStore::feedHorse and HorseStore::isHappyHorse don't emit an event, so it is difficult to track changes of the status.

Vulnerability Details

- HorseStore.sol
function feedHorse(uint256 horseId) external {
@> horseIdToFedTimeStamp[horseId] = block.timestamp;
}
function isHappyHorse(uint256 horseId) external view returns (bool) {
if (horseIdToFedTimeStamp[horseId] <= block.timestamp - HORSE_HAPPY_IF_FED_WITHIN) {
@> return false;
}
@> return true;
}
}
- HorseStore.huff
#define macro FEED_HORSE() = takes (0) returns (0) {
timestamp // [timestamp]
0x04 calldataload // [horseId, timestamp]
@> STORE_ELEMENT(0x00) // []
// End execution
0x11 timestamp mod
endFeed jumpi
revert
endFeed:
stop
}
#define macro IS_HAPPY_HORSE() = takes (0) returns (0) {
0x04 calldataload // [horseId]
LOAD_ELEMENT(0x00) // [horseFedTimestamp]
timestamp // [timestamp, horseFedTimestamp]
dup2 dup2 // [timestamp, horseFedTimestamp, timestamp, horseFedTimestamp]
sub // [timestamp - horseFedTimestamp, timestamp, horseFedTimestamp]
[HORSE_HAPPY_IF_FED_WITHIN_CONST] // [HORSE_HAPPY_IF_FED_WITHIN, timestamp - horseFedTimestamp, timestamp, horseFedTimestamp]
lt // [HORSE_HAPPY_IF_FED_WITHIN < timestamp - horseFedTimestamp, timestamp, horseFedTimestamp]
start_return_true jumpi // [timestamp, horseFedTimestamp]
eq // [timestamp == horseFedTimestamp]
start_return
jump
start_return_true:
0x01
start_return:
// Store value in memory.
@> 0x00 mstore
// Return value
0x20 0x00 return
}

Impact

In Ethereum, events are used to facilitate communication between smart contracts and their user interfaces or other off-chain services. When an event is emitted, it gets logged in the transaction receipt, and these logs can be monitored and reacted to by off-chain services or user interfaces.

Without an event, any off-chain service or user interface that needs to know a current value / status would have to actively query the contract state to get the current value / status. This is less efficient than simply listening for the event, and it can lead to delays in detecting changes.

The impact of this could be significant because the block.timestamp is used to calculate if the Horse is happy (true) or notHappy (false). If the Horse status changes and an off-chain service or user is not aware of the change because they didn't query the contract state at the right time, they could end up seeing a different state for the horse.

Tools Used

Manual review.

Recommendations

Emit an event for critical parameter changes.

  • HorseStore.huff

+ #define event HorseFed(uint256,uint256)
+ #define event HorseHappinessChecked(uint256,bool)
#define macro FEED_HORSE() = takes (0) returns (0) {
timestamp // [timestamp]
0x04 calldataload // [horseId, timestamp]
STORE_ELEMENT(0x00) // []
// Emit the HorseFed event
+ __EVENT_HASH(HorseFed) // [event_signature]
+ 0x04 calldataload // [horseId, event_signature]
+ timestamp // [timestamp, horseId, event_signature]
+ 0x00 0x00 log3 // []
// End execution
0x11 timestamp mod
endFeed jumpi
revert
endFeed:
stop
}
#define macro IS_HAPPY_HORSE() = takes (0) returns (0) {
0x04 calldataload // [horseId]
LOAD_ELEMENT(0x00) // [horseFedTimestamp]
timestamp // [timestamp, horseFedTimestamp]
dup2 dup2 // [timestamp, horseFedTimestamp, timestamp, horseFedTimestamp]
sub // [timestamp - horseFedTimestamp, timestamp, horseFedTimestamp]
[HORSE_HAPPY_IF_FED_WITHIN_CONST] // [HORSE_HAPPY_IF_FED_WITHIN, timestamp - horseFedTimestamp, timestamp, horseFedTimestamp]
lt // [HORSE_HAPPY_IF_FED_WITHIN < timestamp - horseFedTimestamp, timestamp, horseFedTimestamp]
start_return_true jumpi // [timestamp, horseFedTimestamp]
eq // [timestamp == horseFedTimestamp]
start_return
jump
start_return_true:
0x01
@> start_return:
// Store value in memory.
0x00 mstore
// Emit the HorseHappinessChecked event
+ __EVENT_HASH(HorseHappinessChecked) // [event_signature]
+ 0x04 calldataload // [horseId, event_signature]
+ 0x00 mstore // [isHappy, horseId, event_signature]
+ 0x20 0x00 log3 // []
// Return value
0x20 0x00 return
}
  • HorseStore.sol

+ event HorseFed(uint256 indexed horseId, uint256 indexed fedTimeStamp);
+ event HorseChecked(uint256 indexed horseId, bool isHappy);
function feedHorse(uint256 horseId) external {
horseIdToFedTimeStamp[horseId] = block.timestamp;
+ emit HorseFed(horseId, block.timestamp);
}
function isHappyHorse(uint256 horseId) external view returns (bool) {
if (horseIdToFedTimeStamp[horseId] <= block.timestamp - HORSE_HAPPY_IF_FED_WITHIN) {
return false;
+ emit HorseChecked(horseId, false);
}
return true;
+ emit HorseChecked(horseId, true);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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