Deploy a Lottery Smart Contract with Coinbase Cloud's Node
November 7, 2022
In this tutorial, you will learn how to write a smart contract and how to use the Node product from Coinbase Cloud to deploy the smart contract on Ethereum's Goerli network.
Let's simplify this into three simple steps.
1) Writing a smart contract
2) Compiling the smart contract
3) Deploying the smart contract on the Goerli network.
Ethers: npm install ethers
Solidity Compiler: npm install solc
Goerli Ethereum testnet token faucet, to use for gas fees
Coinbase Cloud Goerli Node: https://www.coinbase.com/cloud
Writing a smart contract
Simply said, a "smart contract" is a program that runs on the Ethereum blockchain, and it is a set of functions and state-related data stored at a particular address on the Ethereum blockchain. Smart contracts have an address on the Ethereum blockchain to have balances and perform transactions similar to User Accounts (Externally owned accounts). However, no particular user owns the contract.
Once a smart contract is deployed to the network, user accounts can communicate with it by sending transactions that carry out a function specified in the smart contract. Like a regular contract, smart contracts can establish rules and have the system automatically enforce those rules. Smart contract interactions are irreversible by default and cannot be undone.
We use Solidity, an object-oriented, high-level language for implementing smart contracts to write a smart contract.
Anatomy of the smart contract
Now that you know what a smart contract is, let's begin to build a decentralized Lottery smart contract. We will use Solidity 0.8.10 to write this smart contract.
We begin with setting a compiler version with the first line `pragma ^0.8.10`. Pragma is generally the first line of code within any Solidity file. The pragma directive identifies the version of the compiler to be used for the present Solidity file.
Then we declare the contract name, here we call it contract lottery.
We then declare the following state variables (these values are permanently stored in a contract storage).
Organizer: The External account who conducts the lottery. This is a type address as it's an external account.
Array of Players: To store the list of players (Addresses) who are participating in the lottery.
LotteryID: Setting an ID for each lottery (We can conduct many lotteries)
alreadyParticipated: This is used to avoid duplicate entries.
Winners: To store LotteryID and the winner of that lotteryID
And, lottery_state to mark the lottery OPEN or CLOSED
Next, we write the constructor. A constructor code is executed once when a contract is created and it is used to initialize contract state. The address used to deploy the smart contract becomes the Organizer, and the lottery_state is set to closed
Before we talk about the other functions, let's discuss two modifiers, onlyAdmin() and isOpen(). Function Modifiers are used to modify the behavior of a function. The function body is inserted where the special symbol "_;" appears in the definition of a modifier. So if the condition of the modifier is satisfied while calling this function, the function is executed and else, an exception is thrown. onlyAdmin modifier ensures only the organizer can invoke that function and isOpen ensures the function can be invoked only when the lottery_state is OPEN.
There are 5 public functions (meaning, whoever interacts with the smart contract can see those functions) and 2 private functions (which are not visible, and are helper functions)
open_lottery(): Executing this function will change the state of lottery_state to OPEN. This can only be invoked by the organizer.
enter(): This function can be invoked by any other address except for the organizer. You will see the payable keyword to ensure that money is being sent to the contract to participate in the lottery. Any function in Solidity with the modifier Payable ensures that the function can send and receive Ether. A minimum of 0.01 ETH is required to enter the lottery. We then populate alreadyParticipated with the participants address and map it to a boolean value true. We also add the players address to the players array.
pickWinner(seedPhrase): Smartcontracts do not have a library to randomize a number hence a seedPhrase is sent along with this method when invoking pickWinner function. We send the seedPhrase to the private randomizer function which returns a random int value which we then use to find the index of the winner from the players array. Next, we pay 2.5% of the proceeds (Ether) to the organizer and the remaining amount to the winner’s address. We then populate the winners state variable with the lotteryID and the winner address, reset values in players array and mark the addresses in alreadyParticipated map to false, and finally set the state of the lottery to CLOSED. We reset these variables for the next lottery event.
getWinners(lotteryID): To find the winner’s address using the id
getPlayers(): List all player’s addresses when this function is invoked.
You can test this solidity contract using Remix IDE (https://remix.ethereum.org/)
Compile the Smart contract
Save the above smart contract as Lottery.sol in your project’s folder, you will need the path for your compiler script. Here’s the anatomy of the compiler:
First, we are importing the required modules: fs, path, and solc
We are then taking the file path of the lottery.sol file
We are then reading the contents of lottery.sol and specifying the utf-8 encoding value
We then add a new object in the file called input that calls for requiring some keys like the source, and settings.
We then take this input, convert it into a string value and pass it to the solc compiler. This solc compiler’s output is then parsed into a JSON output.
We are then exporting the output to use it for our deployments
Deploying the Smart contract
Understanding the code:
We are using ethers to deploy to the Goerli environment.
We populate the object compiledFile with what we’ve exported from the compile file. We then extract the abi (ABI stands for Application Binary Interface. The interface is the standard mechanism for encoding and decoding data into and out of machine (Binary) code) as interface and bytecode of our smart contract as bytecode variables.
We create a connectionInfo object (link) as an endpoint object. Here we extract the Coinbase Cloud’s Node endpoint, API token username, password from the environment variables.
We then create a JsonRPCProvider using the connectionInfo.
We also create a wallet object with the deployer’s private key (note: This address who deploys will become the organizer for our smart contract).
We then write our deploy function, which does the following:
gasPrice: We are getting the gasPrice from the provider itself.
We create a new instance of a ContractFactory for the contract described by the interface bytecode, we also need the wallet object as a parameter since we’re deploying the smart contract. We pass the gas_price variable to override the value (refer: Link)
Once deployed, you will receive the contract address. Here’s an example of the address that I deployed using Coinbase Cloud’s Goerli Node: https://goerli.etherscan.io/address/0x23dEC0aa74034EC141967DaBF892c969eaA2524B
That’s it! You’re now ready to build, compile and deploy your own ethereum smart contract. To interact with smart contracts, you can simply use the address you just deployed.