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 2 years 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.

Give us feedback!