Share and get +16 +16



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!

Understanding Vyper

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

python file_name . py

, a vyper script is compiled using

vyper file_name . vy .

State Variables

State variables are values permanently stored in contract storage and can be of any type, such as:

exampleStateVariable: int256 .

Mapping

The first thing a Vyper contract contains is the contract storage fields, such as a token balance mapping:

balance: public(wei_value[address])

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.

Definitions

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:

context = {} # empty dictionary context["a"]: 2 # annotate dictionary variable

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.

Integer Types

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:

true and false booleans; not , and , or , == , and != operators; < , <= , == , != , >= , and > comparisons; and + , - , * , / , ** , and % arithmetic operators (only for int128)

As well as some similar built-in-functions:

len (x) to return the length of an int ; floor(x) to round a decimal down to nearest int ; and ceil(x) to round a decimal up to the nearest int

And some new ones:

sha3(x) to return the sha3 hash as bytes 32 ; concat(x, ... ) to concatenate multiple inputs; slice (x, start = _start, len = _len) to return slice of _len starting at _start

Lists

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.

For example:

lst: int128[ 3 ] # define a list lst = [1, 2, 3] # set the values lst[2] = 5 # set a value by index return lst[0] # returns 1

Structs

Structs are types that you define, which group variables, and are accessed using struct.argname, as so (somewhat similar to Python dictionaries):

struct: { # define the struct arg1: int128, arg2: decimal } struct . arg1 = 1 #access arg1 in struct

Defining Methods

Methods (contract methods in Vyper) are defined the same way in Python and Vyper:

def method (): do_something()

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

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:

@public def __init__ (_name: bytes32, _decimals: uint256, _initialSupply: uint256): self . name = _name self . decimals = _decimals self . totalSupply = uint256_mul(_initialSupply, uint256_exp(convert( 5 , 'uint256' ), _decimals))

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.

Events

You can log events using __log__ in indexed structures, as so:

payment: __log__({amount: uint256, param2: indexed(address)}) tot_payment: uint256 @public def pay (): self . tot_payment += msg . value log . payment(msg . value, msg . sender)

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.

@public def safeTransferFrom (_from: address, _to: address, _tokenId: uint256): self . _validateTransferFrom(_from, _to, _tokenId, msg . sender) self . _doTransfer(_from, _to, _tokenId) if (_to . codesize > 0 ): returnValue: bytes [ 4 ] = raw_call(_to, ' xf0xb9xe5xba ' , outsize = 4 , gas = msg . gas) assert returnValue == ' xf0xb9xe5xba '

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:

# Give a voter the right to vote on this ballot # This may only be called by the chairperson @public def give_right_to_vote(voter: address): assert msg . sender == self . chairperson # throw if sender is not chairperson assert not self.voters[voter].voted # throw if voter has already voted assert self.voters[voter].weight == 0 # throw if voter's voting weight isn't 0 self . voters[voter] . weight = 1 self . voter_count += 1

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:

def delegated (addr: address) -> bool def directly_voted (addr: address) -> bool def __init__ (_proposalNames: bytes32[ 2 ]) def give_right_to_vote (voter: address) def forward_weight (delegate_with_weight_to_forward: address) def delegate (to: address) def vote (proposal: int128) def winning_proposal () -> int128 def winner_name () -> bytes32

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:

def foo (): constant def bar (): modifying # This contract contract B: a: A def baz(): a.foo() a.bar()

Where contract B calls on contract A, including methods within A, in the simplest example possible.

Running Vyper

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

Conclusion

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

per file).

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

them.

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

internally.

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

stuff.

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!



