First Attempt on Vyper

KC Tam
Coinmonks
7 min readJan 16, 2019

--

Overview

Solidity is the de-facto contract coding language in Ethereum world. However since her birth people keep finding problems in this coding language, and are asking for a better one. Vyper currently begins getting more spotlight.

This document is by no means an in-depth comparison between the two contract coding languages in Ethereum. Rather, I try to take a sample application to make a practical comparison, and see the difference when the same logic is written into these two languages. After compilation, as long as the logic is correct, the contract deployment and interaction should be the same no matter which coding language is used. Therefore I walk through several test cases using the bytecode from Vyper-coded contract.

Hope this serves as the first encounter for those who have not yet seen Vyper, and can arouse some of their interests to further explore on this new contract language in Ethereum world.

Contract to be Built: Open Auction

This is a very simple application. Open Auction assumes something to be sold publicly through auction, and anyone (with their Ethereum accounts) can bid it with their own ethers.

When the contract is deployed, we need to specify two pieces of information:

  • Beneficiary, who will collect the highest bid after the auction time is over. This is represented by an Ethereum address.
  • Auction time (in second), which is the period for the auction. Bid is accepted when it is still in the auction period, and rejected when it is over. The bid is transferred to the beneficiary only after the auction period.

During the auction time, the contract is open for bidding, and keeps track the highest bid and the bidder as its state variables. When it sees a bidder with a higher bid, the contract will refund the previous highest bid to the previous bidder, and keeps the new one. The contract simply rejects bid lower than the current highest bid.

Note: it is by no means the best and the most optimized implementation of an auction contract. There is much discussion on how to make an auction contract better and more secure. This is just a minimal contract to demonstrate the basic operation for an auction.

Note: this contract code is adapted from the example in Vyper (link) and from a video from Blockgeeks (link).

Contract Code: Side-by-Side

Similar Structure

The structure of Solidity and Vyper is very similar, and can be easily divided into three parts,

  • State variables: where one can define the variables for the contract. These variables are kept permanently in the storage trie of the deployed contract, and can only be updated through invoking contract functions.
  • Constructor: the creation code that is executed once when the contract is deployed. It is used to initialize the state variables.
  • Functions: one or more functions are being invoked through transactions after contract deployment. Once invoked, the code in the function is executed (on EVM) and the state variables and other states are updated accordingly.

Here is how the logic is implemented using the two coding languages.

Just a quick comparison between the two languages,

  • The coding format of Solidity is JavaScript-like (arguably), while Vyper is obviously Python-based. See how to define constructor and functions, and how to refer a state with self.
  • There are more data types defined in Vyper, such as timestamp, timedelta, wei_value, etc.
  • Visibility (like public, private) and other keywords such as payable are coded as annotation in Vyper.

Of course there are much more difference when comparing the code, but these are just what what we observe in these two contracts side by side.

Compilation and Deployment

Like any coding languages in other domains, both Solidity and Vyper come with its own compiler. The objective of compilation is to generate two pieces of information for contract deployment: Application Binary Interface (ABI) and Bytecode.

  • ABI: it is used when we interact with a deployed contract in a human way (application with SDK or command line)
  • Bytecode: it is the machine code containing the instructions, and is being executed by EVM when deploying contract and invoking functions.

The tools I am using for code compilation is

Bytecode truncated in both contracts

We will not do a byte-by-byte comparison between their ABI and bytecode, as we do not expect both are generating identical codes. We also will not draw a conclusion on bytecode size and therefore gas consumption, as currently we have only one contract without going into very detail analysis. Nevertheless, as far as we can achieve the same logic through executing functions, we just assume both are working fine.

The deployment of bytecode is the same for both Solidity-coded contract and Vyper-coded contract. Remember, both bytecodes will deliver the same functionality and logic, and EVM does not care what coding language the bytecode is developed from.

Testing with Ethereum Simulator and Geth Client

To demonstrate the compiled result, we are going to deploy the contract. Here are the steps we are going to perform.

As both yields the same result, here I just place captured screen shots for code in Vyper.

My screen is split into two: the right-hand-side is the ganache-cli Ethereum simulator, and it comes with 10 Ethereum accounts, each of which has 100 ethers.

The left-hand-side is where I deploy contract and interact with the deployed contract.

Step 1

First we define the variable abi and bytecode. Then use the command eth.contract().new to deploy the contract. Note that eth.accounts[9] is the beneficiary and the auction duration is 600 seconds (10 minutes).

> eth.contract(abi).new(eth.accounts[9], 600, {from: eth.accounts[0], data: bytecode, gas: 1000000})

We obtain the contract ID from the ganache-cli windows. Now we define an object openAuction to this deployed contract. We use openAuction to interact with this deployed contract.

> var openAuction = eth.contract(abi).at(<contract address>)

At the beginning we see the Auction Start and Stop time (in seconds). Date.now() gives us the current time (in milliseconds). It is smaller than the Auction Stop time, meaning that we are still in the auction period.

Also we see the highest bid is currently zero, and no bidder submits the bid yet.

Step 2

Bidder eth.accounts[1] submits a bid with 10 ethers. The transaction is being processed. Now the Highest Bid and Highest Bidder reflects this bid. Note that eth.accounts[1] balance is ~90 ethers, which is 10 ethers less than the previous balance (plus some gas consumed for bidding transaction).

Step 3

Another bidder eth.accounts[2] submits a bid with 15 ethers. After transaction is executed, the Highest Bid and Higest Bidder reflects this new bid. As expected, 15 ethers are taken as bid from eth.accounts[2], while eth.accounts[1] gets back the fund as it is no longer the highest bid.

Step 4

Another bidder eth.accounts[3] tries to bid with a value 12 ethers, which is less than current highest bid (15 ethers). The result is a revert per our contract code (assertion). Meanwhile, the Highest Bid and Highest Bidder remain as Step 3.

Step 5

eth.accounts[0] tries to execute the endAuction() function, which calls for an end of auction. However it is again a revert as the auction time is not over yet. Current time is still less than the Auction Stop time.

Step 6

After the auction time is over (see current time is now larger than the Auction Stop time), eth.accounts[0] now can execute the endAuction() function. Per the code design, the state variables ended is now True, and the highest bid (15 ethers) is transferred to the beneficiary (eth.accounts[9]).

Step 7

After the auction time is over, if any account tries to submit a bid, revert happens as the bid is accepted only in the auction period (assertion).

Step 8

If anyone tries to execute endAuction() again, revert happens, as the whole auction has already ended.

Closing and Further Reference

The structure of Vyper is almost the same as Solidity (and in fact all smart contract coding in other blockchain frameworks looks quite similar at all). Using Vyper’s compiler we can get back both the ABI and bytecode, and deploy and interact with the contract with our normal way.

If you are interested to know more about Vyper, there is a resource list in this site. Don’t forget that Vyper is still in beta and there will be evolvement over time.

Get Best Software Deals Directly In Your Inbox

--

--