Blog

How to Write Your First Smart Contract

If you’re reading this blog, I hope you’re as excited as we are to write, deploy, and interact with your first smart contract! In the first blog of this series, we introduced you to the Web3 ecosystem, which incorporates blockchain technologies, token-based economics, and decentralization.

In this blog, we’ll put what we learned into practice, creating a basic Web3 project by writing a smart contract, deploying it to an available Ethereum testnet, and building a Web app to interact with the smart contract.

By the end of this blog, we will have a basic Ethereum smart contract, written in Solidity, ready to be deployed. In the next blog, we’ll discuss how to deploy the smart contract to the blockchain. For now, let’s get started on creating a smart contract. 

Building a smart contract

The best place to start is by defining what we want to accomplish with the smart contract, including the use cases for it. In our example, our smart contract will be for coffee tokens. To support that, we need to provide for three key use cases:

  • Sell tokens
  • Consume tokens 
  • Get the current number of tokens of a specific user  

For this blog, we’ll focus only on selling tokens. The good news is that the work we do for that use case will cover all the basics we need to support the other use cases as well.

Create a workspace

1. Open Remix IDE from here.

a. Remix is an online tool that allows the developing, deploying, and administering of smart contracts for Ethereum blockchains. It can also be used as a learning platform. 

2. Click on Sure and then Done.

3. Create a new workspace called CoffeeShop using the default template. 

4. Under CoffeeShop, inside the contracts folder,  click on create new file.

5. Rename it as CoffeeShop.sol.

6. Optional: Delete all the auto-generated example contracts created by Remix as shown below. 

 

image1.png

Now, we’re ready to write a smart contract. 👨‍💻🚀

Write the smart contract 

1. Define SDPX-License. 

a. MIT in this case 

2. Declare first the solidity version in the smart contract. 

This is an essential step because Solidity is a new language and is subject to continuous improvement on an ongoing basis. A mismatch between versions can break the whole contract, so we must ensure we are using the same version.

a. Note that pragma is a directive specifying the compiler version.

//SPDX-License-Identifier: MIT pragma solidity ^0.8.17;

3. Define the main contract named CoffeeShop.

Similar to javascript classes, Solidity has a contract. A contract holds states and has methods. 

Use the contract keyword followed by the name of the contract; in this case, use the “CoffeeShop” keyword.

//SPDX-License-Identifier: MIT pragma solidity ^0.8.17; contract CoffeeShop{    ... }

4. Declare the first state variable.

Solidity is a statically-typed language, meaning you must specify each variable’s type. There are many variable types, but for this exercise, we’ll use uint for integers.

To keep track of the number of available coffee tokens, we create a variable called availableCoffeeTokens.

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract CoffeeShop{
     uint public availableCoffeeTokens = 20 // number of available coffee tokens to sell
}

5. Declare a second state variable to represent the price of the token. 

The price is declared in ether, 1 ether. In this example, each coffee token costs 1 ETH (a little expensive, I know…)

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract CoffeeShop{
     uint public availableCoffeeTokens = 20 // number of available coffee tokens to sell
     uint public coffeePrice = 1 ether // 1 ETH
}

6. Declare the last state variable using a map. We’ll map tokens to addresses or said another way, assign coffee tokens to addresses using this syntax:

mapping(KeyType => ValueType) VariableName

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract CoffeeShop{
     uint public availableCoffeeTokens = 20 // number of available coffee tokens to sell
     uint public coffeePrice = 1 ether // 1 ETH
     mapping(address => uint) public soldCoffeeTokensArray 
}

7. Now we write our first function called buyToken

This function will allow users to buy coffee tokens. It will take an input parameter amount representing the number of tokens the user wants to buy. It needs to be public to be called externally (from apps, wallets, and other smart contracts). 

Note that the payable modifier indicates that this function can receive Ether. This is crucial! ​​Imagine how bad it would be if someone sent Ether to a contract, and the developer didn’t write code to handle that event. In such a scenario, the Ether may become permanently inaccessible or the intended recipient may never be able to withdraw it! 

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract CoffeeShop{
     uint public availableCoffeeTokens = 20 // number of available coffee tokens to sell
     uint public coffeePrice = 1 ether // 1 ETH
     mapping(address => uint) public soldCoffeeTokensArray 
   function buyToken(uint amount) public payable {
     …
   }
}

8. Add ‘require’statements so that the buyToken function can validate that the user has sent enough Ether to purchase the desired number of tokens and that there are enough tokens available for sale. 

This is a straightforward statement that returns a Boolean value that is either true or false. If the specified condition returns a true value, it allows the code to flow and function accordingly; if not, it throws an error and stops the code.

The ‘require’ statement takes two parameters:

• The condition that you want to check 

•  An optional error message that you want to show the user if the value returned is false. While this is optional, it’s very important for good UX!

require( condition , message ) 

a. For our exercise, the first parameter is availableCoffeeTokens >= amount to check that enough coffee tokens are available for the user. 

b. The second one is a little more tricky because we need to access the value of ETH sent by the user first, using ‘msg.value,’ where ‘msg’ is the current call and ‘value’ represents the ETH sent by the user.

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract CoffeeShop{
    …
   function buyToken(uint amount) public payable {
     require( availableCoffeeTokens >= amount, "Not Enough Coffee Tokens, 
     aborting" ); // checks if there are enough coffee tokens!
     require( msg.value == (amount * coffeePrice), "Not Enough Eth, aborting" ); 
     // checks if the correct amount of ETH is being received
     …
   }
}

9. Now update state variables. The number of coffee tokens bought by the user must be assigned to their address, and the total number of available coffee tokens needs to be decreased.

a. Start by assigning coffee tokens to the user address. 

i. To get the user address, we will use ‘msg.sender,’ where ‘sender’ is the user’s address calling the function. 

ii. Use ‘soldCoffeeTokensArray[msg.sender] += amount’ to assign user tokens to that user address.

b. Now decrease the number of available coffee tokens with the number of tokens purchased.

i. Use ‘availableCoffeeTokens -= amount’ as shown:

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
contract CoffeeShop{
    …
   function buyToken(uint amount) public payable {
     require( availableCoffeeTokens >= amount, "Not Enough Coffee Tokens, 
     aborting" ); // checks if there are enough coffee tokens!
     require( msg.value == (amount * coffeePrice), "Not Enough Eth, aborting" ); 
     // checks if the correct amount of ETH is being received
     soldCoffeeTokensArray[msg.sender] += amount; // updates the mapping with the number of tokens purchased
    availableCoffeeTokens -= amount; // updates the available tokens
     …
   }
}

10. Now that the smart contract is ready, we can compile it and confirm that it works. 

a. Go to the COMPILER tab in the left navigation bar. 

b. Click on Compile CoffeShop.sol

image2.png

With a successful compilation, the smart contract is ready to be deployed to the blockchain. In the next blog, we will walk through how to deploy it to a proper testnet.

Keep exploring smart contracts and decentralized applications  

Smart contracts are powerful tools that enable secure and automated transactions. In this blog, we covered the basic syntax of Solidity, discussed the main features of the contract, and provided step-by-step instructions on how to write it. At this point, you should have a better understanding of how to create a smart contract and feel inspired to explore the world of decentralized applications further. If you’re ready to dive in, here’s the link to the contract code! 

And finally, always remember to keep your smart contracts bug-free, just like your coffee! ☕

Ready to be Unstoppable? Partner with Gorilla Logic, and you can be.

TALK TO OUR SALES TEAM