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

The `fulfillRandomWords` function uses `send` that can silently fail

Summary

The fulfillRandomWords function uses the send method in order to send the reward to the winner. But this method can not be successfully executed.

Vulnerability Details

The fulfillRandomWords function sends to the winner of the raffle the reward - NFT and the balance of the contract:

def fulfillRandomWords(request_id: uint256, random_words: uint256[MAX_ARRAY_SIZE]):
index_of_winner: uint256 = random_words[0] % len(self.players)
recent_winner: address = self.players[index_of_winner]
self.recent_winner = recent_winner
self.players = []
self.raffle_state = RaffleState.OPEN
self.last_timestamp = block.timestamp
rarity: uint256 = random_words[0] % 3
self.tokenIdToRarity[ERC721._total_supply()] = rarity
log WinnerPicked(recent_winner)
ERC721._mint(recent_winner, ERC721._total_supply())
@> send(recent_winner, self.balance)

In order to send the balance of the contract, the function uses the send function. But these method has some limitations according to the Vyper documentation for version 0.3.10. If these limitations are still valid in the new experimental version, they should be taken into account:

Ethereum specifies that the operations will be rolled back if the contract runs out of gas in execution. send calls to the contract come with a free stipend of 2300 gas, which does not leave much room to perform other operations except basic logging. However, if the sender includes a higher gas amount through a call instead of send, then more complex functionality can be run.
It is considered a best practice to ensure your payable default function is compatible with this stipend. The following operations will consume more than 2300 gas:
- Writing to storage
- Creating a contract
- Calling an external function which consumes a large amount of gas
- Sending Ether

https://docs.vyperlang.org/en/v0.3.10/control-structures.html?highlight=send%5D#considerations

The documentation says that the Sending Ether will lead to operation be out of gas.

Also, the send method doesn't return any value about that if the transaction is successful.

Impact

If the transaction is not successfull the function will not revert and the winner will be not able to receive the reward.
Moreover, there is no check if the winner can receive ether.
It will be impossible to win raffle if the winner is a smart contract without a fallback function.

Tools Used

Manual Review

Recommendations

Use raw_call instead of send and check the return value. Also, check if the winner can receive ethers.

Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
bube Submitter
over 1 year ago
inallhonesty Lead Judge
over 1 year ago
inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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