100DaysOfBlockchain #13 - Creating my first Smart Contract / Hands-on Vyper - Tutorial

in HiveCoding2 months ago (edited)

The other day I came accross an article that mentioned the importance of blcockchain development. I figured that, as any other field in software, there will be may different programming languages that we could use to improve secutiry and speed up the exchange of information while ensuring transparency.

I don't consider myself anymore a core software enginer - I shifted from that, but I still get to work and play around with many different languages on a daily basis. When researching about Smart Contracts, I obviously found information about Solidity, and OOP for writing smart contracts. I found it interesting the fact that the documentation specifies the resemblance with languages like C++, Python and JavaScript - I am familiar with all of them so I gave it a try. I don't know if the fact that I have been working mainly with Python over the past months, but it really felt somewhat difficult for me as a starting point - it is mainly similar to JavaScript - but I still managed to build small stuff (it's doable). However, remember I am also still very new to blockchain so I went and asked my Twitter followers if they knew other approaches and, of course, someone immediately let me know about Vyper.

Vyper - for what I've read so far - is the second most popular choice, after Solidity and it is targeting python developers. I started using it and I am quite happy with it, specially in terms of the syntax. Of course, I will probably run into issues later on as I think it does not have as many features as Solidity, but for the purpose of learning it will be fine. Like python itself or any python framework, I am expecting a community growth around Vyper.

Today I wanted to post a short tutorial on how to get set up with Vyper, as another learning day of the #100DaysOfBlockchain challenge.

If you want to read more about what Vyper is and dig into the documentation you can find it here.

Set up your environment

There are different ways you can set up your environment according to their documentation. I have tried in three different ways:

  1. You can simply navigate to the Vyper Online Compiler or to Remix which are browser-based IDEs.
  2. You can download Vyper as a Docker image: docker pull vyperlang/vyper and run it as docker run -v $(pwd):/code vyperlang/vyper /code/<contract_file.vy>
  3. Install it using pip: pip install vyper

I went ahead with the online IDE (Remix) to see all the process from compiling to testing the contract.

What should you build? What are we building?

There are many examples listed in their documentation and I invite you to give a look into all of them. They have many examples raging from a simple open auction to voting systems.

I will not just go over their documentation as a tutorial, but I will use this tutorial to try to build my own one - a CRUD example. Disclaimer - I am also learning from developing this turotial so if you spot any mistake or ways of improvement, I invite you to point them out in the comment section below.

The main characteristic of smart contracts is that they can eliminate the need for a third-party. You can imagine the amount of fields this approach can make an impact on: finance, healthcare, gaming, etc.

In this tutorial, I will first build a Hello World!, which to my surprise it is not included in their docs, and a short case for CRUD.

Hello World!

If you go to Solidity documentation, you can see a greeting Hello World example. The first thing I wanted to do was to create a hello_world.vy contract myself in Vyper, to understand a bit better the process, structure of the contracts, types and so on.

In Remix, I created the hello_world.vy file with the following:

greeting: public(String[100])

@external
def __init__():
    self.greeting = "Hello World!"

@external
def greet() -> String[100]:
    return self.greeting

First, you need to set the State Variables outside of any function and they contain the default value for the variable type, they are permanently stored in the contract storage. In a similar way to python, you can access them with the self object. Our state variable is greeting which will store our Hello World! string to be used as our greeting message.

Theen we have two functions. We have, in the similar way as python, the initialization function - and if you had a chance to look at the Solidity example, this resembles their constructor. The second function simply returns the greeting message, which we are going to be calling externally to return the message.

After we biuld our contract, in Remix we can easily go to the Vyper compiler tab and use the remote compiler to compile our script. This returns an **ABI**. ABI means Application Binary Interface, which it similar to an API in programming. The ABI basically defines methods and structures that are used to interact with the contract and it does it in a way that it is readable by the EVM (Ethereum Virtual Machine).

Once this is OK - you can proceed to deploy your contract and test under the Deploy & run transactions tab in Remix. You should be able to see your deployed contract and test it as in the picture.


CRUD application

If you are not familiar with this term, CRUD refers to create, read, update and delete, which are four very necessary functions to implement a storage application.

I created a small application for storing users with an id, name and created time.

I guess this is the most simple application that someone can create - just after Hello World 😂 This is how the end script looks like, I will go through it in detail.

struct User:
    name: String[100]
    created: uint256

users: HashMap[int128, User]

nextUserId: int128

@external
def __init__():
    self.nextUserId = 0

@external
def create_user(_name: String[100]):
    nid : int128 = self.nextUserId
    self.users[nid] = User({name: _name, created: block.timestamp})
    self.nextUserId = nid + 1
    
@external
def read_user(_id: int128) -> (String[100], uint256):
    return (self.users[_id].name, self.users[_id].created)
    
@external
def update_user(_id: int128, _name: String[100]):
    self.users[_id].name = _name
    
@external
def delete_user(_id: int128):
    self.users[_id].name = ""
    self.users[_id].created = 0

The first thing I did was to create struct - just like in "regular" programming, to store two variables: the name of the user and the created time. I was considering adding a id to it, but since I created a users variable that already has a key in it, it felt redundant to add an extra id - the key will serve as it. The key corresponding to each struct in the users mapping is represented by the nextUserId variable, which is going to be incremented with every new added user. This will be set to zero at the time of contract initialization.

The next will be the rest of the functions:

  • create_user: to create a new user by simply specifying the name. The id and created time will be set automatically at time creation. To show how how it works, I have created two users: AI and Coding.

  • read_user: to retrieve a specific user's information. You need to specify the id of the user.

  • update_user: to update the information of a user. In this case, only the name is allowed to be updated. In the future, we can just have an extra varibale called lastUpdated to keep track of the time when the user was last updated. You can read the user again to double check that it has been updated.

  • delete_user: I was reading about the possibilities to delete a user, but I guess it makes sense that this possibility is removed completely. I couldn't find a better way to deal with this - so far - but by just "emptying" the variables of a user. If you have any better ideas on how to deal with this, I would like to know!

This is pretty much it! To be honest, for the time that I could dedicate to this today, it has been a huge progress. Vyper is certainly very easy to use. I will keep digging into the documentation and learning a bit more about this language and its usecases and will come up with more tutorials!

vyper.webp

Sort:  

Congratulations @aicoding! You have completed the following achievement on the Hive blockchain and have been rewarded with new badge(s):

You published more than 80 posts.
Your next target is to reach 90 posts.

You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word STOP

To support your work, I also upvoted your post!


The rewards earned on this comment will go directly to the person sharing the post on Twitter as long as they are registered with @poshtoken. Sign up at https://hiveposh.com.