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

The user can feed a horse with ID which is not minted in `HorseStore::feedHorse`

Summary

The function HorseStore::feedHorse allows to be fed horse ID that is not yet minted.

Vulnerability Details

The intended behavior of the HorseStore::feedHorse is to allow anyone to feed the horse of someone else. But the function does not check if the provided horseId is actually of a minted horse token.

function feedHorse(uint256 horseId) external {
horseIdToFedTimeStamp[horseId] = block.timestamp;
}

Therefore, user can feed a horse with horseId which is not minted. After that another user can minted the horse token with the corresponding horseId (within the 24 hours) and his horse will be happy.

function isHappyHorse(uint256 horseId) external view returns (bool) {
if (horseIdToFedTimeStamp[horseId] <= block.timestamp - HORSE_HAPPY_IF_FED_WITHIN) {
return false;
}
return true;
}

Impact

Let's consider the following scenario:
Alice minted a horse token with ID 0. But Alice feed a horse with wrong ID 1, thinking this is her horseID. So, the function HorseStore::isHappyHorse will return true for the horseId 1, but Alice's horse with horseId 0 will be unhappy . Bob minted after Alice a horse token with ID 1. And he calls the HorseStore::isHappyHorse function without feeding the horse and the function returns true.

The following test shows the described scenario. You can add this test to the file Base_Test.t.sol and you can execute it with the Foundry command: forge test --match-test "testFeedingWrongHorse" -vvv

function testFeedingWrongHorse() public {
uint256 horseId = horseStore.totalSupply();
vm.warp(horseStore.HORSE_HAPPY_IF_FED_WITHIN());
vm.roll(horseStore.HORSE_HAPPY_IF_FED_WITHIN());
vm.prank(user);
horseStore.mintHorse();
uint256 lastFedTimeStamp = block.timestamp;
//feed the horse with ID which corresponds to unminted horse token
horseStore.feedHorse(horseId + 1);
uint256 horseId1 = horseStore.totalSupply();
console2.log(horseId1);
vm.prank(anotherUser);
horseStore.mintHorse();
assertEq(horseStore.horseIdToFedTimeStamp(horseId + 1), lastFedTimeStamp);
//The horse can be fed before the token for this horse is minted.
assertEq(horseStore.isHappyHorse(horseId1), true);
}

In the documentation is said that the horse happiness is the most important part of the protocol, therefore the impact of this issue is high. This issue allows a horse with unexisting ID to be happy and a created horse (minted horse token) to be not fed and to be unhappy.

Tools Used

Manual Review, Foundry

Recommendations

Add a check in HorseStore::feedHorse to ensure that the provided horseId is valid.

function feedHorse(uint256 horseId) external {
+ require(horseId <= totalSupply(), "Invalid horseId")
horseIdToFedTimeStamp[horseId] = block.timestamp;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Nonexistent horses can be fed

Support

FAQs

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