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

The new experimental Vyper version allows the `internal` functions to be inherited

Summary

This Vyper version allows the use of internal functions in the derived contract.

Vulnerability Details

The request_raffle_winner and fulfillRandomWords functions use internal ERC721 functions:

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)

The snek_raffle contract inherits the ERC721 contract, but in the README and in the Vyper documentation for the older version (0.3.10) is said that:
You cannot inherit/override internal functions. This is a specific design choice by the Vyper team - so that knowing exactly what a function is supposed to do is easier.

Vyper Documentation:
Internal functions (marked with the @internal decorator) are only accessible from other functions within the same contract.
https://docs.vyperlang.org/en/v0.3.10/control-structures.html?highlight=internal%20functions#internal-functions

However, the used internal functions _mint and _total_supply work fine in the snek_raffle contract. The following test shows that. The USER successfully receive the snek NFT token.

def test_enter_raffle_and_win_raffle(raffle_boa_entered, vrf_coordinator_boa, entrance_fee):
starting_balance = boa.env.get_balance(USER)
boa.env.time_travel(seconds=INTERVAL + 1)
with boa.env.prank(USER):
raffle_boa_entered.request_raffle_winner()
# Normally we need to get the requestID, but our mock ignores that
vrf_coordinator_boa.fulfillRandomWords(0, raffle_boa_entered.address)
recent_winner = raffle_boa_entered.get_recent_winner()
winner_balance = boa.env.get_balance(recent_winner)
assert recent_winner == USER
assert winner_balance == entrance_fee
assert raffle_boa_entered.balanceOf(USER) == 1
assert raffle_boa_entered.ownerOf(0) == USER

Impact

The possibility of inheritance the internal functions is a major change from the previous Vyper version. That will help in the implementation process, but will make harder the readability of the code.

Tools Used

VS Code, pytest

Recommendations

Consider if the inheritance of the internal functions is intented, unintended or it is a compiler error. If it is a compiler error, it should be out of scope according to the README of the protocol.

Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Too generic

Support

FAQs

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