Coder Social home page Coder Social logo

vyperlang / vyper Goto Github PK

View Code? Open in Web Editor NEW
4.8K 167.0 778.0 10.81 MB

Pythonic Smart Contract Language for the EVM

Home Page: https://vyperlang.org

License: Other

Python 99.77% Makefile 0.09% Dockerfile 0.05% Batchfile 0.07% Shell 0.02%
vyper language python ethereum ethereum-dapp

vyper's Introduction

Build Status Documentation Status Discord

PyPI Docker

Coverage Status Language grade: Python

Getting Started

See Installing Vyper to install vyper. See Tools and Resources for an additional list of framework and tools with vyper support. See Documentation for the documentation and overall design goals of the Vyper language.

See learn.vyperlang.org for learning Vyper by building a Pokémon game. See try.vyperlang.org to use Vyper in a hosted jupyter environment!

Note: Vyper is beta software, use with care

Installation

See the Vyper documentation for build instructions.

Compiling a contract

To compile a contract, use:

vyper your_file_name.vy

generate bytecode

vyper -f bytecode file-name.vy > file-name.bin

generate abi

vyper -f abi file-name.vy > file-name.abi

There is also an online compiler available you can use to experiment with the language and compile to bytecode and/or IR.

Note: While the vyper version of the online compiler is updated on a regular basis it might be a bit behind the latest version found in the master branch of this repository.

Testing (using pytest)

(Complete installation steps first.)

make dev-init
python setup.py test

Developing (working on the compiler)

A useful script to have in your PATH is something like the following:

$ cat ~/.local/bin/vyc
#!/usr/bin/env bash
PYTHONPATH=. python vyper/cli/vyper_compile.py "$@"

To run a python performance profile (to find compiler perf hotspots):

PYTHONPATH=. python -m cProfile -s tottime vyper/cli/vyper_compile.py "$@"

To get a call graph from a python profile, https://stackoverflow.com/a/23164271/ is helpful.

Contributing

  • See Issues tab, and feel free to submit your own issues
  • Add PRs if you discover a solution to an existing issue
  • For further discussions and questions, post in Discussions or talk to us on Discord
  • For more information, see Contributing

vyper's People

Contributors

adrianhacker-pdx avatar ben-kaufman avatar benber86 avatar charles-cooper avatar dan-nolan avatar davesque avatar davidknott avatar fubuloubu avatar fulldecent avatar gbisaga avatar harkal avatar hskang9 avatar iamdefinitelyahuman avatar jackiexu avatar jacqueswww avatar jakerockland avatar jamesray1 avatar jessebmiller avatar madelineau avatar nrryuya avatar pcaversaccio avatar pdaian avatar pipermerriam avatar saikat041 avatar skellet0r avatar trocher avatar tserg avatar vbuterin avatar whb07 avatar yograterol avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vyper's Issues

Cross-Type computations

What's your issue about?

There are certain types that should be allow to compute cross-type computations. Some are implemented, but others have been skipped (creating a compiler error). Consider the right implicit type conversions for these datatypes such that data loss is not an issue (e.g. div num num has the potential to lose decimal point information if arg1 is not evenly divisible by arg2). Data loss either needs to be removed, or explcitly stated in the documentation of the behavior different types.

How can it be fixed?

Add it

Cute Animal Picture

PIG

Functions do not properly type check arguments.

Currently functions do not properly check the types of their input arguments and do not error when not enough arguments are given:

age:public(num)

def __init__(start_age: num):
    self.age = start_age

def set_age(new_age: num):
    self.age = new_age

The above function doesn't fail when it's initialized with the following

get_contract(source_code, args=[])   # age is set to 0
get_contract(source_code, args=['b'])  # age is set to 98

After it's initialized the following can be called without errors:

c.set_age()  # age is set to 0
c.set_age('b')  # age is set to 98

Payable semantics and abstract transferable goods.

Abstract

Ether, other cryptocurrencies and contract-based digital assets are about money. I think that tokens, subcurrencies and other abstract calculable goods are very important part of Ethereum ecosystem.

I'd like to suggest some modifications that , I think, would help to avoid accidentally monetary losses in future.

Motivation

There are numbers of abstract digital goods on Ethereum: different tokens, unicorns etc. etc.

These abstract digital goods are transferable. This means that a transaction for the purpose of transferring goods from one account to another can be performed.

It's obvious that transaction of digital goods must be properly handled (doesn't matter Ether or any abstract asset).

Ether transactions could only be handled by @payable functions. I think that it is important to introduce an opportunity to require payable modifier for callable function.

Main idea: when you call a function with the @abstract_payment modifier in contract A, which calls another contract B, then inside B only the @payable function can be called. Each execution of the function of the contract B, which is not @ payable, must fail.

Example

Ether transfer

We are calling @payable function and attaching Ether to the transaction.
If there is no function with matching signature implemented in the receiver contract, then the fallback function of the receiver will be executed.

If the fallback function is not @payable then the transaction will fail and nothing bad will happen.

Abstract asset transfer

The transferAndCall function of the ERC20 token is calling receiveTransfer function at the receiver contract.
If there is no receiveTransfer function implemented in the receiver contract, then the fallback function of the receiver will be executed.

If the fallback function is implemented then it will result in accidentally lost (stuck) tokens, unlike Ether that will be thrown in this case.

Resolution

I suggest to add an @abstract_payment modifier (decorator).

A function with the modifier @abstract_payment can be handled only by @payable functions. This allows contract developers to artificially require their function calls to be handled only by properly designed functions. This will reduce possibilities of mistakes and allow to avoid accidentally lost money in future.

Example

Abstract digital asset contract:

@abstract_payment
def transfer_and_call(_to : address, _value : num256) -> bool:
    # this must call `on_transfer` at the receiver.
    return true

Proper receiver contract implementation:

@payable
def on_transfer():
    # This function will be properly called.

# I'm not familiar with the syntax yet and I didn't found
# any examples of fallback function definition
def fallback():
    # Do something.

In this case fallback function is not @payable. This means that it must throw whenever it received Ether or any abstract goods.

@abstract_payment requires this function call to be handled by @payable functions only.

Optional

I think that it can be a good idea to leave @payable functions for handling of Ether payments and introduce a new @abstract_payable for abstract payments but it seems superfluous.
Payments can be recognized by the variable msg.value.
If msg.value > 0 then it is Ether payment.
If msg.value = 0 then it is abstract payment.

At the other hand this will allow @payable functions to receive both abstract goods payments and Ether payments.

@vbuterin what do you think about it?

Error running tests

I have a error when I run python setup.py test
I have the same error when I go the test folder and I execute python test_parser.py

A have archlinux with python 3.6.0 and viper has been installed in a fresh virtualenv with python setup.py install

Traceback (most recent call last): File "test_parser.py", line 16, in <module> state_transition.apply_transaction(s.state, rlp.decode(u.decode_hex('f903bd808506fc23ac008304c1908080b903aa6103988061000e6000396103a65660006101bf5361202059905901600090526101008152602081019050602052600060605261040036018060200159905901600090528181526020810190509050608052600060e0527f0100000000000000000000000000000000000000000000000000000000000000600035046101005260c061010051121561007e57fe5b60f86101005112156100a95760c061010051036001013614151561009e57fe5b6001610120526100ec565b60f761010051036020036101000a600161012051013504610140526101405160f7610100510360010101361415156100dd57fe5b60f76101005103600101610120525b5b366101205112156102ec577f01000000000000000000000000000000000000000000000000000000000000006101205135046101005260e0516060516020026020510152600160605101606052608061010051121561017a57600160e0516080510152600161012051602060e0516080510101376001610120510161012052602160e0510160e0526102da565b60b8610100511215610218576080610100510360e05160805101526080610100510360016101205101602060e05160805101013760816101005114156101ef5760807f010000000000000000000000000000000000000000000000000000000000000060016101205101350412156101ee57fe5b5b600160806101005103016101205101610120526020608061010051030160e0510160e0526102d9565b60c06101005112156102d65760b761010051036020036101000a6001610120510135046101405260007f0100000000000000000000000000000000000000000000000000000000000000600161012051013504141561027357fe5b603861014051121561028157fe5b6101405160e05160805101526101405160b761010051600161012051010103602060e05160805101013761014051600160b7610100510301016101205101610120526020610140510160e0510160e0526102d8565bfe5b5b5b602060605113156102e757fe5b6100ed565b60e051606051602002602051015261082059905901600090526108008152602081019050610160526000610120525b6060516101205113151561035c576020602060605102610120516020026020510151010161012051602002610160510152600161012051016101205261031b565b60e0518060206020606051026101605101018260805160006004600a8705601201f161038457fe5b50602060e051602060605102010161016051f35b6000f31b2d4f'), transactions.Transaction)) File "/home/alex/.virtualenvs/viper/lib/python3.6/site-packages/ethereum-1.3.7-py3.6.egg/ethereum/state_transition.py", line 211, in apply_transaction validate_transaction(state, tx) File "/home/alex/.virtualenvs/viper/lib/python3.6/site-packages/ethereum-1.3.7-py3.6.egg/ethereum/state_transition.py", line 159, in validate_transaction if not tx.sender: # sender is set and validated on Transaction initialization File "/home/alex/.virtualenvs/viper/lib/python3.6/site-packages/ethereum-1.3.7-py3.6.egg/ethereum/transactions.py", line 89, in sender pub = ecrecover_to_pub(rawhash, v, self.r, self.s) File "/home/alex/.virtualenvs/viper/lib/python3.6/site-packages/ethereum-1.3.7-py3.6.egg/ethereum/utils.py", line 79, in ecrecover_to_pub assert pow(xc, (SECP256K1P - 1) / 2, SECP256K1P) == 1 TypeError: pow() 3rd argument not allowed unless all arguments are integers

Link to the Viper Gitter in the Readme

What's your issue about?

I'd like to have more discussion in the Viper Gitter channel

How can it be fixed?

Add a link to the Viper Gitter in the Viper readme (towards the top) with a few sentences encouraging discussion and questions.

Cute Animal Picture

image

OSX difficult install experience feedback

Followed instructions in readme.md.
I can now compile examples/voting/ballot.v.py, which fortunately is all I need to do right now, but python setup.py test and python3.6 setup.py test both fail with python crashing and a console message similar to:

[1]    79735 illegal hardware instruction  python3.6 setup.py test

where the number part changes each time.

Question Does python need to point to python3.6? If so a note saying that would help some people like me.

I was able to get setup to succeed by first doing:

python3.6 -m pip install --user --upgrade Cython

Before that I was getting

failed to import Cython: dlopen(/Library/Python/2.7/site-packages/Cython/Compiler/Scanning.so, 2): Symbol not found: _PyClass_Type
  Referenced from: /Library/Python/2.7/site-packages/Cython/Compiler/Scanning.so
  Expected in: flat namespace
 in /Library/Python/2.7/site-packages/Cython/Compiler/Scanning.so
error: Setup script exited with error: Cython does not appear to be installed

I added the extra arguments to pip following https://pip.pypa.io/en/stable/user_guide/#user-installs because python3.6 -m pip install Cython resulted in

Requirement already satisfied: Cython in /Library/Python/2.7/site-packages

Testing framework can't handle function calls?

I have the following Viper contract:

def b() -> bool:
    return true

def a() -> bool:
    return self.b()

I am trying to test it as follows:

from ethereum import tester as t
s = t.state()
from viper import compiler
t.languages['viper'] = compiler.Compiler() 

c = s.abi_contract(open('examples/test.vy').read(), language='viper')

print(c.b())
print(c.a())

The tester gives me an error as follows:

Traceback (most recent call last):
  File "test_test.py", line 9, in <module>
    print(c.a())
  File "/usr/local/lib/python3.6/dist-packages/ethereum/tester.py", line 143, in kall
    **dict_without(kwargs, 'sender', 'value', 'output')
  File "/usr/local/lib/python3.6/dist-packages/ethereum/tester.py", line 312, in _send
    raise TransactionFailed()
ethereum.tester.TransactionFailed

Which from reading the tester code looks like an out of gas error?

is this intended behavior / how best to proceed with testing contracts which call their own functions?

it's worth noting that when I compile and deploy the EVM generated:

$ viper examples/test.vy 
0x61011256600035601c52740100000000000000000000000000000000000000006020526fffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff000000000000000000000000000000016060527402540be3fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffdabf41c00000000000000000000000002540be40060a05263f8a8fd6d60005114156100bc576ffffffffffffffffffffffffffffffffe60005260206000f3005b634df7e3d060005114156100d657600160005260206000f3005b630dbe671f600051141561010d5760206101a06004634df7e3d06101405261015c6000305af11558576101a05160005260206000f3005b5b61000461011203610004600039610004610112036000f3

in Geth's development mode, the dispatch works fine.

Array of bytes has infinite type size

I am pretty sure this is an error, although I am a bit unclear behind the purpose of declaring the size of a type to be infinite. Is this a part of the gas estimate?

Anyways, if you define an array of bytes using another type, it throws an error e.g.:

def __init__(test: bytes32[bool]):
    pass

even though that data size should only be 64 bytes max (32 bytes x 2 possible values for bool)

Would appreciate some understanding behind the purpose of this check and if there is supposed to be a deeper check occuring, like some sort of maximum (or reasonable) number of bytes we should be allowed to use? (distinct from their economic cost to store them)

Improve quality of `wallet` example

What's your issue about?

I was working on a black box tester for the examples and realized the wallet example is pretty difficult to understand (in my opinion). It may also suffer from some older syntax rules that might not work anymore as it was written 2 months ago. I think there is a lot of potential to show off some of the more obscure methods available in viper through this contract, so I think if someone just went and cleaned it up (and added a LOT of comments about why certain hard numbers are chosen), it would be very helpful.

Cute Animal Picture

chipmonks holding hands

Documentation

Documentation will help Viper become more widely adopted, here's a skeleton:
I've implemented the base in Sphinx in this PR
Introduction to Viper --> Why Viper is necessary (strong type system, clearer code, easy accessibility and extensibility of the compiler code, etc)
Installing Viper --> Viper's still in the non-user friendly stage so it'd help to have directions that anyone can follow (make being the most basic etc)
Viper by Example --> I'd probably start with Hello world and an explanation of the syntax etc going into it and increase complexity from there
Using the compiler --> A step by step guide that shows someone how to turn their Viper code into byte code
Contributing --> It'd be great to get some guidelines in order to standardize and streamline contributions
@Dexaran @yograterol --> Obviously there's a lot more to be added but these seemed like good starting points

QUESTION: Inline assembly

Is there any possibility of inline assembly in Viper?

The inline assembly is often used in Solidity, because the functionality of the language does not allow developers to implement many things without it.

How to search a variable-sized array

@vbuterin I am writing a viper example contract for owning shares in a company. Since anyone can buy, the array of shareholders grows with each buy order from a new account. For discussion purposes, the signature of my array is stockholders: {account: address, stock: num}[num] and num_stockholders is initialized to zero in my contract creation.

I tried:

for i in range(self.num_stockholders):
  if msg.sender == stockholders[i].account:
    self.stockholders[i].stock += buy_order

which doesn't work because the compiler expects a non-zero, positive size for "number of rounds" in range. I can't reason my way out of this even given your crowdfunding example. The len can be zero, so does that mean this isn't possible to compile (search a variable-sized array)? How does my function get called again if my length exceeds the static number I'm using for "rounds" (30 in your example to avoid gas limit issues). Would appreciate any help you can provide.

Additionally, I think an easier, language-implemented way to obtain a member of or set a value in an array like this would be awesome. Something like if msg.sender in stockholders::account (e.g. list of values for one key in dict list) and stockholders[account==msg.sender].stock += msg.value / price (e.g. incr value for given key for matching item in list) would make it a lot easier to write more concise, readable code for a contract. I'm no programming language expert (especially not with EVM), but some means to represent these very common patterns would be super helpful and potentially optimizable in the bytecode I would think. I would like to write something like:

# If sender is on the books, increment their shares
if msg.sender in stockholders::account:
  self.stockholders[account==msg.sender].stock += msg.value / price
else:
  # Add sender to the books with the amount of shares purchased
  self.num_stockholders += 1
  self.stockholders[self.num_stockholders] = {account: msg.sender, stock: msg.value / price}

Error: Cannot send value to non-payable function

Testing a simple deposit contract and getting a couple of issues. I'll point the one out here and start a new ticket for the other problem.

Error: Cannot send value to non-payable function
    at web3.js:4057:19
    at <anonymous>:1:1

How to reproduce:

Contract

owner: address
depositors: wei_value[address]
depositorsNext: num

def __init__(_owner: address):
    self.owner = _owner
    self.depositorsNext = 1

def check_balance() -> wei_value:
    # Return our current balance 
    return(self.balance)

def drain():
    # Send all stored value to owner
    send(self.owner, self.balance)

def deposit() -> bool:
    # Deposit value in the contract and record the sender and value 
    
    assert(msg.value > 0)

    if self.depositors[msg.sender]:
        self.depositors[msg.sender] += msg.value
        return True
    else:
        self.depositors[msg.sender] = msg.value
        return True

Deploy with geth

> var abi = [ { "inputs":[ {"name": "beneficiary", "type": "address"}, ], "type": "constructor" }, { "type": "function", "name": "check_balance", "constant": true, "inputs": [], "outputs": [{"name": "balance", "type": "uint"}] }, { "type": "function", "name": "drain", "constant": false, "inputs": [], "outputs": [] }, { "type": "function", "name": "deposit", "constant": false, "inputs": [], "outputs": [{"name": "success", "type": "bool"}] }]
> var bcode = "0x600035601c52740100000000000000000000000000000000000000006020526fffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff000000000000000000000000000000016060527402540be3fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffdabf41c00000000000000000000000002540be40060a05260206020380360c03960c05160205181101558575060206020380360c03960c05160005560016002556101f456600035601c52740100000000000000000000000000000000000000006020526fffffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff000000000000000000000000000000016060527402540be3fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffdabf41c00000000000000000000000002540be40060a0526398ba1d4660005114156100ad57303160005260206000f3005b639890220b60005114156100ce57600060006000600030316000546000f150005b63d0e30db06000511415610132576000341315585733600160c05260c06020200154156101175733600160c05260c06020200134815401815550600160005260206000f3610130565b3433600160c05260c06020200155600160005260206000f35b005b5b6100c16101f4036100c16000396100c16101f4036000f3"
> ct = eth.contract(abi)
> ct.new("0xea4aca379b0c21b36e51380e5de936b61ca63176", , {from: eth.accounts[0], data: bcode, gas: 4000000})

Deposit

> x = ct.at("0xdeadbeef...")
> x.deposit.sendTransaction({from: eth.accounts[1], value: web3.toWei(1, "ether")})
Error: Cannot send value to non-payable function
    at web3.js:4057:19
    at <anonymous>:1:1

Perhaps I'm missing something on how to send value to a function?

Power operation is unsupported

What's your issue about?

Exponents are not currently supported

How can it be fixed?

Add them.

Test via:

val: public(num)
def __init__():
    self.val = 10**2
c = compile(...)
assert c.get_val() == 100

Cute Animal Picture

baby corgi

Roadmap for Viper?

I saw that 17 days ago Viper doesn't have updates.

How can we help you, @vbuterin?

If we can create a roadmap, it could be awesome for the project and contributors.

FEATURE: Strings implementation

What's your issue about?

I know Viper has strings (current syntax is str: bytes <= N and a literal is b"My String") but I wanted to have a discussion about strings and how we think it should work and look so that it is as straightforward as possible.

Additionally there's only a few string primitive functions, so let's discuss if more are needed.

Cute Animal Picture

pugly

Fake return values from stack.

In Solidity, if you call a function that does not return a value, assuming that it returns something, you will get fake return values from the stack. Not unassigned value or error.

I think that it is a serious issue because we can't rely on return values at all. It would be better to throw an error or return unassigned values.

I have described this in solidity issue #2630.

pragma solidity ^0.4.11;

contract test_receive
{ 
// this contract is needed only for the other contract to compile - it's never actually called
    function receive(address, uint256, bytes) returns (bool, uint256)
   { 
        return (false, 222);
    }
} 

contract test_cast
{
    uint public test_uint;
    bool public test_bool;

    function test(address addr, uint256 n) returns (uint256)
    {
        bytes memory _data;
        var (_success, _back) = test_receive(addr).receive(addr, n, _data);
        require(_success);
        test_uint = _back;
        test_bool = _success;
        return _back;
    }
}

contract dummy
  {
    function() payable {  }
}

Is here any possibility to avoid the same problem in Viper?

Failed `send` doesn't error or return false

Right now when I run:

send(msg.sender, self.balance + 1)

It neither errors nor returns false. I would like to implement functionality similar to Solidity where a failed send returns false and implement transfer which will throw on failure. Thoughts?

Contributing?

I'd be interested in contributing to this project, but there's no roadmap or list of necessary future features (in order of importance) that I can find. If someone could upload that, it would be very helpful. Thanks.

ModuleNotFoundError: No module named 'viper.signatures'

  • viper Version: 0.0.1
  • pyethereum Version: x.x.x
  • OS: osx
  • Python Version (python --version): Python 3.6.2
  • Environment (output of pip freeze):
bitcoin==1.1.42
bumpversion==0.5.3
coverage==4.4.1
ethereum==2.0.4
pbkdf2==1.3
py==1.4.34
pycryptodome==3.4.7
pyethash==0.1.27
pysha3==1.0.2
pytest==3.2.2
pytest-cov==2.5.1
pytest-runner==2.12.1
PyYAML==3.12
repoze.lru==0.7
rlp==0.6.0
scrypt==0.8.0
viper==0.0.1

What's your issue about?

(workd) ➜  workd git:(master) viper
Traceback (most recent call last):
  File "/Users/msoedov/pyenvs/workd/bin/viper", line 6, in <module>
    from viper import compiler, optimizer
  File "/Users/msoedov/pyenvs/workd/lib/python3.6/site-packages/viper/compiler.py", line 1, in <module>
    from . import parser
  File "/Users/msoedov/pyenvs/workd/lib/python3.6/site-packages/viper/parser.py", line 15, in <module>
    from .signatures.event_signature import (
ModuleNotFoundError: No module named 'viper.signatures'

How can it be fixed?

Add init to signature package

Cute Animal Picture

Page not exist for virtualenv guide.

Under Installation section of the documentation,
image

Broken Link: Page does not exist for virtualenv guide.
Please review the hyperlink on the installation documentation and share the target url or update respectively. [http://python-guide-pt-br.readthedocs.io/en/latest/dev/virtualenvs/] Thanks!

Get complete listing of gas estimates for contract

Some way to get a gas estimate for each function in a contract would be sweet, allowing you to profile the gas-intensive functions you might have but are unaware of and also see it in client programs/editors.

@vbuterin Can this be included in the ABI output? Does that make sense? I am not familiar with the requirements or uses of that format enough

EVM debugging tools

It would be nice if we had functions:

  • get_function_contexts(viper_code): returns a map {function_name: context} where context is the Context object created when processing that function.
  • decode_memory(context, memory): converts the given memory (which would be passed in from an EVM debugger) into a map {variable: value} showing the current state of all variables.
  • pc_to_viper_code_position(pc, in_init_code=False): takes as input a program counter in EVM bytecode (could be contract code or init code) and outputs the corresponding position in Viper code.

A much further ideal would of course be some kind of crazy integration with pyethereum logging that gives a Viper-flavored log for a VM execution showing what all the variables are and the position in Viper code at any point.

VIP: Named Structs

Simple Summary

Add the ability to define custom structure types with a given alias

Motivation

Contract writers often work with structures very extensively. It is very helpful to be able to give commonly-used structure types a reference so that they can be used in many places. Without this functionality, it would not be possible to write clear, efficient contracts for things like Plasma.

Specification

The clearest specification we have come up with would be to adopt this syntax for defining structs (from: #300 (comment)):

struct MyStruct:
    x: address
    y: bytes32

This new type would be available only at compile time for use in both defining globals and assigning to globals as follows:

s: MyStruct

def set(x: address, y: bytes32):
    self.s = MyStruct(x, y)

Additionally, it should be possible to construct a structure in memory, and use it as a variable:

s: MyStruct = MyStruct(x, y)  # or possibly allow {x: x, y: y}
self.s = s  # Write storage from memory as an optimization?

This VIP serves as a basis for #1019 and #1020

Backwards Compatibility

Fully backwards compatible.

Copyright

Copyright and related rights waived via CC0


Original Proposal (for context):

I was working on another example and was wondering if there is any planned support for creating or aliasing new types so that I wouldn't have to carry them around e.g.

newtype data_t = {property1: basetype, property2: basetype, etc...}
data_lookup: data_t[address]

...

@constant
def get_property1(_addr: address) -> basetype:
    return data_lookup[_addr].property1

FEATURE: Identifier type

I propose an additional type identifier extending sha3 (or some other acceptable hashing function with collision avoidance) to implement unique identifiers to be used in multi-party transaction logs (similar to how Firebase or other highly-scalable databases work). This would be useful for keeping track of quantities such as receipts, in-process/pending transactions, or other trackable quantities in a mapping as an alternative to a simple list, which has no collision avoidance and does not allow atomic operations on the data structure.

Usage as the key in a mapping data structure is much more natural than keeping track of items in a simple list (integer index), especially in context of #323 which would allow iteration without tracking indexes.

As an example, it might be used in the following context:

bills: {from: address, amt: wei_value}[identifier]

...

def pay_bill(_id: identifier):
    assert self.bills[_id] is not None
    assert self.balance >= self.bills[_id].amt
    send(self.bills[_id].from, self.bills[_id].amt)
    del self.bills[_id] # effectively self.bills[_id] = None

Errors on Installation

Tried a fresh install of Viper
Getting an error at line 5

unicodedecodeerror: 'ascii' codec can't decode byte 0xe8 in position 5559: ordinal not in range(128)

I fixed this temporarily by just commenting out the readme

Now I'm getting
src/scrypt.c:27:20: fatal error: Python.h: No such file or directory

Remove inputs from abi name field.

What's your issue about?

Viper's abi name field should not have a functions inputs attached to it for two reasons:

  1. Duplicate information (the inputs are already in that abi elsewhere)
  2. Abi uniformity, now the name field will match Solidity's

How can it be fixed?

Change abi name to not have inputs

Cute Animal Picture

image

Semantic Version in Viper

@vbuterin do you like to implement http://semver.org/ to Viper?

The idea is:

1- Manage the Viper's version according to the backwards-compatible features/fixes.
2- Freeze the dependencies version with every Viper's version.
3- To have a CHANGELOG in the repo.

Invalid cast results in runtime error rather than compile error/warning

  • viper Version: 0.0.1
  • pyethereum Version: 2.0.4
  • OS: osx
  • Python Version (python --version): 3.6.2
  • Environment (output of pip freeze):
    bumpversion==0.5.3
    certifi==2017.7.27.1
    chardet==3.0.4
    coverage==4.4.1
    cycler==0.10.0
    cytoolz==0.8.2
    ethereum==2.0.4
    ethereum-abi-utils==0.4.0
    ethereum-serpent==2.0.2
    ethereum-utils==0.4.0
    frozendict==1.2
    idna==2.5
    Jinja2==2.9.6
    MarkupSafe==1.0
    matplotlib==2.0.2
    Naked==0.1.31
    numpy==1.13.1
    pbkdf2==1.3
    py==1.4.34
    py-ecc==1.1.3
    pycryptodome==3.4.6
    pyethash==0.1.27
    pylru==1.0.9
    pyparsing==2.2.0
    pysha3==1.0.2
    pytest==3.2.2
    pytest-cov==2.5.1
    pytest-runner==2.12.1
    python-dateutil==2.6.1
    pytz==2017.2
    PyYAML==3.12
    repoze.lru==0.7
    requests==2.18.3
    rlp==0.6.0
    scipy==0.19.1
    scrypt==0.8.0
    shellescape==3.4.1
    six==1.10.0
    toolz==0.8.2
    urllib3==1.22
    viper==0.0.1
    web3==3.13.5

What's your issue about?

The following codes compile but throw exceptions when called:

def test1():
    y = 0x1000000000000000000000000000000000000000000000000000000000000000
    x = as_num128(y)
def test2():
  x = as_num128(msg.sender)

How can it be fixed?

In the case of test1 where the value of y is known at compile time, it seems that a compile error should be raised as the code will always fail. For test2 the code could potentially run error free if msg.sender fits in a num128 at runtime. In both cases, I believe a compile-time warning would be useful to inform the programmer that the cast may fail at runtime.

cat

QUESTION: Are here any plans to create Viper online compiler and IDE like Remix?

I'm wondering if there are any plans to create an online IDE for Viper (equivalent to Remix) or support for this language in Remix also?

We are very interested in this new language and some of the members of ETC community have suggested me to create an online compiler. I know that the language is not yet ready.
https://github.com/Dexaran/ICO/issues/21

I'd like to know about plans for Viper IDE. May be we can also participate.

Improve and thoroughly test gas estimation

Viper currently has a gas estimation feature (see https://github.com/ethereum/viper/blob/master/tests/test_parser.py#L30 ). However, the gas estimation in many places overshoots the actual gas consumption, it is still under-tested and there may well be areas where it under-estimates actual gas consumption. We need to reach a state where the gas estimator is 100% reliable, in the sense that it never undershoots, and overshooting is minimized, and every function that is called in test_parser.py is also tested for gas estimation correctly.

I recommend creating a wrapper for Chain.contract, call it ContractWithGasEstimation, which has the property that (i) the constructor always assumes the language is viper, for simplicity, and (ii) when you call it, it checks the amount of gas spent and verifies that it is less than viper's gas estimate.

max size of `bytes` doesn't appear in ABI output

  • viper Version: 0.0.1 (although no one has been updating this)
  • pyethereum Version: 1.3.7 (patched)
  • OS: linux, Ubuntu 16.04 LTS
  • Python Version (python --version): 3.6.1
  • Environment (output of pip freeze):
alabaster==0.7.10
Babel==2.5.0
bitcoin==1.1.42
bumpversion==0.5.3
certifi==2017.7.27.1
chardet==3.0.4
CommonMark==0.5.4
coverage==4.4.1
docutils==0.14
ethereum==1.3.7
gitdb2==2.0.2
GitPython==2.1.5
idna==2.6
imagesize==0.7.1
Jinja2==2.9.6
MarkupSafe==1.0
pbkdf2==1.3
py==1.4.34
pycryptodome==3.4.6
pyethash==0.1.27
Pygments==2.2.0
pysha3==1.0.2
pytest==3.1.3
pytest-cov==2.5.1
pytest-runner==2.11.1
pytz==2017.2
PyYAML==3.12
recommonmark==0.4.0
repoze.lru==0.6
requests==2.18.4
rlp==0.5.1
scrypt==0.8.0
semantic-version==2.6.0
serpent==1.23
six==1.10.0
smmap2==2.0.3
snowballstemmer==1.2.1
Sphinx==1.6.3
sphinx-rtd-theme==0.2.4
sphinxcontrib-websupport==1.0.1
urllib3==1.22
viper==0.0.1

What's your issue about?

I was working with the ABI on a testing application for viper and realized that the syntax bytes <= N doesn't represent itself in the ABI (e.g. the type appears as just bytes)

For example, check the approve() function in examples/wallet/wallet.v.py vs viper -f abi examples/wallet/wallet.v.py

Not sure if this points to a larger problem, but it makes it difficult to perform ABI-based testing and calling if we don't know what the maximum size is for that argument.

How can it be fixed?

  1. Add to ABI output (ensuring bytes has corresponding "max size" parameter)
  2. Investigate whether there are errors when handling bytes larger than the dictating size in the compiler.

Feature is_contract method

What's your issue about?

There's currently no way to check if an address is a contract.

How can it be fixed?

Create an is_contract method for addresses.

Test via:
contract_1 =

def foo():
    pass

contract_2 =

def foo(arg1: address) -> bool:
    return arg1.is_contract
c1 = compile(...)
c2 = compile(...)
assert c1.foo(c2.address) == True
assert c1.foo(t.a1) == False

Cute Animal Picture

image

Calling constant functions that use msg.sender in non-constant functions fails

I was testing some updates I was making with one of my example contracts and I think I may have stumbled upon a bug, or at least something I don't understand why it should fail (and it's not very clear why)

To summarize, I have a contract that contains a constant method to return the balance of some map (address -> record) for the address associated with the message sender. I decided to use this function in my other functions so I didn't duplicate this access in multiple spots, basically assuming that if I called this @constant function, the msg.sender attribute would be passed to that @constant function. However, when I do this I get the TransactionFailed exception from pyethereum.

Here's an example:

from ethereum.tools import tester
from viper import compiler

chain = tester.Chain()
tester.languages['viper'] = compiler.Compiler()
chain.head_state.gas_limit = 10**9

code="""
bal: num[address]

def __init__():
    self.bal[msg.sender] = 1

@constant
def get_my_bal() -> num:
    return self.bal[msg.sender]

def foo():
    assert self.bal[msg.sender] > 0

def bar():
    assert self.get_my_bal() > 0
"""

c = chain.contract(code, language='viper')
c.get_my_bal() # Works fine
c.foo() # Works fine as well
c.bar() # Fails with ethereum.tools.tester.TransactionFailed()

Please let me know if I am misunderstanding how the @constant is supposed to be used (I am assuming you should be allowed to call @constant functions from other functions) (I am also assuming that implicit values such as msg.sender are passed to @constant functions as well).

Not totally certain what the problem is...

What should the syntax for (i) ABI-formatted logs, and (ii) calls to external contracts be?

For ABI-formatted logs, we'd need to have syntax for both event type declaration and making the actual logs. For event type declaration, one option is for the parser to expect a list of declarations between storage variable declarations and function declarations that look like this:

MyLog: __log__(arg_1: num, arg2: indexed(bytes32), arg3: timestamp, arg4: bytes <= 100)

For the actual logging, I personally highly disagree with Solidity's syntax of making event logs and function calls syntactically the same; it goes against Viper's goals of making it hard to write misleading code.

One option is to copy Serpent syntax:

log(type=MyLog, 5, sha3("cow"), block.timestamp, "moose")

Another is:

log.MyLog(5, sha3("cow"), block.timestamp, "moose")

For external contract calls, we already have raw_call, but it would be good to have something ABI-formatted. We have the ABI formatting call in place already for self-calls, but to extend that to external calls we need a syntax for declaring external contract types.

One option is for the parser to expect another list of declarations, like:

class Foo():
    def bar(arg1: num, arg2: bytes32): pass
    @constant
    def baz(arg1: bytes <= 100, arg2: num256): pass

Another is to just directly pass in JSON ABI:

Foo = extern([{"constant": false, "type": "function", "name": "bar(int128,bytes32)", "outputs": [], "inputs": [{"type": "int128", "name": "arg1"}, {"type": "bytes32", "name": "arg2"}]}, {"constant": true, "type": "function", "name": "baz(bytes,uint256)", "outputs": [], "inputs": [{"type": "bytes", "name": "arg1"}, {"type": "uint256", "name": "arg2"}]}])

Then, one could declare anything from then on as having type Foo (we'd require contract types to start with a capitalized letter).

Any other ideas?

Very high gas on function

Same test contract as #270.

owner: address
depositors: wei_value[address]
depositorsNext: num

def __init__(_owner: address):
    self.owner = _owner
    self.depositorsNext = 1

def check_balance() -> wei_value:
    # Return our current balance 
    return(self.balance)

def drain():
    # Send all stored value to owner
    send(self.owner, self.balance)

def deposit() -> bool:
    # Deposit value in the contract and record the sender and value 
    
    assert(msg.value > 0)

    if self.depositors[msg.sender]:
        self.depositors[msg.sender] += msg.value
        return True
    else:
        self.depositors[msg.sender] = msg.value
        return True

When using geth to estimate gas on the deposit function, I'm getting gas higher than the block limit. Is this a viper compiler error, or just a really poorly defined function on my part?

> test_contract.deposit.estimateGas()
4712388

Error running tests

======================================================================
ERROR: tests.test_parser (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_parser
Traceback (most recent call last):
  File "/usr/lib/python3.6/unittest/loader.py", line 428, in _find_test_path
    module = self._get_module_from_name(name)
  File "/usr/lib/python3.6/unittest/loader.py", line 369, in _get_module_from_name
    __import__(name)
  File "/home/mike/dev/viper/tests/test_parser.py", line 3, in <module>
    from ethereum.tools import tester2 as t
ModuleNotFoundError: No module named 'ethereum.tools'

FEATURE: Additional mapping support methods

It would be useful if mappings had methods for accessing members similar to Python e.g. keys(),values(), and items(). These methods would mean that the underlying mapping type would need to track storage allocation implicitly, so that membership can be obtained. Additionally, a limit parameter can control the amount of members these methods return so that gas usage can be controlled (the default would be to return all allocated members).

Usage might look like (using crowdfunding example):

funders: wei_value[address]

@constant
def is_funder(_addr: address) -> bool:
    return _addr in self.funders.keys()

@constant
def amt_raised() -> wei_value:
    sum: wei_value
    for value in self.funders.values():
         sum += value
    return sum # or return sum(self.funders.values()) if sum() exists

# Not enough money was raised! Refund everyone
# (max 30 people at a time to avoid gas limit issues)
def refund():
    assert block.timestamp >= self.deadline and self.balance < self.goal
    for funder, value in self.funders.items(limit=30):
        send(funder, value)
        funder = None # Removes value from self.funders (or maybe del funder)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.