Summary
Function FEED_HORSE in HorseStore.huff reverted if block.timestamp is divisible by 17
Vulnerability Details
Function FEED_HORSE in HorseStore.huff
#define macro FEED_HORSE() = takes (0) returns (0) {
timestamp
0x04 calldataload
STORE_ELEMENT(0x00)
0x11 timestamp mod
endFeed jumpi
revert
endFeed:
stop
}
contains code that calls REVERT if block.timestamp
is divisible by 17 without remainder
POC
Add this test to HorseStoreHuff.t.sol
and run via forge test --mt testFeedingMod17 -vv
to see it success.
function testFeedingMod17() public {
uint256 horseId = horseStore.totalSupply();
vm.prank(user);
horseStore.mintHorse();
for (uint delay = 1; delay < 30000; delay++) {
vm.warp(delay);
if (delay % 17 == 0) {
vm.expectRevert();
horseStore.feedHorse(horseId);
} else {
horseStore.feedHorse(horseId);
assertEq(horseStore.isHappyHorse(horseId), true);
}
}
}
Output:
Running 1 test for test/HorseStoreHuff.t.sol:HorseStoreHuff
[PASS] testFeedingMod17() (gas: 64916724)
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 835.78ms
Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)
Impact
It is not possible to feed a horse if block.timestamp is divisible by 17
Tools Used
Foundry, manual inspection.
Recommendations
Make the following changes:
https://github.com/Cyfrin/2024-01-horse-store/blob/8255173c9340c12501881c9ecdd4175ff7350f5d/src/HorseStore.huff#L86C1-L90C9
#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
}