Summary
The condition to check if the horse has not been fed for over 24 hours is incorrect.
Vulnerability Details
Add this test to Base_Test.t.sol
and run forge test --mt testHorseHappyAllDay -vvvv
.
function testHorseHappyAllDay(uint _houseId, uint _pastTime) public {
uint timestamp = 1705152551;
vm.assume(_pastTime < horseStore.HORSE_HAPPY_IF_FED_WITHIN());
vm.startPrank(user);
vm.warp(timestamp);
horseStore.feedHorse(_houseId);
console2.log(horseStore.horseIdToFedTimeStamp(_houseId));
vm.warp(timestamp + _pastTime);
assertEq(timestamp, horseStore.horseIdToFedTimeStamp(_houseId));
assertTrue(horseStore.isHappyHorse(_houseId));
vm.stopPrank();
}
The result is not as expected, assertion failed. Even horses that have been fed within the past 24 hours feel unhappy.
[48136] HorseStoreHuff::testHorseHappyAllDay(11138 [1.113e4], 1224)
├─ [160] 0x6d2eed85750d316088343D6d5e91ca59eb052768::HORSE_HAPPY_IF_FED_WITHIN() [staticcall]
│ └─ ← 86400 [8.64e4]
├─ [0] VM::assume(true) [staticcall]
│ └─ ← ()
├─ [0] VM::startPrank(user: [0x6CA6d1e2D5347Bfab1d91e883F1915560e09129D])
│ └─ ← ()
├─ [0] VM::warp(1705152551 [1.705e9])
│ └─ ← ()
├─ [22239] 0x6d2eed85750d316088343D6d5e91ca59eb052768::feedHorse(11138 [1.113e4])
│ └─ ← ()
├─ [267] 0x6d2eed85750d316088343D6d5e91ca59eb052768::horseIdToFedTimeStamp(11138 [1.113e4]) [staticcall]
│ └─ ← 1705152551 [1.705e9]
├─ [0] console::log(1705152551 [1.705e9]) [staticcall]
│ └─ ← ()
├─ [0] VM::warp(1705153775 [1.705e9])
│ └─ ← ()
├─ [267] 0x6d2eed85750d316088343D6d5e91ca59eb052768::horseIdToFedTimeStamp(11138 [1.113e4]) [staticcall]
│ └─ ← 1705152551 [1.705e9]
├─ [290] 0x6d2eed85750d316088343D6d5e91ca59eb052768::isHappyHorse(11138 [1.113e4]) [staticcall]
│ └─ ← false
├─ emit log(val: "Error: Assertion Failed")
├─ [0] VM::store(VM: [0x7109709ECfa91a80626fF3989D68f67F5b1DD12D], 0x6661696c65640000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000001)
│ └─ ← ()
├─ [0] VM::stopPrank()
│ └─ ← ()
└─ ← ()
Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 468.00ms
Ran 2 test suites: 1 tests passed, 1 failed, 0 skipped (2 total tests)
Failing tests:
Encountered 1 failing test in test/HorseStoreHuff.t.sol:HorseStoreHuff
[FAIL. Reason: assertion failed; counterexample: calldata=0xbf6e8bed0000000000000000000000000000000000000000000000000000000000002b8200000000000000000000000000000000000000000000000000000000000004c8 args=[11138 [1.113e4], 1224]] testHorseHappyAllDay(uint256,uint256) (runs: 0, μ: 0, ~: 0)
The root cause is an incorrect condition for determining the happiness of horses at line 100 in HorseStore.huff
Impact
Even horses that have been fed within the past 24 hours feel unhappy.
Tools Used
foundry
Recommendations
HorseStore.huff#L100
Make the following changes:
#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]
+ gt // [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
}