Tips for Vyper Beginners

There is something you should keep in mind

Vyper is not a replacement for Solidity but provides some advanced features in security, simplicity. Vyper does not provide the dynamic type, class inheritance, function overloading, operator overloading, and recursion, modifier, inline assembly,…

The Vyper philosophy

Security: It should be possible and natural to build secure smart-contracts in Vyper. Simplicity: Vyper’s goal to build a programming language that is easily understood and audited by a lay-person. 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.

Basic of installation, syntax, and example

Vyper now is still in the experimental development stage, and official docs is where you should start first. After that follow the list provided below:

Make a call to external contracts

In smart contract development, we often call to external contracts to get state or executes. In Solidity, it is quite easy to walk around on the internet.

However in Vyper, it is still less information in some special case, that’s why I am writing this post.

Here are 2 ways in Vyper you can do this:

Declares contract interfaces and make a call like Solidity:

Interfaces can be added to smart contracts either through inline definition or by importing them from a separate file.

In addition, Vyper has built-in interfaces ERC20, ERC721, you can import with:

from vyper.interfaces import ERC20

To declare an interface, use the contract keyword as below:

# Declare contract interface FooBar with 2 function

contract FooBar:

def calculate() -> uint256: constant # get state of FooBar contract

def test1(): modifying # A call will execute and change state of FooBar contract # Function make external call

@public

def makeCall(fooBarAddress: address):

FooBar(fooBarAddress).calculate() # cannot change storage

FooBar(fooBarAddress).test1() # storage can be altered

Or you can call another contract with raw_call, a low-level built-in function that provide calls to the specified Ethereum address with function signature and data, value.

Due to Vyper does not provide the dynamic type, that's mean if you call a Solidity contract at the function with a dynamic type like uint256[], raw_call is only way to do this.

For example, you have a function in Solidity like this:

function swap(address fromToken, address toToken, uint256 amount, uint256 minReturn, uint256[] memory distribution, uint256 disableFlags) public payable;

You can not declare an interface in Vyper like the code below because Vyper does not provide dynamic type:

contract IOneSplit:

def swap(fromToken: address, toToken: address, amount: uint256, minReturn: uint256, distribution: uint256[], disableFlags: uint256) -> uint256: modifying

Or even you know the size of distribution (see the code below) and write an interface code like:

contract IOneSplit:

def swap(fromToken: address, toToken: address, amount: uint256, minReturn: uint256, distribution: uint256[4], disableFlags: uint256) -> uint256: modifying

The above code is the correct Vyper syntax but it is not swap function of OneSplit, cause function signature will be different between uint256[] and uint256[4].

The one right way so far…

So the one and the only way to make a call from Vyper to function with dynamic arguments in Solidity contract is to make a call by using raw_call function with 4 bytes signature and data, value like below:

Raw_call example

The funSig variable is a function signature of OneSplit’s swap function and data: bytes[352] is 352 bytes of data will be passed as arguments in this function.

References: