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[lang]!: change ABI type of decimal to int168 #3696

Merged
merged 49 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
e17e3cc
change ABI type of `decimal` to `int168`
charles-cooper Dec 16, 2023
a551ab4
Merge branch 'master' into feat/decimal-abi
charles-cooper Mar 16, 2024
299bdd5
Merge branch 'master' into feat/decimal-abi
charles-cooper Apr 3, 2024
7150dc1
add internalType to decimal
charles-cooper Apr 3, 2024
3a6c3ff
wip
charles-cooper Mar 16, 2024
edf1221
add decimal_to_int
charles-cooper Apr 4, 2024
7a66c20
wip - update tests
charles-cooper Apr 4, 2024
c1bc7fb
update some tests
charles-cooper Apr 4, 2024
85bae9d
Merge branch 'master' into feat/decimal-abi
charles-cooper Apr 4, 2024
4dd3859
update more tests
charles-cooper Apr 4, 2024
c57af0f
lint
charles-cooper Apr 6, 2024
a84bfa9
update more tests
charles-cooper Apr 6, 2024
02a15f5
fix some tests
charles-cooper Apr 6, 2024
0cf6c44
update some more tests
charles-cooper Apr 6, 2024
7e7f19e
wip - tests
charles-cooper Apr 6, 2024
d45ec62
Merge branch 'master' of https://github.com/vyperlang/vyper into feat…
tserg Apr 7, 2024
67d0209
update tests wip
tserg Apr 7, 2024
3c2d697
fix lint
tserg Apr 7, 2024
fff3409
try fixing convert
tserg Apr 7, 2024
2e5d6bd
fix as wei val
tserg Apr 7, 2024
3361649
Revert "Merge branch 'master' of https://github.com/vyperlang/vyper i…
tserg Apr 7, 2024
1235a58
Merge pull request #32 from tserg/feat/decimal-abi
charles-cooper Apr 7, 2024
26cfca9
update type_from_abi for decimals
charles-cooper Apr 7, 2024
f0714bb
update a test
charles-cooper Apr 7, 2024
94cc1fe
update docs
charles-cooper Apr 7, 2024
c0f685a
use math.floor in as_wei_value test for clarity
charles-cooper Apr 7, 2024
d7a9586
fix decimal in as_wei_value fuzzing
charles-cooper Apr 7, 2024
7a10f09
fix as_wei_value test calculation
charles-cooper Apr 7, 2024
6044c82
update as_wei_value test
charles-cooper Apr 7, 2024
8f2ce10
fix more tests
charles-cooper Apr 7, 2024
b26ce74
Merge branch 'master' into feat/decimal-abi
charles-cooper Apr 7, 2024
3a03de7
fail fast
charles-cooper Apr 7, 2024
072e381
fix a branch condition
charles-cooper Apr 7, 2024
a35a3c8
disable fail fast
charles-cooper Apr 8, 2024
dfd8709
Merge branch 'master' into feat/decimal-abi
charles-cooper Apr 8, 2024
a0f9200
update yaml
charles-cooper Apr 8, 2024
8077efb
fix floor/ceil tests
charles-cooper Apr 8, 2024
26f1e5f
Revert "Revert "Merge branch 'master' of https://github.com/vyperlang…
charles-cooper Apr 8, 2024
0948513
use round_towards_zero
charles-cooper Apr 8, 2024
d7f6ad6
fix min/max decimal tests
charles-cooper Apr 8, 2024
3bfea69
fix bad import
charles-cooper Apr 8, 2024
6905394
fix lint
charles-cooper Apr 8, 2024
31f8e8f
fix test again
charles-cooper Apr 8, 2024
362962e
fix lint
charles-cooper Apr 8, 2024
26cc804
style
charles-cooper Apr 8, 2024
fd2664b
add another assertion, comment
charles-cooper Apr 8, 2024
6f34b45
add dedicated decimal abi test
charles-cooper Apr 9, 2024
2930aa5
Merge branch 'master' into feat/decimal-abi
charles-cooper Apr 9, 2024
f9c9f4a
roll back flag change
charles-cooper Apr 9, 2024
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
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ jobs:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
# note that every time this is updated, `--splits` needs to be
# updated below as well.
Expand Down
2 changes: 1 addition & 1 deletion docs/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ A value with a precision of 10 decimal places between -1870722095783555735300716

In order for a literal to be interpreted as ``decimal`` it must include a decimal point.

The ABI type (for computing method identifiers) of ``decimal`` is ``fixed168x10``.
The ABI type (for computing method identifiers) of ``decimal`` is ``int168``.

Operators
*********
Expand Down
21 changes: 13 additions & 8 deletions tests/functional/builtins/codegen/test_abi_decode.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from decimal import Decimal

import pytest
from eth.codecs import abi

from tests.utils import decimal_to_int
from vyper.exceptions import ArgumentException, StackTooDeep, StructureException

TEST_ADDR = "0x" + b"".join(chr(i).encode("utf-8") for i in range(20)).hex()
Expand Down Expand Up @@ -54,22 +53,28 @@ def abi_decode_struct(x: Bytes[544]) -> Human:
c = get_contract(contract)

test_bytes32 = b"".join(chr(i).encode("utf-8") for i in range(32))
args = (TEST_ADDR, -1, True, Decimal("-123.4"), test_bytes32)
encoding = "(address,int128,bool,fixed168x10,bytes32)"
args = (TEST_ADDR, -1, True, decimal_to_int("-123.4"), test_bytes32)
encoding = "(address,int128,bool,int168,bytes32)"
encoded = abi.encode(encoding, args)
assert tuple(c.abi_decode(encoded)) == (TEST_ADDR, -1, True, Decimal("-123.4"), test_bytes32)
assert tuple(c.abi_decode(encoded)) == (
TEST_ADDR,
-1,
True,
decimal_to_int("-123.4"),
test_bytes32,
)

test_bytes32 = b"".join(chr(i).encode("utf-8") for i in range(32))
human_tuple = (
"foobar",
("vyper", TEST_ADDR, 123, True, Decimal("123.4"), [123, 456, 789], test_bytes32),
("vyper", TEST_ADDR, 123, True, decimal_to_int("123.4"), [123, 456, 789], test_bytes32),
)
args = tuple([human_tuple[0]] + list(human_tuple[1]))
human_t = "((string,(string,address,int128,bool,fixed168x10,uint256[3],bytes32)))"
human_t = "((string,(string,address,int128,bool,int168,uint256[3],bytes32)))"
human_encoded = abi.encode(human_t, (human_tuple,))
assert tuple(c.abi_decode_struct(human_encoded)) == (
"foobar",
("vyper", TEST_ADDR, 123, True, Decimal("123.4"), [123, 456, 789], test_bytes32),
("vyper", TEST_ADDR, 123, True, decimal_to_int("123.4"), [123, 456, 789], test_bytes32),
)


Expand Down
7 changes: 3 additions & 4 deletions tests/functional/builtins/codegen/test_abi_encode.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from decimal import Decimal

import pytest
from eth.codecs import abi

from tests.utils import decimal_to_int
from vyper.exceptions import StackTooDeep


Expand Down Expand Up @@ -109,10 +108,10 @@ def abi_encode3(x: uint256, ensure_tuple: bool, include_method_id: bool) -> Byte
test_bytes32 = b"".join(chr(i).encode("utf-8") for i in range(32))
human_tuple = (
"foobar",
("vyper", test_addr, 123, True, Decimal("123.4"), [123, 456, 789], test_bytes32),
("vyper", test_addr, 123, True, decimal_to_int("123.4"), [123, 456, 789], test_bytes32),
)
args = tuple([human_tuple[0]] + list(human_tuple[1]))
human_t = "(string,(string,address,int128,bool,fixed168x10,uint256[3],bytes32))"
human_t = "(string,(string,address,int128,bool,int168,uint256[3],bytes32))"
human_encoded = abi.encode(human_t, human_tuple)
assert c.abi_encode(*args, False, False).hex() == human_encoded.hex()
assert c.abi_encode(*args, False, True).hex() == (method_id + human_encoded).hex()
Expand Down
15 changes: 10 additions & 5 deletions tests/functional/builtins/codegen/test_as_wei_value.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from decimal import Decimal

import pytest

from tests.utils import decimal_to_int
from vyper.semantics.types import DecimalT
from vyper.utils import quantize, round_towards_zero

wei_denoms = {
"femtoether": 3,
"kwei": 3,
Expand Down Expand Up @@ -61,11 +63,14 @@ def test_wei_decimal(get_contract, tx_failed, denom, multiplier):
def foo(a: decimal) -> uint256:
return as_wei_value(a, "{denom}")
"""

c = get_contract(code)
value = Decimal((2**127 - 1) / (10**multiplier))

assert c.foo(value) == value * (10**multiplier)
denom_int = 10**multiplier
# TODO: test with more values
_, hi = DecimalT().ast_bounds
value = quantize(hi / denom_int)

assert c.foo(decimal_to_int(value)) == round_towards_zero(value * denom_int)


@pytest.mark.parametrize("value", (-1, -(2**127)))
Expand Down
6 changes: 4 additions & 2 deletions tests/functional/builtins/codegen/test_ceil.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import math
from decimal import Decimal

from tests.utils import decimal_to_int


def test_ceil(get_contract_with_gas_estimation):
code = """
Expand Down Expand Up @@ -102,8 +104,8 @@ def ceil_param(p: decimal) -> int256:
assert c.fos() == -5472
assert c.fot() == math.ceil(-(Decimal(2**167 - 1)) / 10**10)
assert c.fou() == -3
assert c.ceil_param(Decimal("-0.5")) == 0
assert c.ceil_param(Decimal("-7777777.7777777")) == -7777777
assert c.ceil_param(decimal_to_int("-0.5")) == 0
assert c.ceil_param(decimal_to_int("-7777777.7777777")) == -7777777


def test_ceil_ext_call(w3, side_effects_contract, assert_side_effects_invoked, get_contract):
Expand Down
29 changes: 23 additions & 6 deletions tests/functional/builtins/codegen/test_convert.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import enum
import itertools

# import random
import math
from decimal import Decimal

import eth.codecs.abi as abi
import eth.codecs.abi.exceptions
import pytest

from tests.utils import decimal_to_int
from vyper.compiler import compile_code
from vyper.exceptions import InvalidLiteral, InvalidType, TypeMismatch
from vyper.semantics.types import AddressT, BoolT, BytesM_T, BytesT, DecimalT, IntegerT, StringT
Expand Down Expand Up @@ -249,13 +249,20 @@ def _padconvert(val_bits, direction, n, padding_byte=None):
def _from_bits(val_bits, o_typ):
# o_typ: the type to convert to
try:
return abi.decode(o_typ.abi_type.selector_name(), val_bits)
ret = abi.decode(o_typ.abi_type.selector_name(), val_bits)
if isinstance(o_typ, DecimalT):
return Decimal(ret) / DECIMAL_DIVISOR
return ret
except eth.codecs.abi.exceptions.DecodeError:
raise _OutOfBounds() from None


def _to_bits(val, i_typ):
# i_typ: the type to convert from
if isinstance(i_typ, DecimalT):
val = val * i_typ.divisor
assert math.ceil(val) == math.floor(val)
val = int(val)
return abi.encode(i_typ.abi_type.selector_name(), val)


Expand Down Expand Up @@ -430,6 +437,13 @@ def test_convert_passing(
# web3 has special formatter for zero address
expected_val = None

if isinstance(o_typ, DecimalT):
expected_val = decimal_to_int(expected_val)

input_val = val
if isinstance(i_typ, DecimalT):
input_val = decimal_to_int(val)

contract_1 = f"""
@external
def test_convert() -> {o_typ}:
Expand Down Expand Up @@ -461,7 +475,7 @@ def test_input_convert(x: {i_typ}) -> {o_typ}:
"""

c2 = get_contract_with_gas_estimation(contract_2)
assert c2.test_input_convert(val) == expected_val
assert c2.test_input_convert(input_val) == expected_val

contract_3 = f"""
bar: {i_typ}
Expand All @@ -483,7 +497,7 @@ def test_memory_variable_convert(x: {i_typ}) -> {o_typ}:
"""

c4 = get_contract_with_gas_estimation(contract_4)
assert c4.test_memory_variable_convert(val) == expected_val
assert c4.test_memory_variable_convert(input_val) == expected_val


@pytest.mark.parametrize("typ", ["uint8", "int128", "int256", "uint256"])
Expand Down Expand Up @@ -715,5 +729,8 @@ def foo(bar: {i_typ}) -> {o_typ}:
"""

c3 = get_contract_with_gas_estimation(contract_3)
input_val = val
if isinstance(i_typ, DecimalT):
input_val = decimal_to_int(input_val)
with tx_failed():
c3.foo(val)
c3.foo(input_val)
6 changes: 4 additions & 2 deletions tests/functional/builtins/codegen/test_floor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import math
from decimal import Decimal

from tests.utils import decimal_to_int


def test_floor(get_contract_with_gas_estimation):
code = """
Expand Down Expand Up @@ -106,8 +108,8 @@ def floor_param(p: decimal) -> int256:
assert c.fos() == -1
assert c.fot() == math.floor(-Decimal(2**167) / 10**10)
assert c.fou() == -4
assert c.floor_param(Decimal("-5.6")) == -6
assert c.floor_param(Decimal("-0.0000000001")) == -1
assert c.floor_param(decimal_to_int("-5.6")) == -6
assert c.floor_param(decimal_to_int("-0.0000000001")) == -1


def test_floor_ext_call(w3, side_effects_contract, assert_side_effects_invoked, get_contract):
Expand Down
5 changes: 2 additions & 3 deletions tests/functional/builtins/codegen/test_minmax.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from decimal import Decimal

import pytest

from tests.utils import decimal_to_int
from vyper.semantics.types import IntegerT


Expand All @@ -17,7 +16,7 @@ def goo() -> uint256:
"""

c = get_contract_with_gas_estimation(minmax_test)
assert c.foo() == Decimal("58223.123")
assert c.foo() == decimal_to_int("58223.123")
assert c.goo() == 83

print("Passed min/max test")
Expand Down
2 changes: 1 addition & 1 deletion tests/functional/builtins/codegen/test_minmax_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def foo() -> {typ}:
"""
c = get_contract(code)

lo, hi = typ.ast_bounds
lo, hi = typ.int_bounds
if op == "min_value":
assert c.foo() == lo
elif op == "max_value":
Expand Down
7 changes: 3 additions & 4 deletions tests/functional/builtins/codegen/test_unary.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from decimal import Decimal

import pytest

from tests.utils import decimal_to_int
from vyper.exceptions import InvalidOperation


Expand Down Expand Up @@ -63,8 +62,8 @@ def bar() -> decimal:
"""

c = get_contract(code)
assert c.foo() == Decimal("-18707220957835557353007165858768422651595.9365500927")
assert c.bar() == Decimal("18707220957835557353007165858768422651595.9365500927")
assert c.foo() == decimal_to_int("-18707220957835557353007165858768422651595.9365500927")
assert c.bar() == decimal_to_int("18707220957835557353007165858768422651595.9365500927")


def test_negation_int128(get_contract):
Expand Down
4 changes: 2 additions & 2 deletions tests/functional/builtins/folding/test_epsilon.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from tests.utils import parse_and_fold
from tests.utils import decimal_to_int, parse_and_fold


@pytest.mark.parametrize("typ_name", ["decimal"])
Expand All @@ -16,4 +16,4 @@ def foo() -> {typ_name}:
old_node = vyper_ast.body[0].value
new_node = old_node.get_folded_value()

assert contract.foo() == new_node.value
assert contract.foo() == decimal_to_int(new_node.value)
5 changes: 3 additions & 2 deletions tests/functional/builtins/folding/test_floor_ceil.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from hypothesis import example, given, settings
from hypothesis import strategies as st

from tests.utils import parse_and_fold
from tests.utils import decimal_to_int, parse_and_fold

st_decimals = st.decimals(
min_value=-(2**32), max_value=2**32, allow_nan=False, allow_infinity=False, places=10
Expand All @@ -31,4 +31,5 @@ def foo(a: decimal) -> int256:
old_node = vyper_ast.body[0].value
new_node = old_node.get_folded_value()

assert contract.foo(value) == new_node.value
assert isinstance(new_node.value, int)
assert contract.foo(decimal_to_int(value)) == new_node.value
4 changes: 2 additions & 2 deletions tests/functional/builtins/folding/test_fold_as_wei_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from hypothesis import given, settings
from hypothesis import strategies as st

from tests.utils import parse_and_fold
from tests.utils import decimal_to_int, parse_and_fold
from vyper.builtins import functions as vy_fn
from vyper.utils import SizeLimits

Expand Down Expand Up @@ -34,7 +34,7 @@ def foo(a: decimal) -> uint256:
old_node = vyper_ast.body[0].value
new_node = old_node.get_folded_value()

assert contract.foo(value) == new_node.value
assert contract.foo(decimal_to_int(value)) == new_node.value


@pytest.mark.fuzzing
Expand Down
7 changes: 5 additions & 2 deletions tests/functional/builtins/folding/test_min_max.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from decimal import Decimal

import pytest
from hypothesis import given, settings
from hypothesis import strategies as st

from tests.utils import parse_and_fold
from tests.utils import decimal_to_int, parse_and_fold
from vyper.utils import SizeLimits

st_decimals = st.decimals(
Expand Down Expand Up @@ -32,7 +34,8 @@
old_node = vyper_ast.body[0].value
new_node = old_node.get_folded_value()

assert contract.foo(left, right) == new_node.value
l, r = [decimal_to_int(t) for t in (left, right)]
assert contract.foo(l, r) == decimal_to_int(new_node.value)


@pytest.mark.fuzzing
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from decimal import Decimal

import pytest
from eth.codecs import abi

from tests.utils import decimal_to_int
from vyper import compile_code
from vyper.exceptions import (
ArgumentException,
Expand Down Expand Up @@ -517,7 +516,7 @@ def bar(arg1: address) -> decimal:
"""

c2 = get_contract(contract_2)
assert c2.bar(c.address) == Decimal("1e-10")
assert c2.bar(c.address) == decimal_to_int("1e-10")


def test_decimal_too_long(get_contract, tx_failed):
Expand Down Expand Up @@ -570,7 +569,7 @@ def bar(arg1: address) -> (decimal, Bytes[3], decimal):
c2 = get_contract(contract_2)
assert c.foo() == [0, b"dog", 1]
result = c2.bar(c.address)
assert result == [Decimal("0.0"), b"dog", Decimal("1e-10")]
assert result == [decimal_to_int("0.0"), b"dog", decimal_to_int("1e-10")]


@pytest.mark.parametrize("a,b", [(8, 256), (256, 8), (256, 256)])
Expand Down
Loading
Loading