A day with Vyper
Few days ago, in order to proceed with the registration of my certification, I received an email from B9Lab ask me to send an EOA address or a contract address that represent me.
This sounds like a good opportunity to check three items of my to-do list:
1. Write my first article on medium
2. Write a smart contract in Vyper
3. Check the actual integration of Vyper in a Truffle environment.
Let’s start this day with Vyper!
Why Vyper
Before ask why Vyper, let us examine what is a Smart Contract. It’s a Microservice with some functions to call in order to store and read stuffs in a decentralized environment? Yes of course It is. But from a non technical point of view a Smart Contract is a deal between a machine and the rest of the world. A deal to work in a certain way as long as the network lives.
With this principles in mind a Smart Contract should be easy to write but must be easy to read.
From the Doc:
Simplicity for the reader is more important than simplicity for the writer, and simplicity for readers with low prior experience with Vyper (and low prior experience with programming in general) is particularly important.
Simplicity first will mean that Vyper doesn’t have: Modifiers, Class inheritance, Inline assembly, Function overloading, Operator overloading, Recursive calling, Infinite-length loops and Binary fixed point.
Install Vyper
I’m on MacOS, for different OS click here.
Prerequisites:
Vyper is still in beta version, so we will install It in a virtual python environment.
Virtual environment:
$ sudo apt install virtualenv$ virtualenv -p python3.6 — no-site-packages ~/vyper-venv$ source ~/vyper-venv/bin/activate
Vyper:
$ git clone https://github.com/ethereum/vyper.git$ cd vyper$ make$ make test
Project Setup
We will use the init
option of Truttle to scaffold our project.
Fist we have to install Truffle:
$ npm install -g truffle
Create and move to new folder:
$ mkdir identity-test && cd identity-test
Init the project:
$ truffle init
Write Identity Contract
The project’s purpose is to write a basic identity contract that represent who I am. My basic identity is made up by: name, surname and age, nothing more and nothing less than that.
In contracts folder create a file named Identity.v.py ( yes we can use python syntax highlighter).
Declare five public variables:
- owner is the owner’s address that create the contract
- firstname and surname are bytes32 representation of the name and surname.
- birth is a int128 represent a birth’s timestamp. ( if I use negative timestamp — date before 1970 — ,
assert birth < block.timestamp
revert my transaction, write in comment if you know why). - creationTime timestamp represent the date when identity is created.
Declare a creation Event:
Constructor:
We define:
- a public __init__ function that takes: firstname, surname and birth.
- we check that our function parameters are not empty ( N.B.
assert not not _firstname
is equal toassert _firstname != 0x000000000000000
) - we define our public variables.
- we log the Creation event
First name Update Function:
Here we update firstname if: (i) is not empty, (ii) the transaction is from the owner and (iii) the new name is not equal to old one. At the end we return back new name.
Fallback function:
Fallback functions are triggered when the function signature does not match any of the available functions or when someone try to send ether to our contract.
If someone try to send ether to our contract we send It back.
Truffle Integration
Truffle doesn’t yet support Vyper contracts so we need some tool to compile Vyper to Truffle’s compatible artifacts. Truper save us!
Install Truper:
$ npm install -g truper
Create a package file:
$ npm init
Into scripts field add the following scripts:
"scripts": { "build:sol": "truffle compile", "build:vyper": "truper", "build": "npm run build:sol && npm run build:vyper", "console": "truffle console", "migrate:ganache": "truffle migrate --network ganache", "migrate:mainnet": "truffle migrate --network mainnet", "test": "truffle test"},
Now we can run the build task to build vyper and solidity contract into /build folder (N.B. remember to run It into virtualenv).
$ npm run build
Test
One of the most interesting thing about our Truffle integration is that we can easily test our code.
Create a new file Identity.test.js into test folder.
$ npm install moment bluebird
Now we test our constructor function:
In order to test our constuctor we have two main “blocks”:
- Fail Case: We test if contract creation fail (i) with an empty value and (ii) if we sand value in transaction.
- Success Case: We test if first name, surname, owner and birth have correct values. Notice we have to convert bytes32 in utf8 with
web3.toUtf8()
and bigNumber into string withtoString(10)
UpdateFistName test:
- Fail Case: We test if function fail with (i) transaction from a non owner address (ii) new name is empty and (iii) new name is equal to old name.
- Success Case: We test if new first name has new value.
Fallback test:
Fallback function send back transaction value excluding transaction fee, so we check the balance of the sender at the beginning and at the end of transaction.
Now run $ npm run test
Deploy To Main net
Now we doploy our contract to the main net. I will use Infura as connection provider to Ethereum.
First we have to install HDWalletProvider to handle the transaction signing as well as the connection to the Ethereum network.
$ npm install truffle-hdwallet-provider
Next in truffle.js we have to setup our wallet provider:
- mnemoric: is the 12 seed words of your wallet.
- infura api key: key after you sign up to Infura.
- gasPrice: check Eth Gas Station to know the current gas price (N.B. gasPrice is in wei, ethGasStation in Gwei).
Run $ npm run migrate:mainnet
Thet’s all. See you soon! :)