Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat vyper 0.2.0 #656

Merged
merged 5 commits into from
Jul 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Brownie is a Python-based development and testing framework for smart contracts

## Features

* Full support for [Solidity](https://github.com/ethereum/solidity) (`>=0.4.22`) and [Vyper](https://github.com/vyperlang/vyper) (`0.1.0-b17`)
* Full support for [Solidity](https://github.com/ethereum/solidity) (`>=0.4.22`) and [Vyper](https://github.com/vyperlang/vyper) (`0.2.x`)
* Contract testing via [`pytest`](https://github.com/pytest-dev/pytest), including trace-based coverage evaluation
* Property-based and stateful testing via [`hypothesis`](https://github.com/HypothesisWorks/hypothesis/tree/master/hypothesis-python)
* Powerful debugging tools, including python-style tracebacks and custom error strings
Expand Down
6 changes: 4 additions & 2 deletions brownie/convert/datatypes.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/python3

from copy import deepcopy
from decimal import Decimal
from decimal import Decimal, getcontext
from typing import Any, Dict, ItemsView, KeysView, List, Optional, Sequence, TypeVar, Union

import eth_utils
Expand Down Expand Up @@ -182,7 +182,9 @@ def _to_fixed(value: Any) -> Decimal:
except TypeError:
pass
try:
return Decimal(value)
ctx = getcontext()
ctx.prec = 100
return Decimal(value, context=ctx)
except Exception:
raise TypeError(f"Cannot convert {type(value).__name__} '{value}' to decimal.")

Expand Down
2 changes: 1 addition & 1 deletion brownie/project/compiler/vyper.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def _get_dependencies(ast_json: List) -> List:
import_nodes += [
i for i in ast_json if i["ast_type"] == "ImportFrom" if i["module"] != "vyper.interfaces"
]
return sorted(set([i["names"][0]["name"].split(".")[-1] for i in import_nodes]))
return sorted(set([i["name"].split(".")[-1] for i in import_nodes]))


def _generate_coverage_data(
Expand Down
4 changes: 2 additions & 2 deletions docs/compile.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ If one or more contracts are unable to compile, Brownie raises an exception with
Supported Languages
===================

Brownie supports Solidity (``>=0.4.22``) and Vyper (``0.1.0-b17``). The file extension determines which compiler is used:
Brownie supports Solidity (``>=0.4.22``) and Vyper (``0.2.x``). The file extension determines which compiler is used:

* Solidity: ``.sol``
* Vyper: ``.vy``
Expand Down Expand Up @@ -58,7 +58,7 @@ Setting the Compiler Version

.. note::

Brownie supports Solidity versions ``>=0.4.22`` and Vyper version ``0.1.0-b17``.
Brownie supports Solidity versions ``>=0.4.22`` and Vyper version ``0.2.x``.

If a compiler version is set in the configuration file, all contracts in the project are compiled using that version. The compiler is installed automatically if not already present. The version should be given as a string in the format ``0.x.x``.

Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ pyyaml>=5.3.0,<6.0.0
requests>=2.23.0,<3.0.0
semantic-version==2.8.5
tqdm==4.46.1
vyper==0.1.0b17
vyper==0.2.1
web3==5.11.1
24 changes: 12 additions & 12 deletions tests/data/brownie-test-project/contracts/VyperTester.vy
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
stuff: public(uint256[4])


@public
@external
def branches(a: uint256, b: bool) -> bool:
if a > 4:
return True
Expand All @@ -12,45 +12,45 @@ def branches(a: uint256, b: bool) -> bool:
return False


@public
@external
def revertStrings(a: uint256) -> bool:
assert a != 0, "zero"
assert a != 1 # dev: one
assert a != 2, "two" # dev: error
assert a != 3 # error
assert_modifiable(a != 4) # dev: such modifiable, wow
assert a != 4 # dev: such modifiable, wow
if a != 31337:
return True
raise "awesome show" # dev: great job


@public
@constant
@external
@view
def fixedType(a: decimal, b: decimal[2]) -> decimal[3]:
return [a, b[0], b[1]]


@public
def outOfBounds(i: uint256, value: uint256) -> bool:
self.stuff[i] = value
@external
def outOfBounds(i: uint256, _value: uint256) -> bool:
self.stuff[i] = _value
return True


@public
@external
def overflow(a: uint256, b: uint256) -> uint256:
return a * b


@public
@external
def underflow(a: uint256, b: uint256) -> uint256:
return a - b


@public
@external
def zeroDivision(a: uint256, b: uint256) -> uint256:
return a / b


@public
@external
def zeroModulo(a: uint256, b: uint256) -> uint256:
return a % b
2 changes: 1 addition & 1 deletion tests/data/ipfs-cache-mock/testipfs-vyper
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"contract_types":{"Bar":{"abi":[{"constant":false,"inputs":[],"name":"baz","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}],"source_path":"interfaces/Bar.json"}},"manifest_version":"2","package_name":"vyper","sources":{"contracts/foo.vy":"import interfaces.Bar as Bar\n@public\ndef foo() -> bool: return True"},"version":"1.0.0"}
{"contract_types":{"Bar":{"abi":[{"constant":false,"inputs":[],"name":"baz","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}],"source_path":"interfaces/Bar.json"}},"manifest_version":"2","package_name":"vyper","sources":{"contracts/foo.vy":"import interfaces.Bar as Bar\n@external\ndef foo() -> bool: return True"},"version":"1.0.0"}
2 changes: 1 addition & 1 deletion tests/network/contract/test_contractcall.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def test_block_identifier(accounts, history):
"""
foo: public(int128)

@public
@external
def set_foo(_foo: int128):
self.foo = _foo
"""
Expand Down
4 changes: 2 additions & 2 deletions tests/network/contract/test_natspec_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
the throat to be considered eaten
"""

@public
@external
@payable
def doesEat(food: string[30], qty: uint256) -> (bool, bool):
def doesEat(food: String[30], qty: uint256) -> (bool, bool):
"""
@notice Determine if Bugs will accept `qty` of `food` to eat
@dev Compares the entire string and does not rely on a hash
Expand Down
4 changes: 2 additions & 2 deletions tests/network/contract/test_overloaded_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from brownie.project import compile_source

vyper_source = """
@public
@constant
@external
@view
def foo(a: int128, b: int128 = 42) -> int128:
return a + b
"""
Expand Down
12 changes: 6 additions & 6 deletions tests/network/transaction/test_internal_transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
def test_to_eoa(accounts):
container = compile_source(
"""
@public
@external
@payable
def send_ether(receivers: address[3]) -> bool:
value: uint256 =100
Expand All @@ -28,13 +28,13 @@ def send_ether(receivers: address[3]) -> bool:
def test_to_contract(accounts):
container = compile_source(
"""
@public
@external
@payable
def send_ether(receiver: address) -> bool:
send(receiver, msg.value)
return True

@public
@external
@payable
def __default__():
return
Expand All @@ -50,7 +50,7 @@ def __default__():
def test_types(accounts):
container = compile_source(
"""
@public
@external
@payable
def send_ether(receiver: address) -> bool:
send(receiver, msg.value)
Expand All @@ -67,10 +67,10 @@ def send_ether(receiver: address) -> bool:
def test_via_create_vyper(accounts):
container = compile_source(
"""
@public
@external
@payable
def send_ether() -> bool:
create_forwarder_to(self, value=msg.value)
x: address = create_forwarder_to(self, value=msg.value)
return True"""
).Vyper
contract = container.deploy({"from": accounts[0]})
Expand Down
6 changes: 3 additions & 3 deletions tests/network/transaction/test_new_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ def test_solidity_reverts(solcproject, console_mode):

vyper_forwarder_source = """

@public
@external
def create_new(_target: address) -> address:
return create_forwarder_to(_target)
"""

vyper_factory_source = """

@public
@constant
@external
@view
def foo() -> uint256:
return 42
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/network/transaction/test_revert_msg.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,6 @@ def test_vyper_revert_reasons(vypertester, console_mode):


def test_deployment_size_limit(accounts, console_mode):
code = f"@public\ndef baz():\n assert msg.sender != ZERO_ADDRESS, '{'blah'*10000}'"
code = f"@external\ndef baz():\n assert msg.sender != ZERO_ADDRESS, '{'blah'*10000}'"
tx = compile_source(code).Vyper.deploy({"from": accounts[0]})
assert tx.revert_msg == "exceeds EIP-170 size limit"
4 changes: 2 additions & 2 deletions tests/project/compiler/test_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
"""

vyper_contract = """
@public
@external
def foo() -> bool:
return True
"""

vyper_interface = """
@public
@external
def foo() -> bool:
pass
"""
Expand Down
7 changes: 3 additions & 4 deletions tests/project/compiler/test_vyper.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,22 @@ def test_compile_empty():


def test_get_abi():
code = "@public\ndef baz() -> bool: return True"
code = "@external\ndef baz() -> bool: return True"
abi = compiler.vyper.get_abi(code, "Vyper")
assert len(abi) == 1
assert abi["Vyper"] == [
{
"name": "baz",
"outputs": [{"type": "bool", "name": ""}],
"inputs": [],
"constant": False,
"payable": False,
"stateMutability": "nonpayable",
"type": "function",
"gas": 351,
}
]


def test_size_limit(capfd):
code = f"@public\ndef baz():\n assert msg.sender != ZERO_ADDRESS, '{'blah'*10000}'"
code = f"@external\ndef baz():\n assert msg.sender != ZERO_ADDRESS, '{'blah'*10000}'"
compiler.compile_and_format({"foo.vy": code})
assert "exceeds EIP-170 limit of 24577" in capfd.readouterr()[0]
2 changes: 1 addition & 1 deletion tests/project/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def solc4source():
def vysource():
return """
# comments are totally kickass
@public
@external
def test() -> bool:
return True
"""
2 changes: 1 addition & 1 deletion tests/project/main/test_contract_syntaxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def test_only_events(newproject, minor):
def test_vyper_external_call(newproject):
source = """
from vyper.interfaces import ERC721
@public
@external
def interfaceTest():
ERC721(msg.sender).safeTransferFrom(msg.sender, self, 1, b"")
"""
Expand Down
4 changes: 2 additions & 2 deletions tests/project/main/test_interfaces_vyper.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json

INTERFACE = """
@public
@external
def baz() -> bool: pass
"""

Expand All @@ -10,7 +10,7 @@ def baz() -> bool: pass

implements: Bar

@public
@external
def baz() -> bool:
return True
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/project/main/test_main_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def test_compile_solc_object(project, solc5source):


def test_compile_vyper_object(project):
temp = project.compile_source("@public\ndef x() -> bool: return True")
temp = project.compile_source("@external\ndef x() -> bool: return True")
assert type(temp) is TempProject
assert isinstance(temp, _ProjectBase)
assert len(temp) == 1
Expand Down
2 changes: 1 addition & 1 deletion tests/project/test_project_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_compiles(project, tmp_path):
with tmp_path.joinpath("sources/Foo.vy").open("w") as fp:
fp.write(
"""
@public
@external
def foo() -> int128:
return 2
"""
Expand Down
6 changes: 3 additions & 3 deletions tests/project/test_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@pytest.fixture(scope="module")
def sourceobj(solc5source):
yield sources.Sources(
{"path/to/Foo.sol": solc5source}, {"interfaces/Baz.vy": "@public\ndef bar(): pass"}
{"path/to/Foo.sol": solc5source}, {"interfaces/Baz.vy": "@external\ndef bar(): pass"}
)


Expand All @@ -31,9 +31,9 @@ def test_namespace_collisions(solc5source):
sources.Sources({}, {"foo.sol": solc5source, "bar.sol": solc5source})
# solc / vyper collision
with pytest.raises(NamespaceCollision):
sources.Sources({"foo.sol": solc5source, "Foo.vy": "@public\ndef bar(): pass"}, {})
sources.Sources({"foo.sol": solc5source, "Foo.vy": "@external\ndef bar(): pass"}, {})
with pytest.raises(NamespaceCollision):
sources.Sources({"foo.sol": solc5source}, {"Foo.vy": "@public\ndef bar(): pass"})
sources.Sources({"foo.sol": solc5source}, {"Foo.vy": "@external\ndef bar(): pass"})


def test_get_path_list(sourceobj):
Expand Down
2 changes: 1 addition & 1 deletion tests/test/strategies/test_decimal.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def test_invalid_min_max():
@given(value=strategy("decimal"))
def test_given(value):
assert type(value) is Decimal
assert value.quantize(Decimal("1.0000000000")) == value
assert value.as_tuple().exponent >= -10
assert -(2 ** 127) <= value <= 2 ** 127 - 1


Expand Down