Dynamic arrays in Vyper give you the power to manage data collections dynamically within a declared size limit. Let’s look at a few examples:
contributors: DynArray[address, 1000]
@external
def add_contributor(contributor: address):
if len(contributors) < 1000:
contributors.append(contributor)
gameScores: DynArray[int128, 3]
@external
def record_scores(score1: int128, score2: int128, score3: int128):
gameScores = []
gameScores.append(score1)
gameScores.append(score2)
gameScores.append(score3)
candidates: DynArray[address, 50]
@external
def clear_candidates():
while len(candidates) > 0:
candidates.pop()
Dynamic Arrays in Vyper present a flexible and secured way of dealing with collections of data in your smart contracts. Imagine having a storage container that can adjust its size as you keep on adding or removing stuff, but it also has a maximum limit beyond which it just can’t expand. This is precisely the concept behind Vyper’s Dynamic Arrays! Let’s delve deeper into how they work and why they are so useful, showcasing some practical and easy-to-understand examples related to blockchain scenarios.
Overview of Dynamic Arrays
Dynamic Arrays are arrays that can hold elements of a specified type, and can change their size during runtime, but within a certain boundary limit. You can define them using arrayName: DynArray[_type, _maxSize]
format, where _type
is the data type of the elements stored in the array and _maxSize
is the maximum allowed size of the array.
Alongside, Vyper provides handy functions like append()
to add new elements, pop()
to remove elements, and indexes to access individual elements. However, be careful! If you attempt to add an item to a full array, extract an item from an empty array, or access an index beyond the current array length, you will face a runtime error.
Let’s understand better with some real-world examples.
Example 1: Keeping a Track of Crowdfunding Contributors
Assume you are developing a crowdfunding contract where people can contribute to a project. You can maintain a dynamic array of the addresses of contributors. However, to manage crowdfunds effectively, you can limit the maximum number of contributors.
# Define a dynamic array to store the addresses of contributors
contributors: DynArray[address, 1000]
@external
def add_contributor(contributor: address):
# Check if we can add more contributors
if len(contributors) < 1000:
# Append the contributor address to the array
contributors.append(contributor)
In the add_contributor
function, a contributor’s address is added to the contributors
array as long as the current number of contributors is less than 1000.
Example 2: Storing Different Levels of Game Scores
Consider a gaming contract where you store the top three scores of all completed games in a dynamic array.
# Define a dynamic array to store the top three game scores
gameScores: DynArray[int128, 3]
@external
def record_scores(score1: int128, score2: int128, score3: int128):
# Clear the dynamic array to store new scores
gameScores = []
# Append the new game scores to the array
gameScores.append(score1)
gameScores.append(score2)
gameScores.append(score3)
Here, the record_scores
function resets the gameScores
array and records the top three scores of a newly completed game.
Example 3: Safely Clearing Participating Addresses After Voting
Let’s continue with the contract for a voting system. After the vote, you might want to clear the list of candidates for the next round. Here is how you can do it:
# Define a dynamic array to store the addresses of the candidates
candidates: DynArray[address, 50]
@external
def clear_candidates():
# Loop until the array is empty
while len(candidates) > 0:
# Pop addresses from the array
candidates.pop()
In this clear_candidates
function, we are safely popping out all the candidates’ addresses using a while loop until our candidates
list is completely empty.
Good Habits and Things To Watch Out For
While dynamic arrays offer flexible and powerful storage, keep these guidelines in mind for effective usage:
- Prevent Overflow: Always ensure your dynamic array has enough room before attempting to append new items.
- Don’t Pop from Empty Arrays: Attempting to pop an item from an empty array will result in a runtime error. Always check if the array has items before trying to remove.
- Access the Right Indices: Avoid accessing an index that doesn’t exist in your array. Confirm the index’s existence before referencing to avoid runtime exceptions.
- Optimal Array Size: Choose the maximum array size wisely keeping in mind your specific application needs to avoid unnecessary memory allocation.
Remember that trying to access an unavailable index, popping an empty array, or appending to a full array will all cause a runtime failure (REVERT). Moreover, passing an array in calldata that is larger than the array bound will also result in a runtime REVERT.
Dynamic arrays, thus, provide you with an optimal solution for managing changing data sizes in your Ethereum smart contracts. Knowing how to accurately deal with them will boost your Vyper expertise and bring flexibility to your smart contracts. Happy coding with Vyper!