Understanding Vyper: The slick New Ethereum language
A comprehensive guide on Vyper, the slick new Ethereum language
Vyper is a general-purpose, experimental programming language that compiles down to EVM (Ethereum Virtual Machine) bytecode, as does Solidity. However, Vyper is designed to massively simplify the process in order to create easier-to-understand Smart Contracts that are more transparent for all parties involved, and have fewer points of entry for an attack.
Any code targeting the EVM must be hyper-efficient to minimize the gas needed for Smart Contracts to execute, as a contract with inefficient code literally costs more ether to execute, and can quickly become prohibitively expensive, especially in use-cases such as micro-transactions. The end result is that Vyper looks logically similar to Solidity, and syntactically similar to Python, but without many of the Object Oriented Programming paradigms – perhaps requiring a new paradigm definition for transactional programming.
Learning these logical and syntactical differences now will help you become a world-class Vyper developer since Vyper is still in v0.1.0-beta.1 as of June 2018!
0. Comparing Python, Vyper, and Solidity
Here, we cover the high-level “why” of Vyper – providing a spring point for us to analyze and write Vyper code, including Smart Contracts.
Key Improvement 1: Simplicity
Vyper does not contain many of the constructs familiar to most programmers: Class inheritance, function overloading, operator overloading, and recursion. None of these are technically necessary for a Turing-complete language, and they represent security risks by increasing complexity. Due to this complexity, these constructs would make Smart Contracts too difficult to understand and audit by a lay-person, seen in Solidity contracts.
Less common constructs that are also not included are modifiers (these make it too easy to write misleading code), inline assembly (this breaks Ctrl+F), and binary fixed point (approximations are often required with a binary fixed point).
Key Improvement 2: Security
In the words of Vyper developers themselves, Vyper
“will deliberately forbid things or make things harder if it deems fit to do so for the goal of increasing security.”
Therefore, Vyper is not an end-all-be-all replacement for Solidity, but rather a great language to use wherever security is paramount, such as for Smart Contracts handling patient health metadata or model gradients for Decentralized AI.;pp0
Vyper Code and Syntactical Differences
Vyper was built to be as similar to Python as possible while striving for the goals of security and simplicity, so the overall feel of the languages is the same, though there are many differences to take note of.
Executing a File
While a Python script is executed as
,a vyper script is compiled using
State variables are values permanently stored in contract storage and can be of any type, such as:
The first thing a Vyper contract contains is the contract storage fields, such as a token balance mapping:
which is a state variable that defines keys and corresponding values.
Vyper mappings are basically hash tables that are initialized, as seen above, so that
“every possible key exists and is mapped to a value whose byte-representation is all zeros: a type’s default value.”
The key data is not stored in the mapping, but just its keccak256 hash to look up its value.
In defining balance, the type public() is given, followed by the mapping syntax:Where the value type of wei_value is given first, followed by the key (address) in square brackets – similar to Python’s handling of arrays.
You’ll notice that Vyper uses a colon in defining names (like balance) as opposed to Python’s equal signs, although Python 3.6 includes the same syntax for variable annotation:
Where the colon syntax is for variable annotation, and the colon is used as the assignment operator that assigns just a type annotation only. Vyper uses this syntax for true value assignment.
Vyper has just two integer types: uint256 (for non-negative integers) and int128 (for signed integers) — as opposed to Solidity’s uint8 to uint256 in steps of 8, and same for int8 to int256 (this means 64 different keywords for int types).
Booleans, Operators, Comparisons, and Functions
Vyper has nearly identical syntax to Python for most operators, including:
As well as some similar built-in-functions:
And some new ones:
Lists in Vyper are declared using the format _name: _ValueType[_Integer], while setting the values and return statements have the same syntax as Py=thon.
Structs are types that you define, which group variables, and are accessed using struct.argname, as so (somewhat similar to Python dictionaries):
Methods (contract methods in Vyper) are defined the same way in Python and Vyper:
In addition to what Python provides, Vyper includes Ethereum-specific decorators such as @payable and @assert – the former used to make the contract able to take transactions and the latter taking a boolean expression:
Notice the def function_name(arg1, arg2, …, argx) -> output: syntax to define a function. Unlike in Python, Vyper explicitly defines the output type in the def line after the ->.
Constructor Functions go by the same convention as Python and instantiate a given contract and parameters on the blockchain. The init initializes the program and is executed only once. For example:
As in Python, self is used to assert instance variables. The above function is decorated with the @public decorator to give it public visibility and allow external entities to call it (as opposed to the default — or leaving out the decorator — which is private).
The decorator @constant is used to decorate methods that only read a state, while @payable makes any method able to be called with a payment.
You can log events using __log__ in indexed structures, as so:
Writing Vyper Contracts
Now, let’s write a couple simple Smart Contracts. The following code snippet allows the contract to receive an NFT (non-fungible token) and be able to send against that token.
The following demonstrates the @public decorator, defining a function with a single parameter that is explicitly given a type, and a simple code body using assert statements to verify if a user has the right to vote as part of a “voting with delegation” program:
Having discussed the syntactical and logical distinguishments, the code isn’t too intimidating. vyper.online offers the entire source code for the “voting with delegation” program, using structs for voters and proposals, and the following aptly-named functions:
As with any programming language, planning out the major constructs (in this case, function contracts) beforehand makes the programming much easier. The major difference in Vyper to keep in mind is the lack of OOP paradigms. In the current stage of development, you cannot yet make external code calls.
The considerations for allowing external code calls can be seen in the following development suggestion:
# External contract A:
Where contract B calls on contract A, including methods within A, in the simplest example possible.
To follow along writing code, go to vyper.online, and write the code examples under the “Source Code” tab and click “Compile” when ready. The most used client (though in pre-alpha) for Vyper implementation and test-execution is Py-EVM, developed initially by Vitalik himself, which allows the user to add opcodes or modify existing ones without changing the core library, enabling far greater modularity and extensibility than with a typical client.
To get Py-EVM, just use pip install py-evm==0.2.0a16.
3a. Deploying Vyper Contracts
While Py-EVM is currently in pre-alpha and may be difficult to get up and running, there are two simpler alternatives to deploying Vyper contracts to public testnets (and a bonus):
1) Paste the bytecode generated from vyper.online into Mist or geth
2) Use the myetherwallet contract menu to deploy in the current browser 3) (Upcoming)
In the future, Vyper will integrate with populus, allowing you to easily deploy Vyper contracts
For simplicity’s sake, we’ll deploy contracts using option (1) and Mist (a fresh UI on top of geth as opposed to the terminal-based geth). Since Vyper compiles down to the same Bytecode as Solidity, we don’t need any Vyper-specific clients, and can follow these somewhat-roundabout steps:
- Go to vyper.online and click “Compile” on the pre-filled voting “Source Code”
- Copy everything under the “Bytecode” tab
- Install Mist for your OS, if you haven’t already
- Allow the node to download and sync (this happens automatically)
- Select “USE THE TEST NETWORK” in the Mist setup
- Create a password (and remember it…)
- Input the Contract
- Select “Contracts” in the Mist interface
- Select “DEPLOY NEW CONTRACT”
- Go to the “CONTRACT BYTE CODE” tab
- Paste in the Bytecode you copied from vyper.online
Deploy the Contract
- Select “DEPLOY” and enter the password from earlier
- Confirm the Vyper contract has been deployed
- Go to the “Wallets” tab in Mist
- Scroll down to “Latest Transactions”
- You should see the contract we just deployed!
*Although in the“Creating Contract” state as it’s not being mined and validated
This guide provides a logical and syntactical introduction to Vyper, allowing us to begin programming and deploying contracts. With the knowledge from this guide, you should be able to contribute to the development of Vyper, its documentation, and continue to learn by coding at vyper.online.
Again, Vyper is not meant to replace Solidity, but as one study found over 34,000 vulnerable contracts, the need for stronger security in this space is greater than ever, giving Vyper an important future in Ethereum
Further Reading and Roadmap
As Vyper is still in experimental development, the official documentation and GitHub are the most comprehensive resources, with the following providing value as well:
01.Vyper’s Community Gitter
02.Vyper Tools and Resources
03.“Ethereum Book” pages on Vyper
04.Study: “Finding The Greedy, Prodigal, and Suicidal Contracts at Scale”
05.“Step-by-Step Guide: Getting Started with Ethereum Mist Wallet”
07.Testing and Deploying Vyper Contracts
08.“Build Your First Ethereum Smart Contract with Solidity — Tutorial”[Generalizing the steps to fit Vyper is fairly straightforward]
Vyper’s development steps to version 1.0 focus on interfaces (as well as improvements in internal and external calls, among others), which define constraints so you can communicate with any object implementing that interface. Interfaces enable alternative solutions to upgrading Smart Contracts, so they’re not necessary for basic functions, and you can begin coding in Vyper although the language is incomplete.
The development roadmap to version 1.0, retrieved and edited from Vyper’s gitter:
01.Two types of files: interfaces (one interface per file) and contracts (one contract
02. You can define an interface like ERC721Metadata in an interface file and also in
a contract file.
03. The interface file is one-to-one fully compatible with the Ethereum ABI.
04. Write a translator from Solidity to Vyper interfaces.
05. Make a library of all the final ERC interfaces, even if you have to manually make
06.Import interfaces from the interface files to contracts.
07. An interface is a type which decorates an address.
08. Interfaces can inherit other interfaces.
09. Carefully study interface IDs from ERC-165 and reproduce the examples given in
ERC-721 this relates to how interfaces inherit other interfaces.
10. Interfaces may have optional functions. (A break from solidity.)
11. Contracts can implement interfaces.
12. A contract that implements an interface but does not implement a required
function is an ERROR.
13. A contract that implements an interface but does not implement an optional
function is neither an ERROR nor a WARNING.
14. Rename @public to @external to match Solidity.
15. Introduce a new function decorator @internal which allows a function to be called
16. Reintroduce the function call syntax currently used for external calls (removed in
step 14) but have it apply to internal calls.
17.Implement external calls like this: External jump call table -> LOADCALLDATA
unpack -> add function parameters to stack -> call internal function -> do function
18. Implement internal calls like this: add function parameters to stack -> call internal
function -> do the function stuff.
As you can see from the code we’ve written, Vyper is making big strides in its development, and has just a few major updates (broken into the smaller steps above) until 1.0 is released!