Imagine a lottery where the balls are tumbling in a glass sphere, watched by the world. Each number is a smart contract, each draw a transaction, and the entire network stands witness to the spectacle. This isn’t just a game of chance; it’s a demonstration of trust in technology, a showcase of fairness in play
The Random Fantasy Team Name Selector does not merely pick a name; it orchestrates a symphony of unpredictability, with each note struck by the hammer of cryptographic algorithms. It’s a modern-day oracle, delivering prophecies of randomness that are transparent, tamper-proof, and fair.
OverviewIn this series of posts, we will dive into creating a decentralized application using Solidity, the programming language for writing smart contracts on the Ethereum blockchain. Our project currently consists of two main contracts: RandomTeamSelector and TeamNames. Both of these contracts leverage Chainlink's Verifiable Random Function (VRF) to ensure secure and verifiable randomness, essential for fair and unpredictable outcomes in our application.
The RandomTeamSelector contract is designed to randomly assign team names to participants using names commonly associate with mythical and fantasy creatures. Using Chainlink VRF, this contract can request random values that are used to select from a predefined list of team names. The TeamNames contract holds the list of possible team names and provides a function to retrieve a name based on an index.
Chainlink VRF is a reliable source of randomness for smart contracts. It provides cryptographic proof that the random values generated are tamper-proof and verifiably fair. By integrating Chainlink VRF into our Solidity contracts, we ensure that our random team selections are unbiased and transparent.
So, join us as we embark on this journey through the mechanics of the Random Fantasy Team Name Selector, exploring how it harnesses the power of Chainlink VRF to bring verifiable randomness to the blockchain. It’s a story of innovation, a dance of algorithms, and a testament to the ingenuity of decentralized solutions.
The Forge of Creation: Setting the Stage for Smart Contract DevelopmentBefore we delve deeper into the intricacies of our Random Team Selector smart contract, let’s take a moment to acknowledge the anvil upon which it was forged. In the modern alchemy of smart contract development, the tools we choose are as crucial as the spells we cast. For this project, we’ve chosen a tool that’s as robust as it is refined: Foundry’s forge.
forge initWith a simple forge init, we breathed life into our project, creating a structured environment where our smart contract could take shape. Foundry’s suite of tools offers a streamlined workflow for smart contract development, testing, and deployment, ensuring that our code is not only functional but also battle-tested.
And when it came time to provide our contract with the power of randomness, we turned to the repositories of Chainlink contracts. With forge install, we summoned the Chainlink contracts into our project, each one a building block in the architecture of our application.
forge install smartcontractkit/chainlink --no-commitThis command is the digital equivalent of drawing water from the well of knowledge, bringing into our midst the Chainlink VRF contracts that would become the cornerstone of our Random Team Selector.
NOTE: Don’t forget your remappings!
[solidity]This update to your foundry.toml file sets the remappings for the Chainlink contracts within your Foundry project. It tells Foundry that whenever it encounters an import statement with @chainlink/contracts/, it should look in the lib/chainlink/contracts directory of your project. This is essential for ensuring that your Solidity files can correctly locate and import the Chainlink contract dependencies.
With this configuration in place, you’re ensuring that your development environment is aware of where to find the Chainlink contracts, allowing your smart contract to seamlessly integrate with Chainlink’s VRF functionality.
So, as we stand at the threshold of creation, let’s take a moment to appreciate the tools that make it all possible. Foundry’s forge is more than just a development environment; it’s a crucible where ideas are transformed into reality, where code becomes more than just instructions—it becomes a gateway to new worlds of possibility.
Now, with our stage set and our tools at the ready, let’s continue our journey into the heart of the Random Team Selector smart contract.
The Alchemy of Imports: Weaving the Magic of RandomnessIn the realm of Solidity, the import statement is akin to the summoning of allies, each bringing their unique powers to enhance our smart contract’s capabilities. In the case of our project, three such imports lay the foundation for its functionality:
import {VRFConsumerBaseV2Plus} from "@chainlink/contracts/src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";Firstly, we invoke VRFConsumerBaseV2Plus, a contract from the hallowed libraries of Chainlink. This contract is the bedrock upon which we build our trust in randomness. It’s the guardian that interacts with the Chainlink VRF, ensuring that the randomness we receive is not just a roll of the dice but a cryptographically secure and verifiable act of chance.
Next, we call upon VRFV2PlusClient, a library that serves as our conduit to the Chainlink VRF. It’s the spellbook containing the incantations needed to request and receive verifiable random numbers. This library simplifies the interaction with Chainlink VRF, abstracting the complexity of blockchain oracles into a few lines of Solidity code.
Lastly, TeamNames emerges from our own domain, a contract that holds the essence of our application—the team names. It’s the treasure chest where the potential outcomes of our random selection are stored, waiting to be matched with the random numbers provided by the Chainlink oracle.
Together, these imports form a trio of trust, randomness, and data, as a powerful digital alliance. They are the first step in our contract’s journey, the initial incantation in the spell that will bring forth the Random Fantasy Team Name Selector into existence.
So, let us continue to weave this spell, line by line, until our smart contract stands complete, ready to bring the fair and exciting game of chance to all who dare to partake in its randomness.
The Heart of the Contract: The Random Team SelectorIn the symphony of Solidity, the contract declaration is the opening note, the defining statement that brings our smart contract to life. For the Random Fantasy Team Name Selector, this declaration is the beginning of its existence:
contract RandomTeamSelector is VRFConsumerBaseV2Plus, TeamNames {Here, we declare that our RandomTeamSelector is not just any contract; it’s one that inherits from VRFConsumerBaseV2Plus and TeamNames. This inheritance is akin to a knight donning two powerful artifacts: one that grants the power of randomness and another that holds the wisdom of team names.
But every knight needs an origin, a beginning to their quest. This is where the constructor comes into play:
constructor(uint256 subscriptionId) VRFConsumerBaseV2Plus(vrfCoordinator) {The constructor is the sacred ritual that breathes life into our contract. It takes a subscriptionId—a talisman that connects us to the Chainlink VRF service—and binds it to our contract’s soul. This subscriptionId is the key to the oracle’s gate, allowing us to request randomness from the Chainlink network. You can get your own ID here:
By passing the vrfCoordinator to the VRFConsumerBaseV2Plus constructor, we establish a link to the Chainlink node that will serve as our intermediary to the oracle. It’s like setting the coordinates for a starship, ensuring that we can navigate the cosmos of randomness with precision.
With these lines of code, the Random Fantasy Team Name Selector is no longer just an idea; it becomes a living entity within the blockchain, ready to embark on its mission to bring verifiable randomness to the world.
In the coming sections, we’ll go over the building blocks that give power to our functions.
Crafting the Core: Errors, State Variables, and EventsAs we delve into the heart of the our smart contract, we encounter the elements that give it structure and purpose. Like the rules of a board game, these components define how the game is played, what moves are allowed, and what happens when things go awry.
Custom Errors: The Guardians of OrderIn the Solidity realm, errors are the sentinels that guard the gates of functions, ensuring that only those who meet the criteria may pass:
Errors:
error RandomTeamSelector__AlreadySelected();State variables are the pillars upon which the contract’s memory is built, each holding a piece of information that defines the contract’s state:
State Variables:
NOTE: Yes, I know they are hard coded. I will remedy this in part 3 :)
uint256 private constant SELECTION_ONGOING = 24;Curiosity Question: How do you know what state variables to use?
Well, in this case I just looked at the documentation on Chainlink. However, we can dig a bit further. By analyzing the contract’s requirements in terms of data storage, access, cost, logic, and security, a developer can identify the appropriate state variables to use.
The ManagerSelection struct and associated mappings are the ledger where choices are recorded, a logbook that keeps track of each manager’s journey through the selection process:
Struct:
struct ManagerSelection {The struct serves as a custom data type to encapsulate the selection process for each manager. It has two properties:
Mappings:
mapping(uint256 => address) private s_requestToManager;In Solidity, mappings are a key-value data structure that allows you to associate unique keys with corresponding values. Think of them as a collection of pairs, where each key is linked to one value.
Curiosity Question: Could you explain the structure of mappings?
The structure of a mapping is defined as follows:
mapping(keyType => valueType) visibilityModifier variableName;Curiosity Question: How do you know when to use mappings?
Mappings are typically used when you need to associate unique keys with specific values and require efficient retrieval and updating of these values. Mappings are ideal in scenarios where:
Events in Solidity are the herald’s call, announcing significant occurrences within the contract for all to hear:
Events:
event SelectionMade(uint256 indexed requestId, address indexed manager);Curiosity Question: What is theindexedkeyword in the arguments?
In Solidity, the indexed keyword in event arguments is used to enable these arguments to be searchable and filterable when looking through blockchain logs. When an argument is indexed, it creates a topic that logs can be indexed by, which allows for efficient querying. You can have up to three indexed arguments in an event.
For example, in the SelectionMade event:
event SelectionMade(uint256 indexed requestId, address indexed manager);This is particularly useful for front-end applications that need to display specific information to users, such as all events related to a particular manager or a specific request. By indexing these arguments, the application can quickly retrieve relevant events without having to process every single event log on the blockchain.
Collectively, the elements in this section form the backbone of the Random Fantasy Team Name Selector. They are the rules of engagement, the memory of the contract, and the voice that announces its actions. As we continue to explore the contract, we’ll see these elements in action, orchestrating the dance of randomness and choice.
ConclusionPhew! We’ve covered a lot so far on our journey. We looked at how the project is set up in Foundry using forge init and how chainlink contracts were installed using forge install (although their documentation has an alternative to this). We covered the imports and how the contract is set up with it's core elements such as state variables, mappings, and events. Their were also a few curious questions along the way for those of us, like me, who need a bit more understanding about how things work.
Thank you for reading! Here is what to expect with the rest of the series.
The code lives here, on Github.
ReferencesHere are a list of references and materials I have used.
Chainlinl VRF Supscription App
Building Randomness with Chainlink VRF was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.
All Rights Reserved. Copyright , Central Coast Communications, Inc.