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

The Huff version does not match the Solidity version regarding the `fallback` function

Summary

The functionality of the fallback function in the Huff version differs from that of the fallback function in the Solidity version.

Vulnerability Details

There is no fallback function in the Solidity version, while in the Huff version, the totalSupply function is a fallback function.

Impact

It is important to note that third-party contracts may depend on the success of the execution of the fallback function or the values returned by it, which could lead to unexpected results if the implementation of the fallback function differs between the Solidity and Huff versions. Therefore, it is necessary to ensure that the fallback function is implemented consistently across all versions to prevent any potential issues.

Proof of Concept (PoC)

Add the next test in HorseStoreSolidity.t.sol.

function test_Fallback() public {
(bool success, ) = address(horseStore).call("");
assertFalse(success); // there is no fallback function
}

Run a test with forge test --mt test_Fallback.

Add the next test in HorseStoreHuff.t.sol.

function test_Fallback() public {
// mint 10 NFTs
for (uint256 i = 1; i <= 10; ++i) {
vm.prank(user);
horseStore.mintHorse(); // mint NFT
uint256 totalSupply = horseStore.totalSupply(); // retrieve total supply
assertEq(totalSupply, i);
(bool success, bytes memory data) = address(horseStore).call(""); // execute fallback
assertTrue(success); // there is fallback function
uint256 fallbackData = abi.decode(data, (uint256));
assertEq(fallbackData, totalSupply); // returned value from the fallback execution is the same as the total supply
}
}

Run a test with forge test --mt test_Fallback.

Tools Used

  • Foundry

Recommendations

Recommended changes to HorseStore.huff::MAIN() function to be reverted if no valid function selector is found:

#define macro MAIN() = takes (0) returns (0) {
// Identify which function is being called.
0x00 calldataload 0xE0 shr
dup1 __FUNC_SIG(totalSupply) eq totalSupply jumpi
dup1 __FUNC_SIG(feedHorse) eq feedHorse jumpi
dup1 __FUNC_SIG(isHappyHorse) eq isHappyHorse jumpi
dup1 __FUNC_SIG(horseIdToFedTimeStamp) eq horseIdToFedTimeStamp jumpi
dup1 __FUNC_SIG(mintHorse) eq mintHorse jumpi
dup1 __FUNC_SIG(HORSE_HAPPY_IF_FED_WITHIN) eq horseHappyIfFedWithin jumpi
dup1 __FUNC_SIG(approve) eq approve jumpi
dup1 __FUNC_SIG(setApprovalForAll) eq setApprovalForAll jumpi
dup1 __FUNC_SIG(transferFrom) eq transferFrom jumpi
dup1 __FUNC_SIG(name) eq name jumpi
dup1 __FUNC_SIG(symbol) eq symbol jumpi
dup1 __FUNC_SIG(tokenURI) eq tokenURI jumpi
dup1 __FUNC_SIG(supportsInterface)eq supportsInterface jumpi
dup1 __FUNC_SIG(getApproved) eq getApproved jumpi
dup1 __FUNC_SIG(isApprovedForAll) eq isApprovedForAll jumpi
dup1 __FUNC_SIG(balanceOf) eq balanceOf jumpi
dup1 __FUNC_SIG(ownerOf)eq ownerOf jumpi
+ // Revert if no match is found.
+ 0x00 0x00 revert
totalSupply:
GET_TOTAL_SUPPLY()
feedHorse:
FEED_HORSE()
isHappyHorse:
IS_HAPPY_HORSE()
mintHorse:
MINT_HORSE()
horseIdToFedTimeStamp:
GET_HORSE_FED_TIMESTAMP()
horseHappyIfFedWithin:
HORSE_HAPPY_IF_FED_WITHIN()
approve:
APPROVE()
setApprovalForAll:
SET_APPROVAL_FOR_ALL()
transferFrom:
TRANSFER_FROM()
name:
NAME()
symbol:
SYMBOL()
tokenURI:
TOKEN_URI()
supportsInterface:
SUPPORTS_INTERFACE()
getApproved:
GET_APPROVED()
isApprovedForAll:
IS_APPROVED_FOR_ALL()
balanceOf:
BALANCE_OF()
ownerOf:
OWNER_OF()
MINT_HORSE()
}

Add the next test in HorseStoreHuff.t.sol.

function test_FallbackNotExist() public {
(bool success, ) = address(horseStore).call("");
assertFalse(success);
}

Run a test with forge test --mt test_FallbackNotExist.

Updates

Lead Judging Commences

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

MAIN() macro is not properly implemented

Any call data sent to the contract that doesn't contain a function selector will randomly mint a horse.

Support

FAQs

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