diff --git a/examples/wallet/wallet.v.py b/examples/wallet/wallet.v.py index e60824ba52..98f7fbcd80 100644 --- a/examples/wallet/wallet.v.py +++ b/examples/wallet/wallet.v.py @@ -2,11 +2,12 @@ # Warning: NOT AUDITED. Do not use to store substantial quantities of funds. # A list of the owners addresses (there are a maximum of 5 owners) -owners: address[5] +owners: public(address[5]) # The number of owners required to approve a transaction threshold: int128 # The number of transactions that have been approved -seq: int128 +seq: public(int128) + @public def __init__(_owners: address[5], _threshold: int128): @@ -15,6 +16,12 @@ def __init__(_owners: address[5], _threshold: int128): self.owners[i] = _owners[i] self.threshold = _threshold + +@public +def test_ecrecover(h: bytes32, v:uint256, r:uint256, s:uint256) -> address: + return ecrecover(h, v, r, s) + + # `@payable` allows functions to receive ether @public @payable @@ -35,8 +42,8 @@ def approve(_seq: int128, to: address, value: wei_value, data: bytes[4096], sigd h2: bytes32 = sha3(concat("\x19Ethereum Signed Message:\n32", h)) # Verifies that the caller of approve has entered the correct transaction number assert self.seq == _seq - # Iterates through all the owners and verifies that there signatures, - # given as the sigdata argument are correct + # # Iterates through all the owners and verifies that there signatures, + # # given as the sigdata argument are correct for i in range(5): if sigdata[i][0]: # If an invalid signature is given for an owner then the contract throws diff --git a/setup.py b/setup.py index bad9530d6f..1fd221b3b8 100644 --- a/setup.py +++ b/setup.py @@ -22,9 +22,8 @@ url='https://github.com/ethereum/vyper', license=license, packages=find_packages(exclude=('tests', 'docs')), - install_requires=['py-evm==0.2.0a12'], + install_requires=['py-evm==0.2.0a16'], setup_requires=['pytest-runner'], - python_requires='>=3.6', - tests_require=['pytest', 'pytest-cov', 'ethereum==2.3.1'], + tests_require=['pytest', 'pytest-cov', 'eth-tester==0.1.0b24'], scripts=['bin/vyper', 'bin/vyper-serve', 'bin/vyper-run'] ) diff --git a/tests/compiler/LLL/test_repeat.py b/tests/compiler/LLL/test_repeat.py index 5c05731f43..2750284a09 100644 --- a/tests/compiler/LLL/test_repeat.py +++ b/tests/compiler/LLL/test_repeat.py @@ -1,6 +1,6 @@ -def test_repeat(t, get_contract_from_lll, assert_compile_failed): +def test_repeat(get_contract_from_lll, assert_compile_failed): good_lll = ['repeat', 0, 0, 1, ['seq']] bad_lll_1 = ['repeat', 0, 0, 0, ['seq']] bad_lll_2 = ['repeat', 0, 0, -1, ['seq']] diff --git a/tests/compiler/LLL/test_with.py b/tests/compiler/LLL/test_with.py index aef5677fcd..3b86928a0c 100644 --- a/tests/compiler/LLL/test_with.py +++ b/tests/compiler/LLL/test_with.py @@ -1,6 +1,6 @@ -def test_with_depth(t, get_contract_from_lll, assert_compile_failed): +def test_with_depth(get_contract_from_lll, assert_compile_failed): _16_with_statements = ['with', 'var_1', 0, ['with', 'var_2', 0, ['with', 'var_3', 0, @@ -37,7 +37,7 @@ def test_with_depth(t, get_contract_from_lll, assert_compile_failed): assert_compile_failed(lambda: get_contract_from_lll(_17_with_statements), Exception) -def test_with_set_depth(t, get_contract_from_lll, assert_compile_failed): +def test_with_set_depth(get_contract_from_lll, assert_compile_failed): _16_with_statements = ['with', 'var_1', 0, ['with', 'var_2', 0, ['with', 'var_3', 0, diff --git a/tests/compiler/test_clamps.py b/tests/compiler/test_clamps.py index a1f63c287f..99c5c93937 100644 --- a/tests/compiler/test_clamps.py +++ b/tests/compiler/test_clamps.py @@ -1,6 +1,6 @@ -def test_uclamplt(t, get_contract_from_lll, assert_compile_failed): +def test_uclamplt(get_contract_from_lll, assert_compile_failed): lll = ['uclamplt', 2, 1] assert_compile_failed(lambda: get_contract_from_lll(lll), Exception) lll = ['uclamplt', 1, 1] @@ -9,7 +9,7 @@ def test_uclamplt(t, get_contract_from_lll, assert_compile_failed): get_contract_from_lll(lll) -def test_uclample(t, get_contract_from_lll, assert_compile_failed): +def test_uclample(get_contract_from_lll, assert_compile_failed): lll = ['uclample', 2, 1] assert_compile_failed(lambda: get_contract_from_lll(lll), Exception) lll = ['uclample', 1, 1] @@ -18,7 +18,7 @@ def test_uclample(t, get_contract_from_lll, assert_compile_failed): get_contract_from_lll(lll) -def test_uclampgt(t, get_contract_from_lll, assert_compile_failed): +def test_uclampgt(get_contract_from_lll, assert_compile_failed): lll = ['uclampgt', 1, 2] assert_compile_failed(lambda: get_contract_from_lll(lll), Exception) lll = ['uclampgt', 1, 1] @@ -27,7 +27,7 @@ def test_uclampgt(t, get_contract_from_lll, assert_compile_failed): get_contract_from_lll(lll) -def test_uclampge(t, get_contract_from_lll, assert_compile_failed): +def test_uclampge(get_contract_from_lll, assert_compile_failed): lll = ['uclampge', 1, 2] assert_compile_failed(lambda: get_contract_from_lll(lll), Exception) lll = ['uclampge', 1, 1] @@ -36,7 +36,7 @@ def test_uclampge(t, get_contract_from_lll, assert_compile_failed): get_contract_from_lll(lll) -def test_uclamplt_and_clamplt(t, get_contract_from_lll, assert_compile_failed): +def test_uclamplt_and_clamplt(get_contract_from_lll, assert_compile_failed): lll = ['uclamplt', 2, 1] assert_compile_failed(lambda: get_contract_from_lll(lll), Exception) lll = ['uclamplt', 1, 1] @@ -51,7 +51,7 @@ def test_uclamplt_and_clamplt(t, get_contract_from_lll, assert_compile_failed): get_contract_from_lll(lll) -def test_uclample_clample(t, get_contract_from_lll, assert_compile_failed): +def test_uclample_clample(get_contract_from_lll, assert_compile_failed): lll = ['uclample', 2, 1] assert_compile_failed(lambda: get_contract_from_lll(lll), Exception) lll = ['uclample', 1, 1] @@ -66,7 +66,7 @@ def test_uclample_clample(t, get_contract_from_lll, assert_compile_failed): get_contract_from_lll(lll) -def test_uclampgt_and_clampgt(t, get_contract_from_lll, assert_compile_failed): +def test_uclampgt_and_clampgt(get_contract_from_lll, assert_compile_failed): lll = ['uclampgt', 1, 2] assert_compile_failed(lambda: get_contract_from_lll(lll), Exception) lll = ['uclampgt', 1, 1] @@ -81,7 +81,7 @@ def test_uclampgt_and_clampgt(t, get_contract_from_lll, assert_compile_failed): get_contract_from_lll(lll) -def test_uclampge_and_clampge(t, get_contract_from_lll, assert_compile_failed): +def test_uclampge_and_clampge(get_contract_from_lll, assert_compile_failed): lll = ['uclampge', 1, 2] assert_compile_failed(lambda: get_contract_from_lll(lll), Exception) lll = ['uclampge', 1, 1] diff --git a/tests/conftest.py b/tests/conftest.py index 1767238932..da794cfc79 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,57 +1,121 @@ import pytest + from functools import wraps +import eth_tester +import web3 + +from eth_tester import ( + EthereumTester, +) +from eth_tester.exceptions import ( + TransactionFailed +) +from web3.providers.eth_tester import ( + EthereumTesterProvider, +) -from ethereum.tools import tester +from web3 import ( + Web3, +) +from web3.contract import ( + ConciseContract, +) from vyper.parser.parser_utils import ( LLLnode ) from vyper import ( compile_lll, - optimizer, compiler, + optimizer, ) -from ethereum import utils as ethereum_utils -@pytest.fixture -def check_gas(chain): - def check_gas(code, func=None, num_txs=1): - if func: - gas_estimate = tester.languages['vyper'].gas_estimate(code)[func] - else: - gas_estimate = sum(tester.languages['vyper'].gas_estimate(code).values()) - gas_actual = chain.head_state.receipts[-1].gas_used \ - - chain.head_state.receipts[-1 - num_txs].gas_used \ - - chain.last_tx.intrinsic_gas_used * num_txs - - # Computed upper bound on the gas consumption should - # be greater than or equal to the amount of gas used - if gas_estimate < gas_actual: - raise Exception("Gas upper bound fail: bound %d actual %d" % (gas_estimate, gas_actual)) - - print('Function name: {} - Gas estimate {}, Actual: {}'.format( - func, gas_estimate, gas_actual) - ) - return check_gas - - -def gas_estimation_decorator(chain, fn, source_code, func): - def decorator(*args, **kwargs): - @wraps(fn) - def decorated_function(*args, **kwargs): - result = fn(*args, **kwargs) - check_gas(chain)(source_code, func) - return result - return decorated_function(*args, **kwargs) - return decorator +############ +# PATCHING # +############ -def set_decorator_to_contract_function(chain, contract, source_code, func): - func_definition = getattr(contract, func) - func_with_decorator = gas_estimation_decorator( - chain, func_definition, source_code, func - ) - setattr(contract, func, func_with_decorator) +setattr(eth_tester.backends.pyevm.main, 'GENESIS_GAS_LIMIT', 10**9) +setattr(eth_tester.backends.pyevm.main, 'GENESIS_DIFFICULTY', 1) + + +@pytest.fixture(autouse=True) +def patch_log_filter_remove(monkeypatch): + + def Filter_remove(self, *values): + + def get_key(v): + return v.get('transaction_hash'), v.get('log_index'), v.get('transaction_index') + + values_to_remove = set([ + get_key(value) + for value in values + ]) + + queued_values = self.get_changes() + self.values = [ + value + for value + in self.get_all() + if get_key(value) not in values_to_remove + ] + for value in queued_values: + if get_key(value) in values_to_remove: + continue + self.queue.put_nowait(value) + + monkeypatch.setattr(eth_tester.utils.filters.Filter, 'remove', Filter_remove) + + +@pytest.fixture(autouse=True) +def patch_is_encodeable_for_fixed(monkeypatch): + original_is_encodable = web3.utils.abi.is_encodable + + def utils_abi_is_encodable(_type, value): + from eth_utils import is_integer + from eth_abi.abi import process_type + try: + base, sub, arrlist = _type + except ValueError: + base, sub, arrlist = process_type(_type) + + if not arrlist: + if base == 'fixed' and not arrlist: + return True + elif base == 'int': + if not is_integer(value): + return False + exp = int(sub) + if value < -1 * 2**(exp - 1) or value > 2**(exp - 1) + 1: + return False + return True + + # default behaviour + return original_is_encodable(_type, value) + + monkeypatch.setattr(web3.utils.abi, 'is_encodable', utils_abi_is_encodable) + + +@pytest.fixture(scope="module") +def tester(): + t = EthereumTester() + return t + + +def zero_gas_price_strategy(web3, transaction_params=None): + return 0 # zero gas price makes testing simpler. + + +@pytest.fixture(scope="module") +def w3(tester): + w3 = Web3(EthereumTesterProvider(tester)) + w3.eth.setGasPriceStrategy(zero_gas_price_strategy) + return w3 + + +@pytest.fixture +def keccak(): + return Web3.sha3 @pytest.fixture @@ -62,116 +126,140 @@ def bytes_helper(str, length): @pytest.fixture -def t(): - tester.s = tester.Chain() - return tester +def get_contract_from_lll(w3): + def lll_compiler(lll, *args, **kwargs): + lll = optimizer.optimize(LLLnode.from_list(lll)) + bytecode = compile_lll.assembly_to_evm(compile_lll.compile_to_assembly(lll)) + abi = [] + contract = w3.eth.contract(bytecode=bytecode, abi=abi) + deploy_transaction = { + 'data': contract._encode_constructor_data(args, kwargs) + } + tx = w3.eth.sendTransaction(deploy_transaction) + address = w3.eth.getTransactionReceipt(tx)['contractAddress'] + contract = w3.eth.contract(address, abi=abi, bytecode=bytecode, ContractFactoryClass=ConciseContract) + return contract + return lll_compiler -@pytest.fixture(scope="module") -def chain(): - tester.languages['vyper'] = compiler.Compiler() - s = tester.Chain() - s.head_state.gas_limit = 10**9 - return s +def _get_contract(w3, source_code, *args, **kwargs): + abi = compiler.mk_full_signature(source_code) + bytecode = '0x' + compiler.compile(source_code).hex() + contract = w3.eth.contract(abi=abi, bytecode=bytecode) + + value = kwargs.pop('value', 0) + value_in_eth = kwargs.pop('value_in_eth', 0) + value = value_in_eth * 10**18 if value_in_eth else value # Handle deploying with an eth value. + gasPrice = kwargs.pop('gasPrice', 0) + deploy_transaction = { + 'from': w3.eth.accounts[0], + 'data': contract._encode_constructor_data(args, kwargs), + 'value': value, + 'gasPrice': gasPrice + } + tx = w3.eth.sendTransaction(deploy_transaction) + address = w3.eth.getTransactionReceipt(tx)['contractAddress'] + contract = w3.eth.contract(address, abi=abi, bytecode=bytecode, ContractFactoryClass=ConciseContract) + # Filter logs. + contract._logfilter = w3.eth.filter({ + 'fromBlock': w3.eth.blockNumber - 1, + 'address': contract.address + }) + return contract @pytest.fixture -def utils(): - return ethereum_utils +def get_contract(w3): + def get_contract(source_code, *args, **kwargs): + return _get_contract(w3, source_code, *args, **kwargs) + return get_contract -@pytest.fixture -def get_contract_from_lll(t): - def lll_compiler(lll): - lll = optimizer.optimize(LLLnode.from_list(lll)) - byte_code = compile_lll.assembly_to_evm(compile_lll.compile_to_assembly(lll)) - t.s.tx(to=b'', data=byte_code) - return lll_compiler +def get_compiler_gas_estimate(code, func): + if func: + return compiler.gas_estimate(code)[func] + 22000 + else: + return sum(compiler.gas_estimate(code).values()) + 22000 + + +def check_gas_on_chain(w3, tester, code, func=None, res=None): + gas_estimate = get_compiler_gas_estimate(code, func) + gas_actual = tester.get_block_by_number('latest')['gas_used'] + # Computed upper bound on the gas consumption should + # be greater than or equal to the amount of gas used + if gas_estimate < gas_actual: + raise Exception("Gas upper bound fail: bound %d actual %d" % (gas_estimate, gas_actual)) + + print('Function name: {} - Gas estimate {}, Actual: {}'.format( + func, gas_estimate, gas_actual) + ) + + +def gas_estimation_decorator(w3, tester, fn, source_code, func): + def decorator(*args, **kwargs): + @wraps(fn) + def decorated_function(*args, **kwargs): + result = fn(*args, **kwargs) + if 'transact' in kwargs: + check_gas_on_chain(w3, tester, source_code, func, res=result) + return result + return decorated_function(*args, **kwargs) + return decorator + + +def set_decorator_to_contract_function(w3, tester, contract, source_code, func): + func_definition = getattr(contract, func) + func_with_decorator = gas_estimation_decorator( + w3, tester, func_definition, source_code, func + ) + setattr(contract, func, func_with_decorator) @pytest.fixture -def get_contract_with_gas_estimation(chain): - def get_contract_with_gas_estimation( - source_code, - *args, **kwargs): - contract = chain.contract(source_code, language="vyper", *args, **kwargs) - for func_name in contract.translator.function_data: - set_decorator_to_contract_function( - chain, contract, source_code, func_name - ) +def get_contract_with_gas_estimation(tester, w3): + def get_contract_with_gas_estimation(source_code, *args, **kwargs): + + contract = _get_contract(w3, source_code, *args, **kwargs) + for abi in contract._classic_contract.functions.abi: + if abi['type'] == 'function': + set_decorator_to_contract_function( + w3, tester, contract, source_code, abi['name'] + ) return contract - return get_contract_with_gas_estimation @pytest.fixture -def get_contract_with_gas_estimation_for_constants(chain): +def get_contract_with_gas_estimation_for_constants(w3): def get_contract_with_gas_estimation_for_constants( source_code, *args, **kwargs): - abi = tester.languages['vyper'].mk_full_signature(source_code) - # Take out constants from the abi for the purpose of gas estimation - for func in abi: - func['constant'] = False - ct = tester.ContractTranslator(abi) - byte_code = tester.languages['vyper'].compile(source_code) + (ct.encode_constructor_arguments(kwargs['args']) if kwargs else b'') - address = chain.tx(to=b'', data=byte_code) - contract = tester.ABIContract(chain, abi, address) - for func_name in contract.translator.function_data: - set_decorator_to_contract_function( - chain, contract, source_code, func_name - ) - return contract + return _get_contract(w3, source_code, *args, **kwargs) return get_contract_with_gas_estimation_for_constants @pytest.fixture -def get_contract(chain): - def get_contract(source_code, *args, **kwargs): - return chain.contract(source_code, language="vyper", *args, **kwargs) - return get_contract - - -@pytest.fixture -def assert_tx_failed(t): - def assert_tx_failed(function_to_test, exception=tester.TransactionFailed): - initial_state = t.s.snapshot() +def assert_tx_failed(tester): + def assert_tx_failed(function_to_test, exception=TransactionFailed): + snapshot_id = tester.take_snapshot() with pytest.raises(exception): function_to_test() - t.s.revert(initial_state) + tester.revert_to_snapshot(snapshot_id) return assert_tx_failed @pytest.fixture -def assert_compile_failed(get_contract_from_lll): - def assert_compile_failed(function_to_test, exception=tester.TransactionFailed): +def assert_compile_failed(): + def assert_compile_failed(function_to_test, exception=Exception): with pytest.raises(exception): function_to_test() return assert_compile_failed @pytest.fixture -def get_logs(): - def get_logs(receipt, contract, event_name=None): - contract_log_ids = contract.translator.event_data.keys() # All the log ids contract has - # All logs originating from contract, and matching event_name (if specified) - logs = [log for log in receipt.logs - if log.topics[0] in contract_log_ids and - log.address == contract.address and - (not event_name or - contract.translator.event_data[log.topics[0]]['name'] == event_name)] - assert len(logs) > 0, "No logs in last receipt" - - # Return all events decoded in the receipt - return [contract.translator.decode_event(log.topics, log.data) for log in logs] +def get_logs(w3): + def get_logs(tx_hash, c, event_name): + tx_receipt = w3.eth.getTransactionReceipt(tx_hash) + logs = c._classic_contract.events[event_name]().processReceipt(tx_receipt) + return logs return get_logs - - -@pytest.fixture -def get_last_log(get_logs): - def get_last_log(tester, contract, event_name=None): - receipt = tester.s.head_state.receipts[-1] # Only the receipts for the last block - # Get last log event with correct name and return the decoded event - print(get_logs(receipt, contract, event_name=event_name)) - return get_logs(receipt, contract, event_name=event_name)[-1] - return get_last_log diff --git a/tests/examples/auctions/test_simple_open_auction.py b/tests/examples/auctions/test_simple_open_auction.py index 321817dea8..f2937b6b7d 100644 --- a/tests/examples/auctions/test_simple_open_auction.py +++ b/tests/examples/auctions/test_simple_open_auction.py @@ -1,77 +1,76 @@ import pytest -import ethereum.utils as utils -FIVE_DAYS = 432000 +EXPIRY = 16 @pytest.fixture -def auction_tester(t): - from vyper import compiler - t.languages['vyper'] = compiler.Compiler() - contract_code = open('examples/auctions/simple_open_auction.v.py').read() - t.c = t.s.contract(contract_code, language='vyper', args=[t.accounts[0], FIVE_DAYS]) - return t +def auction_contract(w3, get_contract): + with open('examples/auctions/simple_open_auction.v.py') as f: + contract_code = f.read() + contract = get_contract(contract_code, *[w3.eth.accounts[0], EXPIRY]) + return contract -def test_initial_state(auction_tester): +def test_initial_state(w3, tester, auction_contract): # Check beneficiary is correct - assert utils.remove_0x_head(auction_tester.c.beneficiary()) == auction_tester.accounts[0].hex() + assert auction_contract.beneficiary() == w3.eth.accounts[0] # Check bidding time is 5 days - assert auction_tester.c.auction_end() == auction_tester.s.head_state.timestamp + 432000 + assert auction_contract.auction_end() == tester.get_block_by_number('latest')['timestamp'] + EXPIRY # Check start time is current block timestamp - assert auction_tester.c.auction_start() == auction_tester.s.head_state.timestamp + assert auction_contract.auction_start() == tester.get_block_by_number('latest')['timestamp'] # Check auction has not ended - assert auction_tester.c.ended() is False + assert auction_contract.ended() is False # Check highest bidder is empty - assert auction_tester.c.highest_bidder() == '0x0000000000000000000000000000000000000000' + assert auction_contract.highest_bidder() is None # Check highest bid is 0 - assert auction_tester.c.highest_bid() == 0 + assert auction_contract.highest_bid() == 0 -def test_bid(auction_tester, assert_tx_failed): - auction_tester.s.mine() +def test_bid(w3, tester, auction_contract, assert_tx_failed): + k1, k2, k3, k4, k5 = w3.eth.accounts[:5] # Bidder cannot bid 0 - assert_tx_failed(lambda: auction_tester.c.bid(value=0, sender=auction_tester.k1)) + assert_tx_failed(lambda: auction_contract.bid(transact={"value": 0, "from": k1})) # Bidder can bid - auction_tester.c.bid(value=1, sender=auction_tester.k1) + auction_contract.bid(transact={"value": 1, "from": k1}) # Check that higest bidder and highest bid have changed accordingly - assert utils.remove_0x_head(auction_tester.c.highest_bidder()) == auction_tester.accounts[1].hex() - assert auction_tester.c.highest_bid() == 1 + assert auction_contract.highest_bidder() == k1 + assert auction_contract.highest_bid() == 1 # Bidder bid cannot equal current highest bid - assert_tx_failed(lambda: auction_tester.c.bid(value=1, sender=auction_tester.k1)) + assert_tx_failed(lambda: auction_contract.bid(transact={"value": 0, "from": k1})) # Higher bid can replace current highest bid - auction_tester.c.bid(value=2, sender=auction_tester.k2) + auction_contract.bid(transact={"value": 2, "from": k2}) # Check that higest bidder and highest bid have changed accordingly - assert utils.remove_0x_head(auction_tester.c.highest_bidder()) == auction_tester.accounts[2].hex() - assert auction_tester.c.highest_bid() == 2 + assert auction_contract.highest_bidder() == k2 + assert auction_contract.highest_bid() == 2 # Multiple bidders can bid - auction_tester.c.bid(value=3, sender=auction_tester.k3) - auction_tester.c.bid(value=4, sender=auction_tester.k4) - auction_tester.c.bid(value=5, sender=auction_tester.k5) + auction_contract.bid(transact={"value": 3, "from": k3}) + auction_contract.bid(transact={"value": 4, "from": k4}) + auction_contract.bid(transact={"value": 5, "from": k5}) # Check that higest bidder and highest bid have changed accordingly - assert utils.remove_0x_head(auction_tester.c.highest_bidder()) == auction_tester.accounts[5].hex() - assert auction_tester.c.highest_bid() == 5 - auction_tester.c.bid(value=1 * 10**10, sender=auction_tester.k1) - balance_before_out_bid = auction_tester.s.head_state.get_balance(auction_tester.accounts[1]) - auction_tester.c.bid(value=2 * 10**10, sender=auction_tester.k2) - balance_after_out_bid = auction_tester.s.head_state.get_balance(auction_tester.accounts[1]) + assert auction_contract.highest_bidder() == k5 + assert auction_contract.highest_bid() == 5 + auction_contract.bid(transact={"value": 1 * 10**10, "from": k1}) + balance_before_out_bid = w3.eth.getBalance(k1) + auction_contract.bid(transact={"value": 2 * 10**10, "from": k2}) + balance_after_out_bid = w3.eth.getBalance(k1) # Account has more money after its bid is out bid assert balance_after_out_bid > balance_before_out_bid -def test_end_auction(auction_tester, assert_tx_failed): - auction_tester.s.mine() +def test_end_auction(w3, tester, auction_contract, assert_tx_failed): + k1, k2, k3, k4, k5 = w3.eth.accounts[:5] # Fails if auction end time has not been reached - assert_tx_failed(lambda: auction_tester.c.end_auction()) - auction_tester.c.bid(value=1 * 10**10, sender=auction_tester.k2) + assert_tx_failed(lambda: auction_contract.end_auction()) + auction_contract.bid(transact={"value": 1 * 10**10, "from": k2}) # Move block timestamp foreward to reach auction end time - auction_tester.s.head_state.timestamp += FIVE_DAYS - balance_before_end = auction_tester.s.head_state.get_balance(auction_tester.accounts[0]) - auction_tester.c.end_auction(sender=auction_tester.k2) - balance_after_end = auction_tester.s.head_state.get_balance(auction_tester.accounts[0]) + # tester.time_travel(tester.get_block_by_number('latest')['timestamp'] + EXPIRY) + w3.testing.mine(EXPIRY) + balance_before_end = w3.eth.getBalance(k1) + auction_contract.end_auction(transact={"from": k2}) + balance_after_end = w3.eth.getBalance(k1) # Beneficiary receives the highest bid assert balance_after_end == balance_before_end + 1 * 10 ** 10 # Bidder cannot bid after auction end time has been reached - assert_tx_failed(lambda: auction_tester.c.bid(value=10, sender=auction_tester.k1)) + assert_tx_failed(lambda: auction_contract.bid(transact={"value": 10, "from": k1})) # Auction cannot be ended twice - assert_tx_failed(lambda: auction_tester.c.end_auction()) + assert_tx_failed(lambda: auction_contract.end_auction()) diff --git a/tests/examples/company/test_company.py b/tests/examples/company/test_company.py index a3da82f463..ff6f91c909 100644 --- a/tests/examples/company/test_company.py +++ b/tests/examples/company/test_company.py @@ -1,131 +1,117 @@ import pytest -from ethereum.tools import tester as t -from vyper import compiler +@pytest.fixture +def c(w3, get_contract): + with open('examples/stock/company.v.py') as f: + contract_code = f.read() + contract = get_contract(contract_code, *[w3.eth.accounts[0], 1000, 10**6]) + return contract -@pytest.fixture -def tester(): - tester = t - tester.s = t.Chain() - tester.s.head_state.gas_limit = 10**9 - tester.languages['vyper'] = compiler.Compiler() - contract_code = open('examples/stock/company.v.py').read() - tester.company_address = t.a0 - # Company with 1000 shares @ 10^6 wei / share - tester.c = tester.s.contract(contract_code, language='vyper', - args=[tester.company_address, 1000, 10**6]) - return tester - - -def test_overbuy(tester, assert_tx_failed): +def test_overbuy(w3, c, assert_tx_failed): # If all the stock has been bought, no one can buy more - test_shares = int(tester.c.total_shares() / 2) - test_value = int(test_shares * tester.c.price()) - tester.c.buy_stock(sender=t.k1, value=test_value) - tester.c.buy_stock(sender=t.k1, value=test_value) - assert tester.c.stock_available() == 0 - assert tester.c.get_holding(t.a1) == (test_shares * 2) - one_stock = tester.c.price() - assert_tx_failed(lambda: tester.c.buy_stock(sender=t.k1, value=one_stock)) - assert_tx_failed(lambda: tester.c.buy_stock(sender=t.k2, value=one_stock)) - - -def test_sell_without_stock(tester, assert_tx_failed): + a1, a2 = w3.eth.accounts[1:3] + test_shares = int(c.total_shares() / 2) + test_value = int(test_shares * c.price()) + c.buy_stock(transact={"from": a1, "value": test_value}) + c.buy_stock(transact={"from": a1, "value": test_value}) + assert c.stock_available() == 0 + assert c.get_holding(a1) == (test_shares * 2) + one_stock = c.price() + assert_tx_failed(lambda: c.buy_stock(transact={'from': a1, 'value': one_stock})) + assert_tx_failed(lambda: c.buy_stock(transact={'from': a2, 'value': one_stock})) + + +def test_sell_without_stock(w3, c, assert_tx_failed): + a1, a2 = w3.eth.accounts[1:3] # If you don't have any stock, you can't sell - assert_tx_failed(lambda: tester.c.sell_stock(1, sender=t.k1)) - assert_tx_failed(lambda: tester.c.sell_stock(1, sender=t.k2)) + assert_tx_failed(lambda: c.sell_stock(1, transact={'from': a1})) + assert_tx_failed(lambda: c.sell_stock(1, transact={'from': a2})) # Negative stock doesn't work either - assert_tx_failed(lambda: tester.c.sell_stock(-1, sender=t.k1)) + assert_tx_failed(lambda: c.sell_stock(-1, transact={'from': a1})) # But if you do, you can! - test_shares = int(tester.c.total_shares()) - test_value = int(test_shares * tester.c.price()) - tester.c.buy_stock(sender=t.k1, value=test_value) - assert tester.c.get_holding(t.a1) == test_shares - tester.c.sell_stock(test_shares, sender=t.k1) + test_shares = int(c.total_shares()) + test_value = int(test_shares * c.price()) + c.buy_stock(transact={'from': a1, 'value': test_value}) + assert c.get_holding(a1) == test_shares + c.sell_stock(test_shares, transact={'from': a1}) # But only until you run out - assert_tx_failed(lambda: tester.c.sell_stock(1, sender=t.k1)) + assert_tx_failed(lambda: c.sell_stock(1, transact={'from': a1})) -def test_oversell(tester, assert_tx_failed): +def test_oversell(w3, c, assert_tx_failed): + a0, a1, a2 = w3.eth.accounts[:3] # You can't sell more than you own - test_shares = int(tester.c.total_shares()) - test_value = int(test_shares * tester.c.price()) - tester.c.buy_stock(sender=t.k1, value=test_value) - assert_tx_failed(lambda: tester.c.sell_stock(test_shares + 1, sender=t.k1)) + test_shares = int(c.total_shares()) + test_value = int(test_shares * c.price()) + c.buy_stock(transact={'from': a1, 'value': test_value}) + assert_tx_failed(lambda: c.sell_stock(test_shares + 1, transact={'from': a1})) -def test_transfer(tester, assert_tx_failed): +def test_transfer(w3, c, assert_tx_failed): # If you don't have any stock, you can't transfer - assert_tx_failed(lambda: tester.c.transfer_stock(t.a2, 1, sender=t.k1)) - assert_tx_failed(lambda: tester.c.transfer_stock(t.a1, 1, sender=t.k2)) + a1, a2 = w3.eth.accounts[1:3] + assert_tx_failed(lambda: c.transfer_stock(a2, 1, transact={'from': a1})) + assert_tx_failed(lambda: c.transfer_stock(a1, 1, transact={'from': a2})) # You can't do negative transfers to gain stock - assert_tx_failed(lambda: tester.c.transfer_stock(t.a2, -1, sender=t.k1)) + assert_tx_failed(lambda: c.transfer_stock(a2, -1, transact={'from': a1})) # If you transfer, you don't have the stock anymore - test_shares = int(tester.c.total_shares()) - test_value = int(test_shares * tester.c.price()) - tester.c.buy_stock(sender=t.k1, value=test_value) - assert tester.c.get_holding(t.a1) == test_shares - tester.c.transfer_stock(t.a2, test_shares, sender=t.k1) - assert_tx_failed(lambda: tester.c.sell_stock(1, sender=t.k1)) + test_shares = int(c.total_shares()) + test_value = int(test_shares * c.price()) + c.buy_stock(transact={'from': a1, 'value': test_value}) + assert c.get_holding(a1) == test_shares + c.transfer_stock(a2, test_shares, transact={'from': a1}) + assert_tx_failed(lambda: c.sell_stock(1, transact={'from': a1})) # But the other person does - tester.c.sell_stock(test_shares, sender=t.k2) + c.sell_stock(test_shares, transact={'from': a2}) -def test_paybill(tester, assert_tx_failed): +def test_paybill(w3, c, assert_tx_failed): + a0, a1, a2, a3 = w3.eth.accounts[:4] # Only the company can authorize payments - assert_tx_failed(lambda: tester.c.pay_bill(t.a2, 1, sender=t.k1)) + assert_tx_failed(lambda: c.pay_bill(a2, 1, transact={'from': a1})) # A company can only pay someone if it has the money - assert_tx_failed(lambda: tester.c.pay_bill(t.a2, 1, sender=t.k0)) + assert_tx_failed(lambda: c.pay_bill(a2, 1, transact={'from': a0})) # If it has the money, it can pay someone - test_value = int(tester.c.total_shares() * tester.c.price()) - tester.c.buy_stock(sender=t.k1, value=test_value) - tester.c.pay_bill(t.a2, test_value, sender=t.k0) + test_value = int(c.total_shares() * c.price()) + c.buy_stock(transact={'from': a1, 'value': test_value}) + c.pay_bill(a2, test_value, transact={'from': a0}) # Until it runs out of money - assert_tx_failed(lambda: tester.c.pay_bill(t.a3, 1, sender=t.k0)) + assert_tx_failed(lambda: c.pay_bill(a3, 1, transact={'from': a0})) # Then no stockholders can sell their stock either - assert_tx_failed(lambda: tester.c.sell_stock(1, sender=t.k1)) + assert_tx_failed(lambda: c.sell_stock(1, transact={'from': a1})) -def test_valuation(tester): +def test_valuation(w3, c): + a1 = w3.eth.accounts[1] # Valuation is number of shares held times price - assert tester.c.debt() == 0 - test_value = int(tester.c.total_shares() * tester.c.price()) - tester.c.buy_stock(sender=t.k1, value=test_value) - assert tester.c.debt() == test_value + assert c.debt() == 0 + test_value = int(c.total_shares() * c.price()) + c.buy_stock(transact={'from': a1, 'value': test_value}) + assert c.debt() == test_value -def test_logs(tester, get_logs): +def test_logs(w3, c, get_logs): + a0, a1, a2, a3 = w3.eth.accounts[:4] # Buy is logged - tester.c.buy_stock(sender=t.k1, value=7 * tester.c.price()) - receipt = tester.s.head_state.receipts[-1] - logs = get_logs(receipt, tester.c) + logs = get_logs(c.buy_stock(transact={'from': a1, 'value': 7 * c.price()}), c, 'Buy') assert len(logs) == 1 - assert logs[0]["_event_type"] == b'Buy' - assert logs[0]["_buy_order"] == 7 + assert logs[0].args._buy_order == 7 # Sell is logged - tester.c.sell_stock(3, sender=t.k1) - receipt = tester.s.head_state.receipts[-1] - logs = get_logs(receipt, tester.c) + logs = get_logs(c.sell_stock(3, transact={'from': a1}), c, 'Sell') assert len(logs) == 1 - assert logs[0]["_event_type"] == b'Sell' - assert logs[0]["_sell_order"] == 3 + assert logs[0].args._sell_order == 3 # Transfer is logged - tester.c.transfer_stock(t.a2, 4, sender=t.k1) - receipt = tester.s.head_state.receipts[-1] - logs = get_logs(receipt, tester.c) + logs = get_logs(c.transfer_stock(a2, 4, transact={'from': a1}), c, 'Transfer') assert len(logs) == 1 - assert logs[0]["_event_type"] == b'Transfer' - assert logs[0]["_value"] == 4 + assert logs[0].event == 'Transfer' + assert logs[0].args._value == 4 # Pay is logged amount = 10**4 - tester.c.pay_bill(t.a3, amount) - receipt = tester.s.head_state.receipts[-1] - logs = get_logs(receipt, tester.c) + logs = get_logs(c.pay_bill(a3, amount, transact={}), c, 'Pay') assert len(logs) == 1 - assert logs[0]["_event_type"] == b'Pay' - assert logs[0]["_amount"] == amount + assert logs[0].args._amount == amount diff --git a/tests/examples/market_maker/test_on_chain_market_maker.py b/tests/examples/market_maker/test_on_chain_market_maker.py index 0be0566369..8d40262add 100644 --- a/tests/examples/market_maker/test_on_chain_market_maker.py +++ b/tests/examples/market_maker/test_on_chain_market_maker.py @@ -1,86 +1,91 @@ import pytest -from vyper import compiler @pytest.fixture -def market_maker(t, chain): - t.languages['vyper'] = compiler.Compiler() - contract_code = open('examples/market_maker/on_chain_market_maker.v.py').read() - return chain.contract(contract_code, language='vyper') +def market_maker(get_contract): + with open('examples/market_maker/on_chain_market_maker.v.py') as f: + contract_code = f.read() + return get_contract(contract_code) -TOKEN_NAME = "Vypercoin" -TOKEN_SYMBOL = "FANG" +TOKEN_NAME = b"Vypercoin" +TOKEN_SYMBOL = b"FANG" TOKEN_DECIMALS = 18 TOKEN_INITIAL_SUPPLY = (21 * 10 ** 6) TOKEN_TOTAL_SUPPLY = TOKEN_INITIAL_SUPPLY * (10 ** TOKEN_DECIMALS) @pytest.fixture -def erc20(t, chain): - t.languages['vyper'] = compiler.Compiler() - contract_code = open('examples/tokens/vypercoin.v.py').read() - return chain.contract(contract_code, language='vyper', args=[TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS, TOKEN_INITIAL_SUPPLY]) +def erc20(get_contract): + with open('examples/tokens/vypercoin.v.py') as f: + contract_code = f.read() + return get_contract(contract_code, *[TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS, TOKEN_INITIAL_SUPPLY]) -def test_initial_statet(market_maker, utils): +def test_initial_statet(market_maker): assert market_maker.total_eth_qty() == 0 assert market_maker.total_token_qty() == 0 assert market_maker.invariant() == 0 - assert utils.remove_0x_head(market_maker.owner()) == '0000000000000000000000000000000000000000' + assert market_maker.owner() is None -def test_initiate(t, chain, utils, market_maker, erc20, assert_tx_failed): - erc20.approve(market_maker.address, 2 * 10**18) - market_maker.initiate(erc20.address, 1 * 10**18, value=2 * 10**18) +def test_initiate(w3, market_maker, erc20, assert_tx_failed): + a0 = w3.eth.accounts[0] + erc20.approve(market_maker.address, 2 * 10**18, transact={}) + market_maker.initiate(erc20.address, 1 * 10**18, transact={'value': 2 * 10**18}) assert market_maker.total_eth_qty() == 2 * 10**18 assert market_maker.total_token_qty() == 1 * 10**18 assert market_maker.invariant() == 2 * 10**36 - assert utils.remove_0x_head(market_maker.owner()) == t.a0.hex() - assert erc20.name().split(b'\0', 1)[0].decode() == TOKEN_NAME + assert market_maker.owner() == a0 + assert erc20.name().split(b'\0', 1)[0] == TOKEN_NAME assert erc20.decimals() == TOKEN_DECIMALS - t.s = chain + # Initiate cannot be called twice - assert_tx_failed(lambda: market_maker.initiate(erc20.address, 1 * 10**18, value=2 * 10**18)) + assert_tx_failed(lambda: market_maker.initiate(erc20.address, 1 * 10**18, transact={'value': 2 * 10**18})) -def test_eth_to_tokens(t, market_maker, erc20): - erc20.approve(market_maker.address, 2 * 10**18) - market_maker.initiate(erc20.address, 1 * 10**18, value=2 * 10**18) +def test_eth_to_tokens(w3, market_maker, erc20): + a1 = w3.eth.accounts[1] + erc20.approve(market_maker.address, 2 * 10**18, transact={}) + market_maker.initiate(erc20.address, 1 * 10**18, transact={'value': 2 * 10**18}) assert erc20.balanceOf(market_maker.address) == 1000000000000000000 - assert erc20.balanceOf(t.a1) == 0 + assert erc20.balanceOf(a1) == 0 assert market_maker.total_token_qty() == 1000000000000000000 assert market_maker.total_eth_qty() == 2000000000000000000 - market_maker.eth_to_tokens(value=100, sender=t.k1) + + market_maker.eth_to_tokens(transact={'value': 100, 'from': a1}) assert erc20.balanceOf(market_maker.address) == 999999999999999950 - assert erc20.balanceOf(t.a1) == 50 + assert erc20.balanceOf(a1) == 50 assert market_maker.total_token_qty() == 999999999999999950 assert market_maker.total_eth_qty() == 2000000000000000100 -def test_tokens_to_eth(t, chain, market_maker, erc20): - erc20.transfer(t.a1, 2 * 10**18) - erc20.approve(market_maker.address, 2 * 10**18, sender=t.k1) - market_maker.initiate(erc20.address, 1 * 10**18, value=2 * 10**18, sender=t.k1) - assert chain.head_state.get_balance(market_maker.address) == 2000000000000000000 - assert chain.head_state.get_balance(t.a1) == 999997999999999999999900 +def test_tokens_to_eth(w3, tester, market_maker, erc20): + a1 = w3.eth.accounts[1] + erc20.transfer(a1, 2 * 10**18, transact={}) + erc20.approve(market_maker.address, 2 * 10**18, transact={'from': a1}) + market_maker.initiate(erc20.address, 1 * 10**18, transact={'value': 2 * 10**18, 'from': a1}) + assert w3.eth.getBalance(market_maker.address) == 2000000000000000000 + assert w3.eth.getBalance(a1) == 999997999999999999999900 assert market_maker.total_token_qty() == 1000000000000000000 - erc20.approve(market_maker.address, 1 * 10**18, sender=t.k1) - market_maker.tokens_to_eth(1 * 10**18, sender=t.k1) - assert chain.head_state.get_balance(market_maker.address) == 1000000000000000000 - assert chain.head_state.get_balance(t.a1) == 999998999999999999999900 + + erc20.approve(market_maker.address, 1 * 10**18, transact={'from': a1}) + market_maker.tokens_to_eth(1 * 10**18, transact={'from': a1}) + assert w3.eth.getBalance(market_maker.address) == 1000000000000000000 + assert w3.eth.getBalance(a1) == 999998999999999999999900 assert market_maker.total_token_qty() == 2000000000000000000 assert market_maker.total_eth_qty() == 1000000000000000000 -def test_owner_withdraw(t, chain, market_maker, erc20, assert_tx_failed): - erc20.approve(market_maker.address, 2 * 10**18) - market_maker.initiate(erc20.address, 1 * 10**18, value=2 * 10**18) - assert chain.head_state.get_balance(t.a0) == 999994000000000000000000 - assert erc20.balanceOf(t.a0) == 20999999000000000000000000 - t.s = chain +def test_owner_withdraw(w3, tester, market_maker, erc20, assert_tx_failed): + a0, a1 = w3.eth.accounts[:2] + erc20.approve(market_maker.address, 2 * 10**18, transact={}) + market_maker.initiate(erc20.address, 1 * 10**18, transact={'value': 2 * 10**18}) + assert w3.eth.getBalance(a0) == 999994000000000000000000 + assert erc20.balanceOf(a0) == 20999999000000000000000000 + # Only owner can call owner_withdraw - assert_tx_failed(lambda: market_maker.owner_withdraw(sender=t.k1)) - market_maker.owner_withdraw() - assert chain.head_state.get_balance(t.a0) == 999996000000000000000000 - assert erc20.balanceOf(t.a0) == 21000000000000000000000000 + assert_tx_failed(lambda: market_maker.owner_withdraw(transact={'from': a1})) + market_maker.owner_withdraw(transact={}) + assert w3.eth.getBalance(a0) == 999996000000000000000000 + assert erc20.balanceOf(a0) == 21000000000000000000000000 diff --git a/tests/examples/safe_remote_purchase/test_safe_remote_purchase.py b/tests/examples/safe_remote_purchase/test_safe_remote_purchase.py index a9bd8b3b34..fa7c374423 100644 --- a/tests/examples/safe_remote_purchase/test_safe_remote_purchase.py +++ b/tests/examples/safe_remote_purchase/test_safe_remote_purchase.py @@ -7,86 +7,90 @@ # 3. Seller ships item # 4. Buyer confirms receiving the item. Buyer's deposit (value) is returned. Seller's deposit (2*value) + items value is returned. Balance is 0. import pytest -from ethereum.tools import tester -from ethereum import utils -contract_code = open("examples/safe_remote_purchase/safe_remote_purchase.v.py").read() + # Inital balance of accounts -INIT_BAL = 1000000000000000000000000 +INIT_BAL_a0 = 1000000000000000000000000 +INIT_BAL_a1 = 1000000000000000000000000 @pytest.fixture -def srp_tester(): - t = tester - tester.s = t.Chain() - from vyper import compiler - t.languages["vyper"] = compiler.Compiler() - return tester +def contract_code(get_contract): + with open("examples/safe_remote_purchase/safe_remote_purchase.v.py") as f: + contract_code = f.read() + return contract_code @pytest.fixture -def check_balance(tester): - # balance of a0 = seller, a1 = buyer - sbal = tester.s.head_state.get_balance(tester.a0) - bbal = tester.s.head_state.get_balance(tester.a1) - return [sbal, bbal] +def check_balance(w3, tester): + def check_balance(): + a0, a1 = w3.eth.accounts[:2] + # balance of a1 = seller, a2 = buyer + return w3.eth.getBalance(a0), w3.eth.getBalance(a1) + return check_balance -def test_initial_state(srp_tester, assert_tx_failed): - assert check_balance(srp_tester) == [INIT_BAL, INIT_BAL] +def test_initial_state(w3, assert_tx_failed, get_contract, check_balance, contract_code): + assert check_balance() == (INIT_BAL_a0, INIT_BAL_a1) # Inital deposit has to be divisible by two - assert_tx_failed(lambda: srp_tester.s.contract(contract_code, language="vyper", args=[], value=1)) + assert_tx_failed(lambda: get_contract(contract_code, value=13)) # Seller puts item up for sale - srp_tester.c = tester.s.contract(contract_code, language="vyper", args=[], value=2) + a0_pre_bal, a1_pre_bal = check_balance() + c = get_contract(contract_code, value_in_eth=2) # Check that the seller is set correctly - assert utils.remove_0x_head(srp_tester.c.seller()) == srp_tester.accounts[0].hex() + assert c.seller() == w3.eth.accounts[0] # Check if item value is set correctly (Half of deposit) - assert srp_tester.c.value() == 1 + assert c.value() == w3.toWei(1, 'ether') # Check if unlocked() works correctly after initialization - assert srp_tester.c.unlocked() is True + assert c.unlocked() is True # Check that sellers (and buyers) balance is correct - assert check_balance(srp_tester) == [INIT_BAL - 2, INIT_BAL] + assert check_balance() == ((INIT_BAL_a0 - w3.toWei(2, 'ether')), INIT_BAL_a1) -def test_abort(srp_tester, assert_tx_failed): - srp_tester.c = srp_tester.s.contract(contract_code, language="vyper", args=[], value=2) +def test_abort(w3, assert_tx_failed, check_balance, get_contract, contract_code): + a0, a1, a2 = w3.eth.accounts[:3] + c = get_contract(contract_code, value=2) # Only sender can trigger refund - assert_tx_failed(lambda: srp_tester.c.abort(sender=srp_tester.k2)) + assert_tx_failed(lambda: c.abort(transact={'from': a2})) # Refund works correctly - srp_tester.c.abort(sender=srp_tester.k0) - assert check_balance(srp_tester) == [INIT_BAL, INIT_BAL] + c.abort(transact={'from': a0, 'gasPrice': 0}) + assert check_balance() == (INIT_BAL_a0 - w3.toWei(2, 'ether'), INIT_BAL_a1) # Purchase in process, no refund possible - srp_tester.c = srp_tester.s.contract(contract_code, language="vyper", args=[], value=2) - srp_tester.c.purchase(value=2, sender=srp_tester.k1) - assert_tx_failed(lambda: srp_tester.c.abort(sender=srp_tester.k0)) + c = get_contract(contract_code, value=2) + c.purchase(transact={'value': 2, 'from': a1, 'gasPrice': 0}) + assert_tx_failed(lambda: c.abort(transact={'from': a0})) -def test_purchase(srp_tester, assert_tx_failed): - srp_tester.c = srp_tester.s.contract(contract_code, language="vyper", args=[], value=2) +def test_purchase(w3, get_contract, assert_tx_failed, check_balance, contract_code): + a0, a1, a2, a3 = w3.eth.accounts[:4] + init_bal_a0, init_bal_a1 = check_balance() + c = get_contract(contract_code, value=2) # Purchase for too low/high price - assert_tx_failed(lambda: srp_tester.c.purchase(value=1, sender=srp_tester.k1)) - assert_tx_failed(lambda: srp_tester.c.purchase(value=3, sender=srp_tester.k1)) + assert_tx_failed(lambda: c.purchase(transact={'value': 1, 'from': a1})) + assert_tx_failed(lambda: c.purchase(transact={'value': 3, 'from': a1})) # Purchase for the correct price - srp_tester.c.purchase(value=2, sender=srp_tester.k1) + c.purchase(transact={'value': 2, 'from': a1, 'gasPrice': 0}) # Check if buyer is set correctly - assert utils.remove_0x_head(srp_tester.c.buyer()) == srp_tester.accounts[1].hex() + assert c.buyer() == a1 # Check if contract is locked correctly - assert srp_tester.c.unlocked() is False + assert c.unlocked() is False # Check balances, both deposits should have been deducted - assert check_balance(srp_tester) == [INIT_BAL - 2, INIT_BAL - 2] + assert check_balance() == (init_bal_a0 - 2, init_bal_a1 - 2) # Allow nobody else to purchase - assert_tx_failed(lambda: srp_tester.c.purchase(value=2, sender=srp_tester.k3)) + assert_tx_failed(lambda: c.purchase(transact={'value': 2, 'from': a3})) -def test_received(srp_tester, assert_tx_failed): - srp_tester.c = srp_tester.s.contract(contract_code, language="vyper", args=[], value=2) +def test_received(w3, get_contract, assert_tx_failed, check_balance, contract_code): + a0, a1 = w3.eth.accounts[:2] + init_bal_a0, init_bal_a1 = check_balance() + c = get_contract(contract_code, value=2) # Can only be called after purchase - assert_tx_failed(lambda: srp_tester.c.received(sender=srp_tester.k1)) + assert_tx_failed(lambda: c.received(transact={'from': a1, 'gasPrice': 0})) # Purchase completed - srp_tester.c.purchase(value=2, sender=srp_tester.k1) + c.purchase(transact={'value': 2, 'from': a1, 'gasPrice': 0}) # Check that e.g. sender cannot trigger received - assert_tx_failed(lambda: srp_tester.c.received(sender=srp_tester.k0)) + assert_tx_failed(lambda: c.received(transact={'from': a0, 'gasPrice': 0})) # Check if buyer can call receive - srp_tester.c.received(sender=srp_tester.k1) + c.received(transact={'from': a1, 'gasPrice': 0}) # Final check if everything worked. 1 value has been transferred - assert check_balance(srp_tester) == [INIT_BAL + 1, INIT_BAL - 1] + assert check_balance() == (init_bal_a0 + 1, init_bal_a1 - 1) diff --git a/tests/examples/tokens/test_vypercoin.py b/tests/examples/tokens/test_vypercoin.py index 5fa2d54e29..f811dd9342 100644 --- a/tests/examples/tokens/test_vypercoin.py +++ b/tests/examples/tokens/test_vypercoin.py @@ -1,150 +1,127 @@ import pytest -from ethereum.abi import ValueOutOfBounds -from ethereum.tools import tester +from web3.exceptions import ValidationError -TOKEN_NAME = "Vypercoin" -TOKEN_SYMBOL = "FANG" + +TOKEN_NAME = b"Vypercoin" +TOKEN_SYMBOL = b"FANG" TOKEN_DECIMALS = 18 TOKEN_INITIAL_SUPPLY = (21 * 10 ** 6) TOKEN_TOTAL_SUPPLY = TOKEN_INITIAL_SUPPLY * (10 ** TOKEN_DECIMALS) @pytest.fixture -def token_tester(): - t = tester - tester.s = t.Chain() - from vyper import compiler - t.languages['vyper'] = compiler.Compiler() - contract_code = open('examples/tokens/vypercoin.v.py').read() - tester.c = tester.s.contract( - contract_code, - language='vyper', - args=[TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS, TOKEN_INITIAL_SUPPLY] - ) - return tester +def c(get_contract): + with open('examples/tokens/vypercoin.v.py') as f: + return get_contract( + f.read(), + *[TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS, TOKEN_INITIAL_SUPPLY] + ) def pad_bytes32(instr): """ Pad a string \x00 bytes to return correct bytes32 representation. """ - bstr = instr.encode() - return bstr + (32 - len(bstr)) * b'\x00' + return instr.ljust(32, b'\x00') -def test_initial_state(token_tester): - assert token_tester.c.totalSupply() == TOKEN_TOTAL_SUPPLY == token_tester.c.balanceOf(token_tester.accounts[0]) - assert token_tester.c.balanceOf(token_tester.accounts[1]) == 0 - assert token_tester.c.symbol() == pad_bytes32(TOKEN_SYMBOL) - assert token_tester.c.name() == pad_bytes32(TOKEN_NAME) +def test_initial_state(c, w3): + a0, a1 = w3.eth.accounts[:2] + assert c.totalSupply() == TOKEN_TOTAL_SUPPLY == c.balanceOf(a0) + assert c.balanceOf(a1) == 0 + assert c.symbol() == pad_bytes32(TOKEN_SYMBOL) + assert c.name() == pad_bytes32(TOKEN_NAME) -def test_transfer(token_tester, assert_tx_failed): +def test_transfer(w3, c, assert_tx_failed): + a0, a1 = w3.eth.accounts[:2] # Basic transfer. - assert token_tester.c.transfer(token_tester.accounts[1], 1) is True - assert token_tester.c.balanceOf(token_tester.accounts[1]) == 1 - assert token_tester.c.balanceOf(token_tester.accounts[0]) == TOKEN_TOTAL_SUPPLY - 1 + c.transfer(a1, 1, transact={}) + assert c.balanceOf(a1) == 1 + assert c.balanceOf(a0) == TOKEN_TOTAL_SUPPLY - 1 # more than allowed - assert_tx_failed(lambda: token_tester.c.transfer(token_tester.accounts[1], TOKEN_TOTAL_SUPPLY)) + assert_tx_failed(lambda: c.transfer(a1, TOKEN_TOTAL_SUPPLY)) # Negative transfer value. assert_tx_failed( - function_to_test=lambda: tester.c.transfer(token_tester.accounts[1], -1), - exception=ValueOutOfBounds + function_to_test=lambda: c.transfer(a1, -1), + exception=ValidationError ) -def test_approve_allowance(token_tester): - assert token_tester.c.allowance(token_tester.accounts[0], token_tester.accounts[1]) == 0 - assert token_tester.c.approve(token_tester.accounts[1], 10) is True - assert token_tester.c.allowance(token_tester.accounts[0], token_tester.accounts[1]) == 10 +def test_approve_allowance(w3, c): + a0, a1 = w3.eth.accounts[:2] + assert c.allowance(a0, a1) == 0 + c.approve(a1, 10, transact={}) + assert c.allowance(a0, a1) == 10 -def test_transferFrom(token_tester, assert_tx_failed): - a0 = token_tester.accounts[0] - a1 = token_tester.accounts[1] - k1 = token_tester.k1 - a2 = token_tester.accounts[2] - k2 = token_tester.k2 - contract = token_tester.c +def test_transferFrom(w3, c, assert_tx_failed): + a0, a1, a2 = w3.eth.accounts[:3] # Allow 10 token transfers. Account a1 is allowed to spend 10 tokens of a0's account. ALLOWANCE = 10 - assert contract.approve(a1, ALLOWANCE) is True - assert contract.allowance(a0, a1) == ALLOWANCE + c.approve(a1, ALLOWANCE, transact={}) is True + assert c.allowance(a0, a1) == ALLOWANCE - assert contract.transferFrom(a0, a2, 3, sender=k1) is True # a1 may transfer. - assert contract.balanceOf(a0) == TOKEN_TOTAL_SUPPLY - 3 - assert contract.balanceOf(a1) == 0 - assert contract.balanceOf(a2) == 3 - assert contract.allowance(a0, a1) == ALLOWANCE - 3 + c.transferFrom(a0, a2, 3, transact={'from': a1}) # a1 may transfer. + assert c.balanceOf(a0) == TOKEN_TOTAL_SUPPLY - 3 + assert c.balanceOf(a1) == 0 + assert c.balanceOf(a2) == 3 + assert c.allowance(a0, a1) == ALLOWANCE - 3 # a2 may not transfer. - assert_tx_failed(lambda: contract.transferFrom(a0, a2, ALLOWANCE, sender=k2)) + assert_tx_failed(lambda: c.transferFrom(a0, a2, ALLOWANCE, transact={'from': a2})) # Negative transfer value. assert_tx_failed( - function_to_test=lambda: contract.transferFrom(a0, a2, -1, sender=k1), - exception=ValueOutOfBounds + function_to_test=lambda: c.transferFrom(a0, a2, -1, transact={'from': a1}), + exception=ValidationError ) # Transfer more than allowance: - assert_tx_failed(lambda: contract.transferFrom(a0, a2, 8, sender=k1)) - assert contract.balanceOf(a0) == TOKEN_TOTAL_SUPPLY - 3 - assert contract.balanceOf(a1) == 0 - assert contract.balanceOf(a2) == 3 - assert contract.allowance(a0, a1) == ALLOWANCE - 3 + assert_tx_failed(lambda: c.transferFrom(a0, a2, 8, transact={'from': a1})) + assert c.balanceOf(a0) == TOKEN_TOTAL_SUPPLY - 3 + assert c.balanceOf(a1) == 0 + assert c.balanceOf(a2) == 3 + assert c.allowance(a0, a1) == ALLOWANCE - 3 # Transfer exact amount left in allowance: - allowance_left = contract.allowance(a0, a1) - assert contract.transferFrom(a0, a2, allowance_left, sender=k1) is True - assert contract.balanceOf(a0) == TOKEN_TOTAL_SUPPLY - ALLOWANCE - assert contract.balanceOf(a1) == 0 - assert contract.balanceOf(a2) == ALLOWANCE - assert contract.allowance(a0, a1) == 0 + allowance_left = c.allowance(a0, a1) + c.transferFrom(a0, a2, allowance_left, transact={'from': a1}) + assert c.balanceOf(a0) == TOKEN_TOTAL_SUPPLY - ALLOWANCE + assert c.balanceOf(a1) == 0 + assert c.balanceOf(a2) == ALLOWANCE + assert c.allowance(a0, a1) == 0 -def test_transfer_event(token_tester, get_last_log): - a0 = token_tester.accounts[0] - a1 = token_tester.accounts[1] - k1 = token_tester.k1 - a2 = token_tester.accounts[2] +def test_transfer_event(w3, c, get_logs): + a0, a1, a2 = w3.eth.accounts[:3] - contract = token_tester.c + logs = get_logs(c.transfer(a1, 1, transact={}), c, 'Transfer') - assert contract.transfer(a1, 1) is True - - assert get_last_log(tester, contract) == { - '_from': '0x' + a0.hex(), - '_to': '0x' + a1.hex(), - '_value': 1, - '_event_type': b'Transfer' - } + args = logs[0].args + assert args._from == a0 + assert args._to == a1 + assert args._value == 1 # Test event using transferFrom - assert contract.approve(a1, 10) is True # approve 10 token transfers to a1. - assert contract.transferFrom(a0, a2, 4, sender=k1) # transfer to a2, as a1, from a0's funds. - - assert get_last_log(tester, contract) == { - '_from': '0x' + a0.hex(), - '_to': '0x' + a2.hex(), - '_value': 4, - '_event_type': b'Transfer' - } + c.approve(a1, 10, transact={}) # approve 10 token transfers to a1. + logs = get_logs(c.transferFrom(a0, a2, 4, transact={'from': a1}), c, 'Transfer') # transfer to a2, as a1, from a0's funds. + args = logs[0].args + assert args._from == a0 + assert args._to == a2 + assert args._value == 4 -def test_approval_event(token_tester, get_last_log): - a0 = token_tester.accounts[0] - a1 = token_tester.accounts[1] - contract = token_tester.c +def test_approval_event(w3, c, get_logs): + a0, a1 = w3.eth.accounts[:2] - assert contract.approve(a1, 10) is True # approve 10 token transfers to a1. + logs = get_logs(c.approve(a1, 10, transact={}), c, 'Approval') # approve 10 token transfers to a1. - assert get_last_log(tester, contract) == { - '_owner': '0x' + a0.hex(), - '_spender': '0x' + a1.hex(), - '_value': 10, - '_event_type': b'Approval' - } + args = logs[0].args + assert args._owner == a0 + assert args._spender == a1 + assert args._value == 10 diff --git a/tests/examples/voting/test_ballot.py b/tests/examples/voting/test_ballot.py index a9ffe1a785..26868a6691 100644 --- a/tests/examples/voting/test_ballot.py +++ b/tests/examples/voting/test_ballot.py @@ -1,237 +1,237 @@ -import unittest - -from ethereum.tools import tester -import ethereum.utils as utils - - -def assert_tx_failed(ballot_tester, function_to_test, exception=tester.TransactionFailed): - """ Ensure that transaction fails, reverting state (to prevent gas exhaustion) """ - initial_state = ballot_tester.s.snapshot() - ballot_tester.assertRaises(exception, function_to_test) - ballot_tester.s.revert(initial_state) - - -class TestVoting(unittest.TestCase): - def setUp(self): - # Initialize tester, contract and expose relevant objects - self.t = tester - self.s = self.t.Chain() - self.s.head_state.gas_limit = 10**7 - from vyper import compiler - self.t.languages['vyper'] = compiler.Compiler() - contract_code = open('examples/voting/ballot.v.py').read() - self.c = self.s.contract(contract_code, language='vyper', args=[["Clinton", "Trump"]]) - - def test_initial_state(self): - # Check chairperson is msg.sender - self.assertEqual(utils.remove_0x_head(self.c.chairperson()), self.t.a0.hex()) - # Check propsal names are correct - self.assertEqual(self.c.proposals__name(0), b'Clinton\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') - self.assertEqual(self.c.proposals__name(1), b'Trump\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') - # Check proposal vote_count is 0 - self.assertEqual(self.c.proposals__vote_count(0), 0) - self.assertEqual(self.c.proposals__vote_count(1), 0) - # Check voter_count is 0 - self.assertEqual(self.c.voter_count(), 0) - # Check voter starts empty - self.assertEqual(self.c.voters__delegate(), '0x0000000000000000000000000000000000000000') - self.assertEqual(self.c.voters__vote(), 0) - self.assertEqual(self.c.voters__voted(), False) - self.assertEqual(self.c.voters__weight(), 0) - - def test_give_the_right_to_vote(self): - self.c.give_right_to_vote(self.t.a1) - # Check voter given right has weight of 1 - self.assertEqual(self.c.voters__weight(self.t.a1), 1) - # Check no other voter attributes have changed - self.assertEqual(self.c.voters__delegate(self.t.a1), '0x0000000000000000000000000000000000000000') - self.assertEqual(self.c.voters__vote(self.t.a1), 0) - self.assertEqual(self.c.voters__voted(self.t.a1), False) - # Chairperson can give themselves the right to vote - self.c.give_right_to_vote(self.t.a0) - # Check chairperson has weight of 1 - self.assertEqual(self.c.voters__weight(self.t.a0), 1) - # Check voter_acount is 2 - self.assertEqual(self.c.voter_count(), 2) - # Check several giving rights to vote - self.c.give_right_to_vote(self.t.a2) - self.c.give_right_to_vote(self.t.a3) - self.c.give_right_to_vote(self.t.a4) - self.c.give_right_to_vote(self.t.a5) - # Check voter_acount is now 6 - self.assertEqual(self.c.voter_count(), 6) - # Check chairperson cannot give the right to vote twice to the same voter - assert_tx_failed(self, lambda: self.c.give_right_to_vote(self.t.a5)) - # Check voters weight didn't change - self.assertEqual(self.c.voters__weight(self.t.a5), 1) - - def test_forward_weight(self): - self.c.give_right_to_vote(self.t.a0) - self.c.give_right_to_vote(self.t.a1) - self.c.give_right_to_vote(self.t.a2) - self.c.give_right_to_vote(self.t.a3) - self.c.give_right_to_vote(self.t.a4) - self.c.give_right_to_vote(self.t.a5) - self.c.give_right_to_vote(self.t.a6) - self.c.give_right_to_vote(self.t.a7) - self.c.give_right_to_vote(self.t.a8) - self.c.give_right_to_vote(self.t.a9) - - # aN(V) in these comments means address aN has vote weight V - - self.c.delegate(self.t.a2, sender=self.t.k1) - # a1(0) -> a2(2) a3(1) - self.c.delegate(self.t.a3, sender=self.t.k2) - # a1(0) -> a2(0) -> a3(3) - self.assertEqual(self.c.voters__weight(self.t.a1), 0) - self.assertEqual(self.c.voters__weight(self.t.a2), 0) - self.assertEqual(self.c.voters__weight(self.t.a3), 3) - - self.c.delegate(self.t.a9, sender=self.t.k8) - # a7(1) a8(0) -> a9(2) - self.c.delegate(self.t.a8, sender=self.t.k7) - # a7(0) -> a8(0) -> a9(3) - self.assertEqual(self.c.voters__weight(self.t.a7), 0) - self.assertEqual(self.c.voters__weight(self.t.a8), 0) - self.assertEqual(self.c.voters__weight(self.t.a9), 3) - self.c.delegate(self.t.a7, sender=self.t.k6) - self.c.delegate(self.t.a6, sender=self.t.k5) - self.c.delegate(self.t.a5, sender=self.t.k4) - # a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(6) - self.assertEqual(self.c.voters__weight(self.t.a9), 6) - self.assertEqual(self.c.voters__weight(self.t.a8), 0) - - # a3(3) a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(6) - self.c.delegate(self.t.a4, sender=self.t.k3) - # a3(0) -> a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(3) -> a9(6) - # a3's vote weight of 3 only makes it to a8 in the delegation chain: - self.assertEqual(self.c.voters__weight(self.t.a8), 3) - self.assertEqual(self.c.voters__weight(self.t.a9), 6) - - # call forward_weight again to move the vote weight the - # rest of the way: - self.c.forward_weight(self.t.a8) - # a3(0) -> a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(9) - self.assertEqual(self.c.voters__weight(self.t.a8), 0) - self.assertEqual(self.c.voters__weight(self.t.a9), 9) - - # a0(1) -> a1(0) -> a2(0) -> a3(0) -> a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(9) - self.c.delegate(self.t.a1, sender=self.t.k0) - # a0's vote weight of 1 only makes it to a5 in the delegation chain: - # a0(0) -> a1(0) -> a2(0) -> a3(0) -> a4(0) -> a5(1) -> a6(0) -> a7(0) -> a8(0) -> a9(9) - self.assertEqual(self.c.voters__weight(self.t.a5), 1) - self.assertEqual(self.c.voters__weight(self.t.a9), 9) - - # once again call forward_weight to move the vote weight the - # rest of the way: - self.c.forward_weight(self.t.a5) - # a0(0) -> a1(0) -> a2(0) -> a3(0) -> a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(10) - self.assertEqual(self.c.voters__weight(self.t.a5), 0) - self.assertEqual(self.c.voters__weight(self.t.a9), 10) - - def test_block_short_cycle(self): - self.c.give_right_to_vote(self.t.a0) - self.c.give_right_to_vote(self.t.a1) - self.c.give_right_to_vote(self.t.a2) - self.c.give_right_to_vote(self.t.a3) - self.c.give_right_to_vote(self.t.a4) - self.c.give_right_to_vote(self.t.a5) - - self.c.delegate(self.t.a1, sender=self.t.k0) - self.c.delegate(self.t.a2, sender=self.t.k1) - self.c.delegate(self.t.a3, sender=self.t.k2) - self.c.delegate(self.t.a4, sender=self.t.k3) - # would create a length 5 cycle: - assert_tx_failed(self, lambda: self.c.delegate(self.t.a0, sender=self.t.k4)) - - self.c.delegate(self.t.a5, sender=self.t.k4) - # can't detect length 6 cycle, so this works: - self.c.delegate(self.t.a0, sender=self.t.k5) - # which is fine for the contract; those votes are simply spoiled. - # but this is something the frontend should prevent for user friendliness - - def test_delegate(self): - self.c.give_right_to_vote(self.t.a0) - self.c.give_right_to_vote(self.t.a1) - self.c.give_right_to_vote(self.t.a2) - self.c.give_right_to_vote(self.t.a3) - # Voter's weight is 1 - self.assertEqual(self.c.voters__weight(self.t.a1), 1) - # Voter can delegate: a1 -> a0 - self.c.delegate(self.t.a0, sender=self.t.k1) - # Voter's weight is now 0 - self.assertEqual(self.c.voters__weight(self.t.a1), 0) - # Voter has voted - self.assertEqual(self.c.voters__voted(self.t.a1), True) - # Delegate's weight is 2 - self.assertEqual(self.c.voters__weight(self.t.a0), 2) - # Voter cannot delegate twice - assert_tx_failed(self, lambda: self.c.delegate(self.t.a2, sender=self.t.k1)) - # Voter cannot delegate to themselves - assert_tx_failed(self, lambda: self.c.delegate(self.t.a2, sender=self.t.k2)) - # Voter CAN delegate to someone who hasn't been granted right to vote - # Exercise: prevent that - self.c.delegate(self.t.a6, sender=self.t.k2) - # Voter's delegatation is passed up to final delegate, yielding: - # a3 -> a1 -> a0 - self.c.delegate(self.t.a1, sender=self.t.k3) - # Delegate's weight is 3 - self.assertEqual(self.c.voters__weight(self.t.a0), 3) - - def test_vote(self): - self.c.give_right_to_vote(self.t.a0) - self.c.give_right_to_vote(self.t.a1) - self.c.give_right_to_vote(self.t.a2) - self.c.give_right_to_vote(self.t.a3) - self.c.give_right_to_vote(self.t.a4) - self.c.give_right_to_vote(self.t.a5) - self.c.give_right_to_vote(self.t.a6) - self.c.give_right_to_vote(self.t.a7) - self.c.delegate(self.t.a0, sender=self.t.k1) - self.c.delegate(self.t.a1, sender=self.t.k3) - # Voter can vote - self.c.vote(0) - # Vote count changes based on voters weight - self.assertEqual(self.c.proposals__vote_count(0), 3) - # Voter cannot vote twice - assert_tx_failed(self, lambda: self.c.vote(0)) - # Voter cannot vote if they've delegated - assert_tx_failed(self, lambda: self.c.vote(0, sender=self.t.k1)) - # Several voters can vote - self.c.vote(1, sender=self.t.k4) - self.c.vote(1, sender=self.t.k2) - self.c.vote(1, sender=self.t.k5) - self.c.vote(1, sender=self.t.k6) - self.assertEqual(self.c.proposals__vote_count(1), 4) - # Can't vote on a non-proposal - assert_tx_failed(self, lambda: self.c.vote(2, sender=self.t.k7)) - - def test_winning_proposal(self): - self.c.give_right_to_vote(self.t.a0) - self.c.give_right_to_vote(self.t.a1) - self.c.give_right_to_vote(self.t.a2) - self.c.vote(0) - # Proposal 0 is now winning - self.assertEqual(self.c.winning_proposal(), 0) - self.c.vote(1, sender=self.t.k1) - # Proposal 0 is still winning (the proposals are tied) - self.assertEqual(self.c.winning_proposal(), 0) - self.c.vote(1, sender=self.t.k2) - # Proposal 2 is now winning - self.assertEqual(self.c.winning_proposal(), 1) - - def test_winner_namer(self): - self.c.give_right_to_vote(self.t.a0) - self.c.give_right_to_vote(self.t.a1) - self.c.give_right_to_vote(self.t.a2) - self.c.delegate(self.t.a1, sender=self.t.k2) - self.c.vote(0) - # Proposal 0 is now winning - self.assertEqual(self.c.winner_name(), b'Clinton\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') - self.c.vote(1, sender=self.t.k1) - # Proposal 2 is now winning - self.assertEqual(self.c.winner_name(), b'Trump\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') - - -if __name__ == '__main__': - unittest.main() +import pytest + + +@pytest.fixture +def c(get_contract): + with open('examples/voting/ballot.v.py') as f: + contract_code = f.read() + return get_contract(contract_code, *[[b"Clinton", b"Trump"]]) + + +z0 = '0x0000000000000000000000000000000000000000' + + +def test_initial_state(w3, c): + a0 = w3.eth.accounts[0] + # Check chairperson is msg.sender + assert c.chairperson() == a0 + # Check propsal names are correct + assert c.proposals__name(0)[:7] == b'Clinton' + assert c.proposals__name(1)[:5] == b'Trump' + # Check proposal vote_count is 0 + assert c.proposals__vote_count(0) == 0 + assert c.proposals__vote_count(1) == 0 + # Check voter_count is 0 + assert c.voter_count() == 0 + # Check voter starts empty + assert c.voters__delegate(z0) is None + assert c.voters__vote(z0) == 0 + assert c.voters__voted(z0) is False + assert c.voters__weight(z0) == 0 + + +def test_give_the_right_to_vote(w3, c, assert_tx_failed): + a0, a1, a2, a3, a4, a5 = w3.eth.accounts[:6] + c.give_right_to_vote(a1, transact={}) + # Check voter given right has weight of 1 + assert c.voters__weight(a1) == 1 + # Check no other voter attributes have changed + assert c.voters__delegate(a1) is None + assert c.voters__vote(a1) == 0 + assert c.voters__voted(a1) is False + # Chairperson can give themselves the right to vote + c.give_right_to_vote(a0, transact={}) + # Check chairperson has weight of 1 + assert c.voters__weight(a0) == 1 + # Check voter_acount is 2 + assert c.voter_count() == 2 + # Check several giving rights to vote + c.give_right_to_vote(a2, transact={}) + c.give_right_to_vote(a3, transact={}) + c.give_right_to_vote(a4, transact={}) + c.give_right_to_vote(a5, transact={}) + # Check voter_acount is now 6 + assert c.voter_count() == 6 + # Check chairperson cannot give the right to vote twice to the same voter + assert_tx_failed(lambda: c.give_right_to_vote(a5, transact={})) + # Check voters weight didn't change + assert c.voters__weight(a5) == 1 + + +def test_forward_weight(w3, c): + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = w3.eth.accounts[:10] + c.give_right_to_vote(a0, transact={}) + c.give_right_to_vote(a1, transact={}) + c.give_right_to_vote(a2, transact={}) + c.give_right_to_vote(a3, transact={}) + c.give_right_to_vote(a4, transact={}) + c.give_right_to_vote(a5, transact={}) + c.give_right_to_vote(a6, transact={}) + c.give_right_to_vote(a7, transact={}) + c.give_right_to_vote(a8, transact={}) + c.give_right_to_vote(a9, transact={}) + + # aN(V) in these comments means address aN has vote weight V + + c.delegate(a2, transact={'from': a1}) + # a1(0) -> a2(2) a3(1) + c.delegate(a3, transact={'from': a2}) + # a1(0) -> a2(0) -> a3(3) + assert c.voters__weight(a1) == 0 + assert c.voters__weight(a2) == 0 + assert c.voters__weight(a3) == 3 + + c.delegate(a9, transact={'from': a8}) + # a7(1) a8(0) -> a9(2) + c.delegate(a8, transact={'from': a7}) + # a7(0) -> a8(0) -> a9(3) + assert c.voters__weight(a7) == 0 + assert c.voters__weight(a8) == 0 + assert c.voters__weight(a9) == 3 + c.delegate(a7, transact={'from': a6}) + c.delegate(a6, transact={'from': a5}) + c.delegate(a5, transact={'from': a4}) + # a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(6) + assert c.voters__weight(a9) == 6 + assert c.voters__weight(a8) == 0 + + # a3(3) a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(6) + c.delegate(a4, transact={'from': a3}) + # a3(0) -> a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(3) -> a9(6) + # a3's vote weight of 3 only makes it to a8 in the delegation chain: + assert c.voters__weight(a8) == 3 + assert c.voters__weight(a9) == 6 + + # call forward_weight again to move the vote weight the + # rest of the way: + c.forward_weight(a8, transact={}) + # a3(0) -> a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(9) + assert c.voters__weight(a8) == 0 + assert c.voters__weight(a9) == 9 + + # a0(1) -> a1(0) -> a2(0) -> a3(0) -> a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(9) + c.delegate(a1, transact={'from': a0}) + # a0's vote weight of 1 only makes it to a5 in the delegation chain: + # a0(0) -> a1(0) -> a2(0) -> a3(0) -> a4(0) -> a5(1) -> a6(0) -> a7(0) -> a8(0) -> a9(9) + assert c.voters__weight(a5) == 1 + assert c.voters__weight(a9) == 9 + + # once again call forward_weight to move the vote weight the + # rest of the way: + c.forward_weight(a5, transact={}) + # a0(0) -> a1(0) -> a2(0) -> a3(0) -> a4(0) -> a5(0) -> a6(0) -> a7(0) -> a8(0) -> a9(10) + assert c.voters__weight(a5) == 0 + assert c.voters__weight(a9) == 10 + + +def test_block_short_cycle(w3, c, assert_tx_failed): + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = w3.eth.accounts[:10] + c.give_right_to_vote(a0, transact={}) + c.give_right_to_vote(a1, transact={}) + c.give_right_to_vote(a2, transact={}) + c.give_right_to_vote(a3, transact={}) + c.give_right_to_vote(a4, transact={}) + c.give_right_to_vote(a5, transact={}) + + c.delegate(a1, transact={'from': a0}) + c.delegate(a2, transact={'from': a1}) + c.delegate(a3, transact={'from': a2}) + c.delegate(a4, transact={'from': a3}) + # would create a length 5 cycle: + assert_tx_failed(lambda: c.delegate(a0, transact={'from': a4})) + + c.delegate(a5, transact={'from': a4}) + # can't detect length 6 cycle, so this works: + c.delegate(a0, transact={'from': a5}) + # which is fine for the contract; those votes are simply spoiled. + # but this is something the frontend should prevent for user friendliness + + +def test_delegate(w3, c, assert_tx_failed): + a0, a1, a2, a3, a4, a5, a6 = w3.eth.accounts[:7] + c.give_right_to_vote(a0, transact={}) + c.give_right_to_vote(a1, transact={}) + c.give_right_to_vote(a2, transact={}) + c.give_right_to_vote(a3, transact={}) + # Voter's weight is 1 + assert c.voters__weight(a1) == 1 + # Voter can delegate: a1 -> a0 + c.delegate(a0, transact={'from': a1}) + # Voter's weight is now 0 + assert c.voters__weight(a1) == 0 + # Voter has voted + assert c.voters__voted(a1) is True + # Delegate's weight is 2 + assert c.voters__weight(a0) == 2 + # Voter cannot delegate twice + assert_tx_failed(lambda: c.delegate(a2, transact={'from': a1})) + # Voter cannot delegate to themselves + assert_tx_failed(lambda: c.delegate(a2, transact={'from': a2})) + # Voter CAN delegate to someone who hasn't been granted right to vote + # Exercise: prevent that + c.delegate(a6, transact={'from': a2}) + # Voter's delegatation is passed up to final delegate, yielding: + # a3 -> a1 -> a0 + c.delegate(a1, transact={'from': a3}) + # Delegate's weight is 3 + assert c.voters__weight(a0) == 3 + + +def test_vote(w3, c, assert_tx_failed): + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = w3.eth.accounts[:10] + c.give_right_to_vote(a0, transact={}) + c.give_right_to_vote(a1, transact={}) + c.give_right_to_vote(a2, transact={}) + c.give_right_to_vote(a3, transact={}) + c.give_right_to_vote(a4, transact={}) + c.give_right_to_vote(a5, transact={}) + c.give_right_to_vote(a6, transact={}) + c.give_right_to_vote(a7, transact={}) + c.delegate(a0, transact={'from': a1}) + c.delegate(a1, transact={'from': a3}) + # Voter can vote + c.vote(0, transact={}) + # Vote count changes based on voters weight + assert c.proposals__vote_count(0) == 3 + # Voter cannot vote twice + assert_tx_failed(lambda: c.vote(0)) + # Voter cannot vote if they've delegated + assert_tx_failed(lambda: c.vote(0, transact={'from': a1})) + # Several voters can vote + c.vote(1, transact={'from': a4}) + c.vote(1, transact={'from': a2}) + c.vote(1, transact={'from': a5}) + c.vote(1, transact={'from': a6}) + assert c.proposals__vote_count(1) == 4 + # Can't vote on a non-proposal + assert_tx_failed(lambda: c.vote(2, transact={'from': a7})) + + +def test_winning_proposal(w3, c): + a0, a1, a2 = w3.eth.accounts[:3] + c.give_right_to_vote(a0, transact={}) + c.give_right_to_vote(a1, transact={}) + c.give_right_to_vote(a2, transact={}) + c.vote(0, transact={}) + # Proposal 0 is now winning + assert c.winning_proposal() == 0 + c.vote(1, transact={'from': a1}) + # Proposal 0 is still winning (the proposals are tied) + assert c.winning_proposal() == 0 + c.vote(1, transact={'from': a2}) + # Proposal 2 is now winning + assert c.winning_proposal() == 1 + + +def test_winner_namer(w3, c): + a0, a1, a2 = w3.eth.accounts[:3] + c.give_right_to_vote(a0, transact={}) + c.give_right_to_vote(a1, transact={}) + c.give_right_to_vote(a2, transact={}) + c.delegate(a1, transact={'from': a2}) + c.vote(0, transact={}) + # Proposal 0 is now winning + assert c.winner_name()[:7], b'Clinton' + c.vote(1, transact={'from': a1}) + # Proposal 2 is now winning + assert c.winner_name()[:5], b'Trump' diff --git a/tests/examples/wallet/test_wallet.py b/tests/examples/wallet/test_wallet.py index bb70c4e3e5..ffa1eb3506 100644 --- a/tests/examples/wallet/test_wallet.py +++ b/tests/examples/wallet/test_wallet.py @@ -1,48 +1,79 @@ -from ethereum.tools import tester as t -from ethereum import utils -from vyper import compiler +import pytest +from eth_keys import KeyAPI +from eth_account import Account +from eth_utils import is_same_address -t.languages['vyper'] = compiler.Compiler() -t.s = t.Chain() -t.s.head_state.gas_limit = 10**9 -x = t.s.contract(open('examples/wallet/wallet.v.py').read(), args=[[t.a1, t.a2, t.a3, t.a4, t.a5], 3], language='vyper') -print(t.s.last_tx.data[-192:]) -# Sends wei to the contract for future transactions gas costs -t.s.tx(sender=t.k1, to=x.address, value=10**17) +@pytest.fixture +def c(w3, get_contract): + a0, a1, a2, a3, a4, a5, a6 = w3.eth.accounts[:7] + with open('examples/wallet/wallet.v.py') as f: + code = f.read() + # Sends wei to the contract for future transactions gas costs + c = get_contract(code, *[[a1, a2, a3, a4, a5], 3]) + w3.eth.sendTransaction({'to': c.address, 'value': 10**17}) + return c -print([utils.encode_hex(a) for a in [t.a1, t.a2, t.a3, t.a4, t.a5]]) +@pytest.fixture +def sign(keccak): + def _sign(seq, to, value, data, key): + keys = KeyAPI() + comb = seq.to_bytes(32, "big") + b'\x00' * 12 + to + value.to_bytes(32, "big") + data + h1 = keccak(comb) + h2 = keccak(b"\x19Ethereum Signed Message:\n32" + h1) + sig = keys.ecdsa_sign(h2, key) + return [28 if sig.v == 1 else 27, sig.r, sig.s] + return _sign -# Signs a transaction with a given key -def sign(seq, to, value, data, key): - h1 = utils.sha3(utils.encode_int32(seq) + b'\x00' * 12 + to + utils.encode_int32(value) + data) - h2 = utils.sha3(b"\x19Ethereum Signed Message:\n32" + h1) - return list(utils.ecsign(h2, key)) +def test_approve(w3, c, tester, assert_tx_failed, sign): + a0, a1, a2, a3, a4, a5, a6 = w3.eth.accounts[:7] + k0, k1, k2, k3, k4, k5, k6, k7 = tester.backend.account_keys[:8] -def test_approve(assert_tx_failed): to, value, data = b'\x35' * 20, 10**16, b"" - assert x.approve(0, to, value, data, [sign(0, to, value, data, k) if k else [0, 0, 0] for k in (t.k1, 0, t.k3, 0, t.k5)], value=value, sender=t.k1) + to_address = w3.toChecksumAddress(to) + + def pack_and_sign(seq, *args): + sigs = [ + sign(seq, to, value, data, k) + if k else [0, 0, 0] + for k in args + ] + return sigs + + # Legitimate approval + sigs = pack_and_sign(0, k1, 0, k3, 0, k5) + c.approve(0, '0x' + to.hex(), value, data, sigs, transact={'value': value, 'from': a1}) # Approve fails if only 2 signatures are given - assert_tx_failed(lambda: x.approve(1, to, value, data, [sign(1, to, value, data, k) if k else [0, 0, 0] for k in (t.k1, 0, 0, 0, t.k5)], value=value, sender=t.k1)) + sigs = pack_and_sign(1, k1, 0, k3, 0, 0) + assert_tx_failed(lambda: c.approve(1, to_address, value, data, sigs, transact={'value': value, 'from': a1})) # Approve fails if an invalid signature is given - assert_tx_failed(lambda: x.approve(1, to, value, data, [sign(1, to, value, data, k) if k else [0, 0, 0] for k in (t.k1, 0, t.k7, 0, t.k5)], value=value, sender=t.k1)) + sigs = pack_and_sign(1, k1, 0, k7, 0, k5) + assert_tx_failed(lambda: c.approve(1, to_address, value, data, sigs, transact={'value': value, 'from': a1})) # Approve fails if transaction number is incorrect (the first argument should be 1) - assert_tx_failed(lambda: x.approve(0, to, value, data, [sign(0, to, value, data, k) if k else [0, 0, 0] for k in (t.k1, 0, t.k3, 0, t.k5)], value=value, sender=t.k1)) + sigs = pack_and_sign(0, k1, 0, k3, 0, k5) + assert_tx_failed(lambda: c.approve(0, to_address, value, data, sigs, transact={'value': value, 'from': a1})) # Approve fails if not enough value is sent - assert_tx_failed(lambda: x.approve(1, to, value, data, [sign(1, to, value, data, k) if k else [0, 0, 0] for k in (t.k1, 0, t.k3, 0, t.k5)], value=0, sender=t.k1)) - assert x.approve(1, to, value, data, [sign(1, to, value, data, k) if k else [0, 0, 0] for k in (t.k1, 0, t.k3, 0, t.k5)], value=value, sender=t.k1) + sigs = pack_and_sign(1, k1, 0, k3, 0, k5) + assert_tx_failed(lambda: c.approve(1, to_address, value, data, sigs, transact={'value': 0, 'from': a1})) + sigs = pack_and_sign(1, k1, 0, k3, 0, k5) + assert c.approve(1, to_address, value, data, sigs, call={'value': value, 'from': a1}) + print("Basic tests passed") -def test_javascript_signatures(): +def test_javascript_signatures(w3, get_contract): + a3 = w3.eth.accounts[2] # The zero address will cause `approve` to default to valid signatures zero_address = "0x0000000000000000000000000000000000000000" - accounts = ["0x776ba14735ff84789320718cf0aa43e91f7a8ce1", "0x095ce4e4240fa66ff90282c26847456e3f3b5002"] + accounts = [ + "0x776ba14735ff84789320718cf0aa43e91f7a8ce1", + "0x095ce4e4240fa66ff90282c26847456e3f3b5002" + ] # The address that will receive the transaction - recipient = "0x776ba14735ff84789320718cf0aa43e91f7a8ce1" + recipient = "0x776Ba14735FF84789320718cf0aa43e91F7A8Ce1" # These are the matching sigs to the accounts raw_sigs = [ "0x4a89507bf71749fb338ed13fba623a683d9ecab0fb9c389a4298525c043e38281a00ab65628bb18a382eb8c8b4fb4dae95ccc993cf49f617c60d8051180778601c", @@ -50,20 +81,29 @@ def test_javascript_signatures(): ] # Turns the raw sigs into sigs - sigs = [(utils.big_endian_to_int(x[64:]), utils.big_endian_to_int(x[:32]), utils.big_endian_to_int(x[32:64])) for x in - map(lambda z: utils.decode_hex(z[2:]), raw_sigs)] + sigs = [ + ( + w3.toInt(x[64:]), # v + w3.toInt(x[:32]), # r + w3.toInt(x[32:64]) # s + ) for x in map(lambda z: w3.toBytes(hexstr=z[2:]), raw_sigs) + ] + + h = w3.sha3((0).to_bytes(32, "big") + b'\x00' * 12 + w3.toBytes(hexstr=recipient[2:]) + (25).to_bytes(32, "big") + b'') + h2 = w3.sha3(b"\x19Ethereum Signed Message:\n32" + h) - h = utils.sha3(utils.encode_int32(0) + b'\x00' * 12 + utils.decode_hex(recipient[2:]) + utils.encode_int32(25) + b'') - h2 = utils.sha3(b"\x19Ethereum Signed Message:\n32" + h) # Check to make sure the signatures are valid - assert '0x' + utils.encode_hex(utils.sha3(utils.ecrecover_to_pub(h2, sigs[0][0], sigs[0][1], sigs[0][2]))[12:]) == accounts[0] - assert '0x' + utils.encode_hex(utils.sha3(utils.ecrecover_to_pub(h2, sigs[1][0], sigs[1][1], sigs[1][2]))[12:]) == accounts[1] + assert is_same_address(Account.recoverHash(h2, sigs[0]), accounts[0]) + assert is_same_address(Account.recoverHash(h2, sigs[1]), accounts[1]) # Set the owners to zero addresses - x2 = t.s.contract(open('examples/wallet/wallet.v.py').read(), args=[accounts + [t.a3, zero_address, zero_address], 2], language='vyper') - t.s.tx(sender=t.k1, to=x2.address, value=10**17) + with open('examples/wallet/wallet.v.py') as f: + owners = [w3.toChecksumAddress(x) for x in accounts + [a3, zero_address, zero_address]] + x2 = get_contract(f.read(), *[owners, 2]) + + w3.eth.sendTransaction({'to': x2.address, 'value': 10**17}) # There's no need to pass in signatures because the owners are 0 addresses causing them to default to valid signatures - assert x2.approve(0, recipient, 25, "", sigs + [[0, 0, 0]] * 3, value=25, sender=t.k1) + assert x2.approve(0, recipient, 25, b"", sigs + [[0, 0, 0]] * 3, call={'to': x2.address, 'value': 10**17}) print("Javascript signature tests passed") diff --git a/tests/parser/features/arithmetic/test_modulo.py b/tests/parser/features/arithmetic/test_modulo.py index 039d826900..f40922f17f 100644 --- a/tests/parser/features/arithmetic/test_modulo.py +++ b/tests/parser/features/arithmetic/test_modulo.py @@ -1,4 +1,5 @@ from vyper.exceptions import TypeMismatchException +from decimal import Decimal def test_modulo(get_contract_with_gas_estimation): @@ -22,9 +23,9 @@ def num_modulo_decimal() -> decimal: """ c = get_contract_with_gas_estimation(code) assert c.num_modulo_num() == 1 - assert c.decimal_modulo_decimal() == .18 - assert c.decimal_modulo_num() == .5 - assert c.num_modulo_decimal() == .5 + assert c.decimal_modulo_decimal() == Decimal('.18') + assert c.decimal_modulo_num() == Decimal('.5') + assert c.num_modulo_decimal() == Decimal('.5') def test_modulo_with_different_units(assert_compile_failed, get_contract_with_gas_estimation): diff --git a/tests/parser/features/external_contracts/test_erc20_abi.py b/tests/parser/features/external_contracts/test_erc20_abi.py index 8318288b3c..8ebda804a3 100644 --- a/tests/parser/features/external_contracts/test_erc20_abi.py +++ b/tests/parser/features/external_contracts/test_erc20_abi.py @@ -1,8 +1,9 @@ import pytest -from ethereum.abi import ValueOutOfBounds +from web3.exceptions import ValidationError -TOKEN_NAME = "Vypercoin" -TOKEN_SYMBOL = "FANG" + +TOKEN_NAME = b"Vypercoin" +TOKEN_SYMBOL = b"FANG" TOKEN_DECIMALS = 18 TOKEN_INITIAL_SUPPLY = (21 * 10 ** 6) TOKEN_TOTAL_SUPPLY = TOKEN_INITIAL_SUPPLY * (10 ** TOKEN_DECIMALS) @@ -10,8 +11,9 @@ @pytest.fixture def erc20(get_contract): - erc20_code = open('examples/tokens/vypercoin.v.py').read() - return get_contract(erc20_code, args=[TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS, TOKEN_INITIAL_SUPPLY]) + with open('examples/tokens/vypercoin.v.py') as f: + contract = get_contract(f.read(), *[TOKEN_NAME, TOKEN_SYMBOL, TOKEN_DECIMALS, TOKEN_INITIAL_SUPPLY]) + return contract @pytest.fixture @@ -55,57 +57,55 @@ def transferFrom(_from: address, _to: address, _value: int128(uint256)) -> bool: def allowance(_owner: address, _spender: address) -> uint256: return self.token_address.allowance(_owner, _spender) """ - return get_contract(erc20_caller_code, args=[erc20.address]) + return get_contract(erc20_caller_code, *[erc20.address]) def pad_bytes32(instr): """ Pad a string \x00 bytes to return correct bytes32 representation. """ - bstr = instr.encode() - return bstr + (32 - len(bstr)) * b'\x00' + return instr + (32 - len(instr)) * b'\x00' -def test_initial_state(t, erc20_caller): - assert erc20_caller.totalSupply() == TOKEN_TOTAL_SUPPLY == erc20_caller.balanceOf(t.a0) - assert erc20_caller.balanceOf(t.a1) == 0 +def test_initial_state(w3, erc20_caller): + assert erc20_caller.totalSupply() == TOKEN_TOTAL_SUPPLY == erc20_caller.balanceOf(w3.eth.accounts[0]) + assert erc20_caller.balanceOf(w3.eth.accounts[1]) == 0 assert erc20_caller.name() == pad_bytes32(TOKEN_NAME) assert erc20_caller.symbol() == pad_bytes32(TOKEN_SYMBOL) assert erc20_caller.decimals() == TOKEN_DECIMALS -def test_call_transfer(t, chain, erc20, erc20_caller, assert_tx_failed): +def test_call_transfer(w3, erc20, erc20_caller, assert_tx_failed): # Basic transfer. - erc20.transfer(erc20_caller.address, 10) + erc20.transfer(erc20_caller.address, 10, transact={}) assert erc20.balanceOf(erc20_caller.address) == 10 - erc20_caller.transfer(t.a1, 10) + erc20_caller.transfer(w3.eth.accounts[1], 10, transact={}) assert erc20.balanceOf(erc20_caller.address) == 0 - assert erc20.balanceOf(t.a1) == 10 + assert erc20.balanceOf(w3.eth.accounts[1]) == 10 # more than allowed - assert_tx_failed(lambda: erc20_caller.transfer(t.a1, TOKEN_TOTAL_SUPPLY)) + assert_tx_failed(lambda: erc20_caller.transfer(w3.eth.accounts[1], TOKEN_TOTAL_SUPPLY)) - t.s = chain # Negative transfer value. assert_tx_failed( - function_to_test=lambda: erc20_caller.transfer(t.a1, -1), - exception=ValueOutOfBounds + function_to_test=lambda: erc20_caller.transfer(w3.eth.accounts[1], -1), + exception=ValidationError ) -def test_caller_approve_allowance(t, erc20, erc20_caller): +def test_caller_approve_allowance(w3, erc20, erc20_caller): assert erc20_caller.allowance(erc20.address, erc20_caller.address) == 0 - assert erc20.approve(erc20_caller.address, 10) - assert erc20_caller.allowance(t.a0, erc20_caller.address) == 10 + assert erc20.approve(erc20_caller.address, 10, transact={}) + assert erc20_caller.allowance(w3.eth.accounts[0], erc20_caller.address) == 10 -def test_caller_tranfer_from(t, erc20, erc20_caller, assert_tx_failed): +def test_caller_tranfer_from(w3, erc20, erc20_caller, assert_tx_failed): # Cannot transfer tokens that are unavailable - assert_tx_failed(lambda: erc20_caller.transferFrom(t.a0, erc20_caller.address, 10)) + assert_tx_failed(lambda: erc20_caller.transferFrom(w3.eth.accounts[0], erc20_caller.address, 10)) assert erc20.balanceOf(erc20_caller.address) == 0 - assert erc20.approve(erc20_caller.address, 10) - erc20_caller.transferFrom(t.a0, erc20_caller.address, 5) + assert erc20.approve(erc20_caller.address, 10, transact={}) + erc20_caller.transferFrom(w3.eth.accounts[0], erc20_caller.address, 5, transact={}) assert erc20.balanceOf(erc20_caller.address) == 5 - assert erc20_caller.allowance(t.a0, erc20_caller.address) == 5 - erc20_caller.transferFrom(t.a0, erc20_caller.address, 3) + assert erc20_caller.allowance(w3.eth.accounts[0], erc20_caller.address) == 5 + erc20_caller.transferFrom(w3.eth.accounts[0], erc20_caller.address, 3, transact={}) assert erc20.balanceOf(erc20_caller.address) == 8 - assert erc20_caller.allowance(t.a0, erc20_caller.address) == 2 + assert erc20_caller.allowance(w3.eth.accounts[0], erc20_caller.address) == 2 diff --git a/tests/parser/features/external_contracts/test_external_contract_calls.py b/tests/parser/features/external_contracts/test_external_contract_calls.py index 5f4473b5c0..c60d698989 100644 --- a/tests/parser/features/external_contracts/test_external_contract_calls.py +++ b/tests/parser/features/external_contracts/test_external_contract_calls.py @@ -47,7 +47,7 @@ def array() -> bytes[3]: """ lucky_number = 7 - c = get_contract_with_gas_estimation(contract_1, args=[lucky_number]) + c = get_contract_with_gas_estimation(contract_1, *[lucky_number]) contract_2 = """ class Foo(): @@ -109,7 +109,7 @@ def set_lucky(arg1: address, arg2: int128): c2 = get_contract(contract_2) assert c.lucky() == 0 - c2.set_lucky(c.address, lucky_number) + c2.set_lucky(c.address, lucky_number, transact={}) assert c.lucky() == lucky_number print('Successfully executed an external contract call state change') @@ -143,8 +143,8 @@ def set_lucky_stmt(arg1: address, arg2: int128) -> int128: """ c2 = get_contract_with_gas_estimation(contract_2) - assert_tx_failed(lambda: c2.set_lucky_expr(c.address, lucky_number)) - assert_tx_failed(lambda: c2.set_lucky_stmt(c.address, lucky_number)) + assert_tx_failed(lambda: c2.set_lucky_expr(c.address, lucky_number, transact={})) + assert_tx_failed(lambda: c2.set_lucky_stmt(c.address, lucky_number, transact={})) print('Successfully tested an constant external contract call attempted state change') @@ -182,8 +182,8 @@ def set_lucky(arg1: address, arg2: int128): """ c3 = get_contract(contract_3) - c3.set_lucky(c.address, lucky_number_1) - c3.set_lucky(c2.address, lucky_number_2) + c3.set_lucky(c.address, lucky_number_1, transact={}) + c3.set_lucky(c2.address, lucky_number_2, transact={}) assert c.lucky() == lucky_number_1 assert c2.lucky() == lucky_number_2 print('Successfully executed multiple external contract calls to different contracts based on address') @@ -199,7 +199,7 @@ def __init__(_lucky: int128): """ lucky_number = 7 - c = get_contract(contract_1, args=[lucky_number]) + c = get_contract(contract_1, *[lucky_number]) contract_2 = """ class Foo(): @@ -225,7 +225,7 @@ def __init__(_lucky: int128): """ lucky_number = 7 - c = get_contract(contract_1, args=[lucky_number]) + c = get_contract(contract_1, *[lucky_number]) contract_2 = """ class Foo(): @@ -238,7 +238,7 @@ def __init__(arg1: address): self.magic_number = Foo(arg1).lucky() """ - c2 = get_contract(contract_2, args=[c.address]) + c2 = get_contract(contract_2, *[c.address]) contract_3 = """ class Bar(): def magic_number() -> int128: pass @@ -250,7 +250,7 @@ def __init__(arg1: address): self.best_number = Bar(arg1).magic_number() """ - c3 = get_contract(contract_3, args=[c2.address]) + c3 = get_contract(contract_3, *[c2.address]) assert c3.best_number() == lucky_number print('Successfully executed a multiple external contract calls') @@ -288,7 +288,7 @@ def _expr(x: address) -> int128: assert_tx_failed(lambda: c2._expr(c2.address)) -def test_invalid_nonexistent_contract_call(t, assert_tx_failed, get_contract): +def test_invalid_nonexistent_contract_call(w3, assert_tx_failed, get_contract): contract_1 = """ @public def bar() -> int128: @@ -308,8 +308,8 @@ def foo(x: address) -> int128: c2 = get_contract(contract_2) assert c2.foo(c1.address) == 1 - assert_tx_failed(lambda: c2.foo(t.a1)) - assert_tx_failed(lambda: c2.foo(t.a7)) + assert_tx_failed(lambda: c2.foo(w3.eth.accounts[0])) + assert_tx_failed(lambda: c2.foo(w3.eth.accounts[3])) def test_invalid_contract_reference_declaration(assert_tx_failed, get_contract): @@ -440,10 +440,10 @@ def get_lucky(contract_address: contract(Bar)) -> int128: c2 = get_contract(contract_2) assert c1.get_lucky() == 0 assert c2.get_lucky(c1.address) == 0 - c1.set_lucky(6) + c1.set_lucky(6, transact={}) assert c1.get_lucky() == 6 assert c2.get_lucky(c1.address) == 6 - c2.set_lucky(c1.address) + c2.set_lucky(c1.address, transact={}) assert c1.get_lucky() == 1 assert c2.get_lucky(c1.address) == 1 @@ -482,13 +482,13 @@ def get_lucky() -> int128: c3 = get_contract_with_gas_estimation(contract_3) assert c1.get_lucky() == 1 assert c2.get_lucky() == 2 - c3.set_contract(c1.address) + c3.set_contract(c1.address, transact={}) assert c3.get_lucky() == 1 - c3.set_contract(c2.address) + c3.set_contract(c2.address, transact={}) assert c3.get_lucky() == 2 -def test_address_can_returned_from_contract_type(get_contract, utils): +def test_address_can_returned_from_contract_type(get_contract): contract_1 = """ @public def bar() -> int128: @@ -510,8 +510,8 @@ def get_bar() -> int128: """ c1 = get_contract(contract_1) c2 = get_contract(contract_2) - c2.foo(c1.address) - assert utils.remove_0x_head(c2.bar_contract()) == c1.address.hex() + c2.foo(c1.address, transact={}) + assert c2.bar_contract() == c1.address assert c2.get_bar() == 1 @@ -547,7 +547,7 @@ def foo(contract_address: contract(Bar)) -> int128: assert_compile_failed(lambda: get_contract(contract_1), InvalidTypeException) -def test_external_with_payble_value(chain, get_contract_with_gas_estimation): +def test_external_with_payble_value(w3, get_contract_with_gas_estimation): contract_1 = """ @payable @public @@ -585,21 +585,25 @@ def get_lucky(amount_to_send: int128) -> int128: # Set address. assert c1.get_lucky() == 1 assert c1.get_balance() == 0 - c2.set_contract(c1.address) + + c2.set_contract(c1.address, transact={}) # Send some eth - assert c2.get_lucky(value=500) == 1 + assert c2.get_lucky(0, call={'value': 500}) == 1 + c2.get_lucky(0, transact={'value': 500}) # Contract 1 received money. assert c1.get_balance() == 500 - assert chain.head_state.get_balance(c1.address) == 500 - assert chain.head_state.get_balance(c2.address) == 0 + assert w3.eth.getBalance(c1.address) == 500 + assert w3.eth.getBalance(c2.address) == 0 # Send subset of amount - assert c2.get_lucky(250, value=500) == 1 + assert c2.get_lucky(250, call={'value': 500}) == 1 + c2.get_lucky(250, transact={'value': 500}) + # Contract 1 received more money. assert c1.get_balance() == 750 - assert chain.head_state.get_balance(c1.address) == 750 - assert chain.head_state.get_balance(c2.address) == 250 + assert w3.eth.getBalance(c1.address) == 750 + assert w3.eth.getBalance(c2.address) == 250 def test_external_call_with_gas(assert_tx_failed, get_contract_with_gas_estimation): @@ -627,7 +631,7 @@ def get_lucky(gas_amount: int128) -> int128: c1 = get_contract_with_gas_estimation(contract_1) c2 = get_contract_with_gas_estimation(contract_2) - c2.set_contract(c1.address) + c2.set_contract(c1.address, transact={}) assert c2.get_lucky(1000) == 656598 assert_tx_failed(lambda: c2.get_lucky(100)) # too little gas. diff --git a/tests/parser/features/external_contracts/test_modifiable_external_contract_calls.py b/tests/parser/features/external_contracts/test_modifiable_external_contract_calls.py index 39e7ceb02d..ea35e2e9ee 100644 --- a/tests/parser/features/external_contracts/test_modifiable_external_contract_calls.py +++ b/tests/parser/features/external_contracts/test_modifiable_external_contract_calls.py @@ -32,11 +32,11 @@ def static_set_lucky(_lucky: int128): """ c1 = get_contract(contract_1) - c2 = get_contract(contract_2, args=[c1.address]) - c2.modifiable_set_lucky(7) + c2 = get_contract(contract_2, *[c1.address]) + c2.modifiable_set_lucky(7, transact={}) assert c1.lucky() == 7 # Fails attempting a state change after a call to a static address - assert_tx_failed(lambda: c2.static_set_lucky(5)) + assert_tx_failed(lambda: c2.static_set_lucky(5, transact={})) assert c1.lucky() == 7 @@ -73,11 +73,11 @@ def static_set_lucky(_lucky: int128): """ c1 = get_contract(contract_1) - c2 = get_contract(contract_2, args=[c1.address]) - c2.modifiable_set_lucky(7) + c2 = get_contract(contract_2, *[c1.address]) + c2.modifiable_set_lucky(7, transact={}) assert c1.lucky() == 7 # Fails attempting a state change after a call to a static address - assert_tx_failed(lambda: c2.static_set_lucky(5)) + assert_tx_failed(lambda: c2.static_set_lucky(5, transact={})) assert c1.lucky() == 7 @@ -142,19 +142,19 @@ def static_modifiable_set_lucky(_lucky: int128): """ c1 = get_contract(contract_1) - c2 = get_contract(contract_2, args=[c1.address]) - c3 = get_contract(contract_3, args=[c2.address]) + c2 = get_contract(contract_2, *[c1.address]) + c3 = get_contract(contract_3, *[c2.address]) assert c1.lucky() == 0 - c3.modifiable_modifiable_set_lucky(7) + c3.modifiable_modifiable_set_lucky(7, transact={}) assert c1.lucky() == 7 - assert_tx_failed(lambda: c3.modifiable_static_set_lucky(6)) - assert_tx_failed(lambda: c3.static_modifiable_set_lucky(6)) - assert_tx_failed(lambda: c3.static_static_set_lucky(6)) + assert_tx_failed(lambda: c3.modifiable_static_set_lucky(6, transact={})) + assert_tx_failed(lambda: c3.static_modifiable_set_lucky(6, transact={})) + assert_tx_failed(lambda: c3.static_static_set_lucky(6, transact={})) assert c1.lucky() == 7 -def test_address_can_returned_from_contract_type(get_contract, utils): +def test_address_can_returned_from_contract_type(get_contract): contract_1 = """ @public def bar() -> int128: @@ -176,8 +176,8 @@ def get_bar() -> int128: """ c1 = get_contract(contract_1) c2 = get_contract(contract_2) - c2.foo(c1.address) - assert utils.remove_0x_head(c2.bar_contract()) == c1.address.hex() + c2.foo(c1.address, transact={}) + assert c2.bar_contract() == c1.address assert c2.get_bar() == 1 diff --git a/tests/parser/features/iteration/test_for_in_list.py b/tests/parser/features/iteration/test_for_in_list.py index 82b0442c3e..5f0e1bcce7 100644 --- a/tests/parser/features/iteration/test_for_in_list.py +++ b/tests/parser/features/iteration/test_for_in_list.py @@ -1,4 +1,5 @@ from vyper.exceptions import StructureException, VariableDeclarationException +from decimal import Decimal def test_basic_for_in_list(get_contract_with_gas_estimation): @@ -51,7 +52,7 @@ def data() -> int128: c = get_contract_with_gas_estimation(code) assert c.data() == -1 - assert c.set() is None + c.set(transact={}) assert c.data() == 7 @@ -74,7 +75,7 @@ def data() -> address: c = get_contract_with_gas_estimation(code) - assert c.data() == "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1" + assert c.data() == "0x82A978B3f5962A5b0957d9ee9eEf472EE55B42F1" def test_multiple_for_loops_1(get_contract_with_gas_estimation): @@ -163,11 +164,11 @@ def iterate_return_second() -> address: c = get_contract_with_gas_estimation(code) - c.set(0, '0x82A978B3f5962A5b0957d9ee9eEf472EE55B42F1') - c.set(1, '0x7d577a597B2742b498Cb5Cf0C26cDCD726d39E6e') - c.set(2, '0xDCEceAF3fc5C0a63d195d69b1A90011B7B19650D') + c.set(0, '0x82A978B3f5962A5b0957d9ee9eEf472EE55B42F1', transact={}) + c.set(1, '0x7d577a597B2742b498Cb5Cf0C26cDCD726d39E6e', transact={}) + c.set(2, '0xDCEceAF3fc5C0a63d195d69b1A90011B7B19650D', transact={}) - assert c.ret(1) == c.iterate_return_second() == "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e" + assert c.ret(1) == c.iterate_return_second() == "0x7d577a597B2742b498Cb5Cf0C26cDCD726d39E6e" def test_basic_for_list_storage_decimal(get_contract_with_gas_estimation): @@ -193,13 +194,13 @@ def i_return(break_count: int128) -> decimal: c = get_contract_with_gas_estimation(code) - c.set(0, 0.0001) - c.set(1, 1.1) - c.set(2, 2.2) + c.set(0, Decimal('0.0001'), transact={}) + c.set(1, Decimal('1.1'), transact={}) + c.set(2, Decimal('2.2'), transact={}) - assert c.ret(2) == c.i_return(2) == 2.2 - assert c.ret(1) == c.i_return(1) == 1.1 - assert c.ret(0) == c.i_return(0) == 0.0001 + assert c.ret(2) == c.i_return(2) == Decimal('2.2') + assert c.ret(1) == c.i_return(1) == Decimal('1.1') + assert c.ret(0) == c.i_return(0) == Decimal('0.0001') def test_altering_list_within_for_loop_1(assert_compile_failed, get_contract_with_gas_estimation): diff --git a/tests/parser/features/iteration/test_range_in.py b/tests/parser/features/iteration/test_range_in.py index 05f641e9f2..34a3ae252f 100644 --- a/tests/parser/features/iteration/test_range_in.py +++ b/tests/parser/features/iteration/test_range_in.py @@ -74,7 +74,7 @@ def testin() -> bool: assert_compile_failed(lambda: get_contract_with_gas_estimation(code), TypeMismatchException) -def test_ownership(t, assert_tx_failed, get_contract_with_gas_estimation): +def test_ownership(w3, assert_tx_failed, get_contract_with_gas_estimation): code = """ owners: address[2] @@ -92,20 +92,20 @@ def set_owner(i: int128, new_owner: address): def is_owner() -> bool: return msg.sender in self.owners """ - + a1 = w3.eth.accounts[1] c = get_contract_with_gas_estimation(code) assert c.is_owner() is True # contract creator is owner. - assert c.is_owner(sender=t.k1) is False # no one else is. + assert c.is_owner(call={'from': a1}) is False # no one else is. # only an owner may set another owner. - assert_tx_failed(lambda: c.set_owner(1, t.a1, sender=t.k1)) + assert_tx_failed(lambda: c.set_owner(1, a1, call={'from': a1})) - c.set_owner(1, t.a1) - assert c.is_owner(sender=t.k1) is True + c.set_owner(1, a1, transact={}) + assert c.is_owner(call={'from': a1}) is True # Owner in place 0 can be replaced. - c.set_owner(0, t.a1) + c.set_owner(0, a1, transact={}) assert c.is_owner() is False diff --git a/tests/parser/features/test_assert.py b/tests/parser/features/test_assert.py index 6d20a2481e..d93bd7afb5 100644 --- a/tests/parser/features/test_assert.py +++ b/tests/parser/features/test_assert.py @@ -1,17 +1,17 @@ -import pytest -def test_assert_refund(t, get_contract_with_gas_estimation): +def test_assert_refund(w3, get_contract_with_gas_estimation, assert_tx_failed): code = """ @public def foo(): assert 1 == 2 """ c = get_contract_with_gas_estimation(code) - pre_balance = t.s.head_state.get_balance(t.a0) - with pytest.raises(t.TransactionFailed): - c.foo(startgas=10**6, gasprice=10) - post_balance = t.s.head_state.get_balance(t.a0) + a0 = w3.eth.accounts[0] + pre_balance = w3.eth.getBalance(a0) + # assert_tx_failed(lambda: c.foo(transact={'from': a0, 'gas': 10**6, 'gasPrice': 10})) + assert_tx_failed(lambda: c.foo()) + post_balance = w3.eth.getBalance(a0) # Checks for gas refund from revert # 10**5 is added to account for gas used before the transactions fails assert pre_balance < post_balance + 10**5 diff --git a/tests/parser/features/test_bytes_map_keys.py b/tests/parser/features/test_bytes_map_keys.py index 24a51278ea..118508806a 100644 --- a/tests/parser/features/test_bytes_map_keys.py +++ b/tests/parser/features/test_bytes_map_keys.py @@ -2,7 +2,7 @@ from vyper.exceptions import TypeMismatchException -def test_basic_bytes_keys(get_contract): +def test_basic_bytes_keys(w3, get_contract): code = """ mapped_bytes: int128[bytes[5]] @@ -17,9 +17,9 @@ def get(k: bytes[5]) -> int128: c = get_contract(code) - c.set("test", 54321) + c.set(b"test", 54321, transact={}) - assert c.get("test") == 54321 + assert c.get(b"test") == 54321 def test_basic_bytes_literal_key(get_contract): @@ -37,9 +37,9 @@ def get(k: bytes[5]) -> int128: c = get_contract(code) - c.set(54321) + c.set(54321, transact={}) - assert c.get("test") == 54321 + assert c.get(b"test") == 54321 def test_basic_long_bytes_as_keys(get_contract): @@ -57,29 +57,9 @@ def get(k: bytes[34]) -> int128: c = get_contract(code) - c.set("a" * 34, 6789) + c.set(b"a" * 34, 6789, transact={'gas': 10**6}) - assert c.get("a" * 34) == 6789 - - -def test_basic_very_long_bytes_as_keys(get_contract): - code = """ -mapped_bytes: int128[bytes[4096]] - -@public -def set(k: bytes[4096], v: int128): - self.mapped_bytes[k] = v - -@public -def get(k: bytes[4096]) -> int128: - return self.mapped_bytes[k] - """ - - c = get_contract(code) - - c.set("test" * 1024, 6789) - - assert c.get("test" * 1024) == 6789 + assert c.get(b"a" * 34) == 6789 def test_mismatched_byte_length(get_contract): diff --git a/tests/parser/features/test_clampers.py b/tests/parser/features/test_clampers.py index 587d73d3ce..7a73f15f0b 100644 --- a/tests/parser/features/test_clampers.py +++ b/tests/parser/features/test_clampers.py @@ -1,18 +1,13 @@ -def test_clamper_test_code(t, get_contract_with_gas_estimation): +def test_clamper_test_code(assert_tx_failed, get_contract_with_gas_estimation): clamper_test_code = """ @public def foo(s: bytes[3]) -> bytes[3]: return s """ - c = get_contract_with_gas_estimation(clamper_test_code, value=1) + c = get_contract_with_gas_estimation(clamper_test_code) assert c.foo(b"ca") == b"ca" assert c.foo(b"cat") == b"cat" - try: - c.foo(b"cate") - success = True - except t.TransactionFailed: - success = False - assert not success + assert_tx_failed(lambda: c.foo(b"cate")) print("Passed bytearray clamping test") diff --git a/tests/parser/features/test_constructor.py b/tests/parser/features/test_constructor.py index 94dfb267a5..39674d7c02 100644 --- a/tests/parser/features/test_constructor.py +++ b/tests/parser/features/test_constructor.py @@ -1,4 +1,7 @@ -from ethereum.abi import ValueOutOfBounds +import pytest +from web3.exceptions import ( + ValidationError +) def test_init_argument_test(get_contract_with_gas_estimation): @@ -14,7 +17,7 @@ def returnMoose() -> int128: return self.moose """ - c = get_contract_with_gas_estimation(init_argument_test, args=[5]) + c = get_contract_with_gas_estimation(init_argument_test, *[5]) assert c.returnMoose() == 5 print('Passed init argument test') @@ -31,7 +34,7 @@ def __init__(x: int128): def get_twox() -> int128: return self.twox """ - c = get_contract_with_gas_estimation(constructor_advanced_code, args=[5]) + c = get_contract_with_gas_estimation(constructor_advanced_code, *[5]) assert c.get_twox() == 10 @@ -47,7 +50,7 @@ def __init__(x: int128[2], y: bytes[3], z: int128): def get_comb() -> int128: return self.comb """ - c = get_contract_with_gas_estimation(constructor_advanced_code2, args=[[5, 7], "dog", 8]) + c = get_contract_with_gas_estimation(constructor_advanced_code2, *[[5, 7], b"dog", 8]) assert c.get_comb() == 5738 print("Passed advanced init argument tests") @@ -62,15 +65,12 @@ def foo(x: int128) -> int128: c = get_contract_with_gas_estimation(large_input_code) c.foo(1274124) c.foo(2**120) - try: + + with pytest.raises(ValidationError): c.foo(2**130) - success = True - except ValueOutOfBounds: - success = False - assert not success -def test_large_input_code_2(t, get_contract_with_gas_estimation): +def test_large_input_code_2(w3, get_contract_with_gas_estimation): large_input_code_2 = """ @public def __init__(x: int128): @@ -81,12 +81,9 @@ def foo() -> int128: return 5 """ - get_contract_with_gas_estimation(large_input_code_2, args=[17], sender=t.k0, value=0) - try: - get_contract_with_gas_estimation(large_input_code_2, args=[2**130], sender=t.k0, value=0) - success = True - except ValueOutOfBounds: - success = False - assert not success + get_contract_with_gas_estimation(large_input_code_2, *[17]) + + with pytest.raises(TypeError): + get_contract_with_gas_estimation(large_input_code_2, *[2**130]) print('Passed invalid input tests') diff --git a/tests/parser/features/test_gas.py b/tests/parser/features/test_gas.py index 58b457280e..73c1113162 100644 --- a/tests/parser/features/test_gas.py +++ b/tests/parser/features/test_gas.py @@ -11,8 +11,9 @@ def foo() -> int128: c = get_contract_with_gas_estimation(gas_call) - assert c.foo(startgas=50000) < 50000 - assert c.foo(startgas=50000) > 25000 + assert c.foo(call={"gas": 50000}) < 50000 + assert c.foo(call={"gas": 50000}) > 25000 + print('Passed gas test') @@ -26,5 +27,5 @@ def __init__(): """ parser_utils.LLLnode.repr_show_gas = True out = parse_to_lll(code) - assert str(out)[:30] == '\x1b[94m{\x1b[0m20303\x1b[94m} \x1b[0m[seq' + assert str(out)[:30] == '\x1b[94m{\x1b[0m35303\x1b[94m} \x1b[0m[seq' parser_utils.LLLnode.repr_show_gas = False diff --git a/tests/parser/features/test_internal_call.py b/tests/parser/features/test_internal_call.py index 7a4f7091ad..d185fbb39b 100644 --- a/tests/parser/features/test_internal_call.py +++ b/tests/parser/features/test_internal_call.py @@ -1,3 +1,4 @@ +from decimal import Decimal from vyper.exceptions import StructureException @@ -18,7 +19,7 @@ def bar() -> int128: print("Passed no-argument self-call test") -def test_selfcall_code_2(get_contract_with_gas_estimation, utils): +def test_selfcall_code_2(get_contract_with_gas_estimation, keccak): selfcall_code_2 = """ @public def double(x: int128) -> int128: @@ -39,12 +40,12 @@ def return_hash_of_rzpadded_cow() -> bytes32: c = get_contract_with_gas_estimation(selfcall_code_2) assert c.returnten() == 10 - assert c.return_hash_of_rzpadded_cow() == utils.sha3(b'cow' + b'\x00' * 29) + assert c.return_hash_of_rzpadded_cow() == keccak(b'cow' + b'\x00' * 29) print("Passed single fixed-size argument self-call test") -def test_selfcall_code_3(get_contract_with_gas_estimation, utils): +def test_selfcall_code_3(get_contract_with_gas_estimation, keccak): selfcall_code_3 = """ @public def _hashy2(x: bytes[100]) -> bytes32: @@ -64,7 +65,7 @@ def returnten() -> int128: """ c = get_contract_with_gas_estimation(selfcall_code_3) - assert c.return_hash_of_cow_x_30() == utils.sha3(b'cow' * 30) + assert c.return_hash_of_cow_x_30() == keccak(b'cow' * 30) assert c.returnten() == 10 print("Passed single variable-size argument self-call test") @@ -191,7 +192,7 @@ def bar3() -> int128: c = get_contract_with_gas_estimation(code) assert c.bar() == 0 - assert c.foo1() == 0 + assert c.foo1([0, 0]) == 0 assert c.bar2() == 55 assert c.bar3() == 66 @@ -222,7 +223,7 @@ def bar1() -> int128: """ c = get_contract_with_gas_estimation(code) - c.set() + c.set(transact={}) assert c.bar0() == 88 assert c.bar1() == 99 @@ -288,9 +289,9 @@ def bar6() -> int128: c = get_contract_with_gas_estimation(code) assert c.bar() == 0 - assert c.foo1() == 0 + assert c.foo1([0, 0], Decimal('0')) == 0 assert c.bar2() == 55 - assert c.bar3() == 1.33 + assert c.bar3() == Decimal('1.33') assert c.bar4() == 77 assert c.bar5() == 88 @@ -315,7 +316,7 @@ def bar() -> (int128, decimal): return self.fooz(x, y, z, a), self.fooa(x, y, z, a) """ c = get_contract_with_gas_estimation(code) - assert c.bar() == [66, 66.77] + assert c.bar() == [66, Decimal('66.77')] def test_multi_mixed_arg_list_bytes_call(get_contract_with_gas_estimation): @@ -342,7 +343,7 @@ def bar() -> (bytes[11], decimal, int128): return self.fooz(x, y, z, a), self.fooa(x, y, z, a), self.foox(x, y, z, a) """ c = get_contract_with_gas_estimation(code) - assert c.bar() == [b"hello world", 66.77, 44] + assert c.bar() == [b"hello world", Decimal('66.77'), 44] def test_selfcall_with_wrong_arg_count_fails(get_contract_with_gas_estimation, assert_tx_failed): diff --git a/tests/parser/features/test_logging.py b/tests/parser/features/test_logging.py index e7750972ae..c2015d31e3 100644 --- a/tests/parser/features/test_logging.py +++ b/tests/parser/features/test_logging.py @@ -1,7 +1,9 @@ +from decimal import Decimal + from vyper.exceptions import VariableDeclarationException, TypeMismatchException, StructureException -def test_empy_event_logging(get_contract_with_gas_estimation, utils, chain): +def test_empy_event_logging(w3, tester, keccak, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({}) @@ -11,20 +13,20 @@ def foo(): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog()', 'utf-8'))) + tx_hash = c.foo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + event_id = keccak(bytes('MyLog()', 'utf-8')) + # Event id is always the first topic - assert logs.topics[0] == event_id - # Event id is calculated correctly - assert c.translator.event_data[event_id] + assert receipt['logs'][0]['topics'][0] == event_id.hex() # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': [], 'name': 'MyLog', 'names': [], 'indexed': [], 'anonymous': False} + assert c._classic_contract.abi[0] == {'name': 'MyLog', 'inputs': [], 'anonymous': False, 'type': 'event'} # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == {'_event_type': b'MyLog'} + assert hasattr(c._classic_contract.events, 'MyLog') -def test_event_logging_with_topics(get_contract_with_gas_estimation, chain, utils): +def test_event_logging_with_topics(w3, tester, keccak, get_logs, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(bytes[3])}) @@ -34,20 +36,21 @@ def foo(): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(bytes3)', 'utf-8'))) + tx_hash = c.foo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + event_id = keccak(bytes('MyLog(bytes3)', 'utf-8')) + # Event id is always the first topic - assert logs.topics[0] == event_id - # Event id is calculated correctly - assert c.translator.event_data[event_id] + assert receipt['logs'][0]['topics'][0] == event_id.hex() # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': ['bytes3'], 'name': 'MyLog', 'names': ['arg1'], 'indexed': [True], 'anonymous': False} + assert c._classic_contract.abi[0] == {'name': 'MyLog', 'inputs': [{'type': 'bytes3', 'name': 'arg1', 'indexed': True}], 'anonymous': False, 'type': 'event'} # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == {'arg1': b'bar', '_event_type': b'MyLog'} + logs = get_logs(tx_hash, c, 'MyLog') + assert logs[0].event == 'MyLog' + assert logs[0].args.arg1 == b'bar' -def test_event_logging_with_multiple_topics(get_contract_with_gas_estimation, chain, utils): +def test_event_logging_with_multiple_topics(w3, tester, keccak, get_logs, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(bytes[3]), arg2: indexed(bytes[4]), arg3: indexed(address)}) @@ -57,26 +60,31 @@ def foo(): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(bytes3,bytes4,address)', 'utf-8'))) + tx_hash = c.foo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + event_id = keccak(bytes('MyLog(bytes3,bytes4,address)', 'utf-8')) # Event id is always the first topic - assert logs.topics[0] == event_id - # Event id is calculated correctly - assert c.translator.event_data[event_id] + assert receipt['logs'][0]['topics'][0] == event_id.hex() # Event abi is created correctly - assert c.translator.event_data[event_id] == ( - {'types': ['bytes3', 'bytes4', 'address'], + assert c._classic_contract.abi[0] == { 'name': 'MyLog', - 'names': ['arg1', 'arg2', 'arg3'], - 'indexed': [True, True, True], - 'anonymous': False} - ) + 'inputs': [ + {'type': 'bytes3', 'name': 'arg1', 'indexed': True}, + {'type': 'bytes4', 'name': 'arg2', 'indexed': True}, + {'type': 'address', 'name': 'arg3', 'indexed': True}], + 'anonymous': False, + 'type': 'event' + } # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == {'arg1': b'bar', 'arg2': b'home', 'arg3': '0x' + c.address.hex(), '_event_type': b'MyLog'} + logs = get_logs(tx_hash, c, 'MyLog') + assert logs[0].event == 'MyLog' + assert logs[0].args.arg1 == b'bar' + assert logs[0].args.arg2 == b'home' + assert logs[0].args.arg3 == c._classic_contract.address -def test_event_logging_with_multiple_topics_var_and_store(get_contract_with_gas_estimation, chain, get_logs): +def test_event_logging_with_multiple_topics_var_and_store(tester, get_contract_with_gas_estimation, get_logs): code = """ MyLog: event({arg1: indexed(bytes[3]), arg2: indexed(bytes[4]), arg3: indexed(address), arg4: bytes[10]}) b: bytes[10] @@ -89,22 +97,18 @@ def foo(arg1: bytes[3]): """ c = get_contract_with_gas_estimation(code) - c.foo('hel') + tx_hash = c.foo(b'hel', transact={}) # Event is decoded correctly - receipt = chain.head_state.receipts[-1] - log = get_logs(receipt, c)[0] - - assert log == { - 'arg1': b'hel', - 'arg2': b'home', - 'arg3': '0x' + c.address.hex(), - 'arg4': b'hellothere', - '_event_type': b'MyLog' - } + log = get_logs(tx_hash, c, 'MyLog')[0] + assert log.args.arg1 == b'hel' + assert log.args.arg2 == b'home' + assert log.args.arg3 == c.address + assert log.args.arg4 == b'hellothere' -def test_logging_the_same_event_multiple_times_with_topics(get_contract_with_gas_estimation, chain, utils): + +def test_logging_the_same_event_multiple_times_with_topics(w3, tester, keccak, get_logs, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(int128), arg2: indexed(address)}) @@ -120,18 +124,31 @@ def bar(): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - c.bar() - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(int128,address)', 'utf-8'))) + tx_hash1 = c.foo(transact={}) + tx_hash2 = c.bar(transact={}) + receipt1 = tester.get_transaction_receipt(tx_hash1.hex()) + receipt2 = tester.get_transaction_receipt(tx_hash2.hex()) + + event_id = keccak(bytes('MyLog(int128,address)', 'utf-8')) # Event id is always the first topic - assert logs.topics[0] == event_id - # Event id is calculated correctly - assert c.translator.event_data[event_id] + assert receipt1['logs'][0]['topics'][0] == event_id.hex() + assert receipt2['logs'][0]['topics'][0] == event_id.hex() # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': ['int128', 'address'], 'name': 'MyLog', 'names': ['arg1', 'arg2'], 'indexed': [True, True], 'anonymous': False} + assert c._classic_contract.abi[0] == { + 'name': 'MyLog', + 'inputs': [ + {'type': 'int128', 'name': 'arg1', 'indexed': True}, + {'type': 'address', 'name': 'arg2', 'indexed': True}], + 'anonymous': False, + 'type': 'event' + } + # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == {'_event_type': b'MyLog', 'arg1': 1, 'arg2': '0x' + c.address.hex()} + logs = get_logs(tx_hash1, c, 'MyLog') + assert logs[0].args.arg1 == 1 + assert logs[0].args.arg2 == c.address + assert logs[1].args.arg1 == 1 + assert logs[1].args.arg2 == c.address def test_event_logging_cannot_have_more_than_three_topics(assert_tx_failed, get_contract_with_gas_estimation): @@ -142,7 +159,7 @@ def test_event_logging_cannot_have_more_than_three_topics(assert_tx_failed, get_ assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), VariableDeclarationException) -def test_event_logging_with_data(get_contract_with_gas_estimation, chain, utils): +def test_event_logging_with_data(w3, tester, keccak, get_logs, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: int128}) @@ -152,20 +169,21 @@ def foo(): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(int128)', 'utf-8'))) + tx_hash = c.foo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + event_id = keccak(bytes('MyLog(int128)', 'utf-8')) # Event id is always the first topic - assert logs.topics[0] == event_id - # Event id is calculated correctly - assert c.translator.event_data[event_id] + assert receipt['logs'][0]['topics'][0] == event_id.hex() # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': ['int128'], 'name': 'MyLog', 'names': ['arg1'], 'indexed': [False], 'anonymous': False} + assert c._classic_contract.abi[0] == {'name': 'MyLog', 'inputs': [{'type': 'int128', 'name': 'arg1', 'indexed': False}], 'anonymous': False, 'type': 'event'} + # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == {'arg1': 123, '_event_type': b'MyLog'} + logs = get_logs(tx_hash, c, 'MyLog') + assert logs[0].args.arg1 == 123 -def test_event_logging_with_units(get_contract_with_gas_estimation, chain, utils): +def test_event_logging_with_units(get_contract_with_gas_estimation): code = """ MyLog: event({arg1: indexed(int128(wei)), arg2: int128(wei)}) @@ -176,7 +194,7 @@ def foo(): get_contract_with_gas_estimation(code) -def test_event_logging_with_fixed_array_data(get_contract_with_gas_estimation, chain, utils): +def test_event_logging_with_fixed_array_data(w3, tester, keccak, get_logs, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: int128[2], arg2: timestamp[3], arg3: int128[2][2]}) @@ -187,21 +205,34 @@ def foo(): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(int128[2],int128[3],int128[2][2])', 'utf-8'))) - # # Event id is always the first topic - assert logs.topics[0] == event_id - # # Event id is calculated correctly - assert c.translator.event_data[event_id] - # # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': ['int128[2]', 'int128[3]', 'int128[2][2]'], 'name': 'MyLog', 'names': ['arg1', 'arg2', 'arg3'], 'indexed': [False, False, False], 'anonymous': False} - # # Event is decoded correctly - timestamp = chain.head_state.timestamp - assert c.translator.decode_event(logs.topics, logs.data) == {'arg1': [1, 2], 'arg2': [timestamp, timestamp + 1, timestamp + 2], 'arg3': [[1, 2], [1, 2]], '_event_type': b'MyLog'} - - -def test_logging_with_input_bytes_1(bytes_helper, get_contract_with_gas_estimation, chain, utils): + tx_hash = c.foo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + event_id = keccak(bytes('MyLog(int128[2],int128[3],int128[2][2])', 'utf-8')) + # Event id is always the first topic + assert receipt['logs'][0]['topics'][0] == event_id.hex() + # Event abi is created correctly + + assert c._classic_contract.abi[0] == { + 'name': 'MyLog', + 'inputs': [ + {'type': 'int128[2]', 'name': 'arg1', 'indexed': False}, + {'type': 'int128[3]', 'name': 'arg2', 'indexed': False}, + {'type': 'int128[2][2]', 'name': 'arg3', 'indexed': False}], + 'anonymous': False, + 'type': 'event' + } + + # Event is decoded correctly + timestamp = w3.eth.getBlock(w3.eth.blockNumber).timestamp + logs = get_logs(tx_hash, c, 'MyLog') + + assert logs[0].args.arg1 == [1, 2] + assert logs[0].args.arg2 == [timestamp, timestamp + 1, timestamp + 2] + assert logs[0].args.arg3 == [[1, 2], [1, 2]] + + +def test_logging_with_input_bytes_1(w3, tester, keccak, get_logs, bytes_helper, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(bytes[4]), arg2: indexed(bytes[29]), arg3: bytes[31]}) @@ -211,25 +242,30 @@ def foo(arg1: bytes[29], arg2: bytes[31]): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo('bar', 'foo') - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(bytes4,bytes29,bytes)', 'utf-8'))) - # # Event id is always the first topic - assert logs.topics[0] == event_id - # # Event id is calculated correctly - assert c.translator.event_data[event_id] - # # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': ['bytes4', 'bytes29', 'bytes'], 'name': 'MyLog', 'names': ['arg1', 'arg2', 'arg3'], 'indexed': [True, True, False], 'anonymous': False} - # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == { - 'arg1': b'bar\x00', - 'arg2': bytes_helper('bar', 29), - 'arg3': b'foo', - '_event_type': b'MyLog' + tx_hash = c.foo(b'bar', b'foo', transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + event_id = keccak(bytes('MyLog(bytes4,bytes29,bytes)', 'utf-8')) + # Event id is always the first topic + assert receipt['logs'][0]['topics'][0] == event_id.hex() + # Event abi is created correctly + assert c._classic_contract.abi[0] == { + 'name': 'MyLog', + 'inputs': [ + {'type': 'bytes4', 'name': 'arg1', 'indexed': True}, + {'type': 'bytes29', 'name': 'arg2', 'indexed': True}, + {'type': 'bytes', 'name': 'arg3', 'indexed': False}], + 'anonymous': False, 'type': 'event' } + # Event is decoded correctly + logs = get_logs(tx_hash, c, 'MyLog') + + assert logs[0].args.arg1 == b'bar\x00' + assert logs[0].args.arg2 == bytes_helper('bar', 29) + assert logs[0].args.arg3 == b'foo' -def test_event_logging_with_bytes_input_2(t, bytes_helper, get_contract_with_gas_estimation, chain, utils): +def test_event_logging_with_bytes_input_2(w3, tester, keccak, get_logs, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: bytes[20]}) @@ -239,20 +275,20 @@ def foo(_arg1: bytes[20]): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo('hello') - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(bytes)', 'utf-8'))) + tx_hash = c.foo(b'hello', transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + event_id = keccak(bytes('MyLog(bytes)', 'utf-8')) # Event id is always the first topic - assert logs.topics[0] == event_id - # Event id is calculated correctly - assert c.translator.event_data[event_id] + assert receipt['logs'][0]['topics'][0] == event_id.hex() # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': ['bytes'], 'name': 'MyLog', 'names': ['arg1'], 'indexed': [False], 'anonymous': False} + assert c._classic_contract.abi[0] == {'anonymous': False, 'inputs': [{'indexed': False, 'name': 'arg1', 'type': 'bytes'}], 'name': 'MyLog', 'type': 'event'} # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == {'arg1': b'hello', '_event_type': b'MyLog'} + logs = get_logs(tx_hash, c, 'MyLog') + assert logs[0].args.arg1 == b'hello' -def test_event_logging_with_bytes_input_3(get_contract, chain, utils): +def test_event_logging_with_bytes_input_3(w3, tester, keccak, get_logs, get_contract): loggy_code = """ MyLog: event({arg1: bytes[5]}) @@ -262,20 +298,20 @@ def foo(_arg1: bytes[5]): """ c = get_contract(loggy_code) - c.foo('hello') - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(bytes)', 'utf-8'))) + tx_hash = c.foo(b'hello', transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + event_id = keccak(bytes('MyLog(bytes)', 'utf-8')) # Event id is always the first topic - assert logs.topics[0] == event_id - # Event id is calculated correctly - assert c.translator.event_data[event_id] + assert receipt['logs'][0]['topics'][0] == event_id.hex() # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': ['bytes'], 'name': 'MyLog', 'names': ['arg1'], 'indexed': [False], 'anonymous': False} + assert c._classic_contract.abi[0] == {'anonymous': False, 'inputs': [{'indexed': False, 'name': 'arg1', 'type': 'bytes'}], 'name': 'MyLog', 'type': 'event'} # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == {'arg1': b'hello', '_event_type': b'MyLog'} + logs = get_logs(tx_hash, c, 'MyLog') + assert logs[0].args.arg1 == b'hello' -def test_event_logging_with_data_with_different_types(get_contract_with_gas_estimation, chain, utils): +def test_event_logging_with_data_with_different_types(w3, tester, keccak, get_logs, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: int128, arg2: bytes[4], arg3: bytes[3], arg4: address, arg5: address, arg6: timestamp}) @@ -285,20 +321,38 @@ def foo(): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(int128,bytes,bytes,address,address,int128)', 'utf-8'))) + tx_hash = c.foo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + event_id = keccak(bytes('MyLog(int128,bytes,bytes,address,address,int128)', 'utf-8')) # Event id is always the first topic - assert logs.topics[0] == event_id - # Event id is calculated correctly - assert c.translator.event_data[event_id] + assert receipt['logs'][0]['topics'][0] == event_id.hex() # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': ['int128', 'bytes', 'bytes', 'address', 'address', 'int128'], 'name': 'MyLog', 'names': ['arg1', 'arg2', 'arg3', 'arg4', 'arg5', 'arg6'], 'indexed': [False, False, False, False, False, False], 'anonymous': False} - # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == {'arg1': 123, 'arg2': b'home', 'arg3': b'bar', 'arg4': '0xc305c901078781c232a2a521c2af7980f8385ee9', 'arg5': '0x' + c.address.hex(), 'arg6': chain.head_state.timestamp, '_event_type': b'MyLog'} - + assert c._classic_contract.abi[0] == { + 'name': 'MyLog', + 'inputs': [{'type': 'int128', 'name': 'arg1', 'indexed': False}, + {'type': 'bytes', 'name': 'arg2', 'indexed': False}, + {'type': 'bytes', 'name': 'arg3', 'indexed': False}, + {'type': 'address', 'name': 'arg4', 'indexed': False}, + {'type': 'address', 'name': 'arg5', 'indexed': False}, + {'type': 'int128', 'name': 'arg6', 'indexed': False}], + 'anonymous': False, + 'type': 'event' + } -def test_event_logging_with_topics_and_data_1(get_contract_with_gas_estimation, chain, utils): + # Event is decoded correctly + timestamp = w3.eth.getBlock(w3.eth.blockNumber).timestamp + logs = get_logs(tx_hash, c, 'MyLog') + args = logs[0].args + assert args.arg1 == 123 + assert args.arg2 == b'home' + assert args.arg3 == b'bar' + assert args.arg4 == '0xc305c901078781C232A2a521C2aF7980f8385ee9' + assert args.arg5 == c.address + assert args.arg6 == timestamp + + +def test_event_logging_with_topics_and_data_1(w3, tester, keccak, get_logs, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(int128), arg2: bytes[3]}) @@ -308,20 +362,26 @@ def foo(): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - logs = chain.head_state.receipts[-1].logs[-1] - event_id = utils.bytes_to_int(utils.sha3(bytes('MyLog(int128,bytes)', 'utf-8'))) + tx_hash = c.foo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + event_id = keccak(bytes('MyLog(int128,bytes)', 'utf-8')) # Event id is always the first topic - assert logs.topics[0] == event_id - # Event id is calculated correctly - assert c.translator.event_data[event_id] + assert receipt['logs'][0]['topics'][0] == event_id.hex() # Event abi is created correctly - assert c.translator.event_data[event_id] == {'types': ['int128', 'bytes'], 'name': 'MyLog', 'names': ['arg1', 'arg2'], 'indexed': [True, False], 'anonymous': False} + assert c._classic_contract.abi[0] == { + 'anonymous': False, + 'inputs': [ + {'indexed': True, 'name': 'arg1', 'type': 'int128'}, + {'indexed': False, 'name': 'arg2', 'type': 'bytes'}], 'name': 'MyLog', 'type': 'event'} # Event is decoded correctly - assert c.translator.decode_event(logs.topics, logs.data) == {'arg1': 1, 'arg2': b'bar', '_event_type': b'MyLog'} + logs = get_logs(tx_hash, c, 'MyLog') + args = logs[0].args + assert args.arg1 == 1 + assert args.arg2 == b'bar' -def test_event_logging_with_multiple_logs_topics_and_data(get_contract_with_gas_estimation, chain, utils): +def test_event_logging_with_multiple_logs_topics_and_data(w3, tester, keccak, get_logs, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(int128), arg2: bytes[3]}) YourLog: event({arg1: indexed(address), arg2: bytes[5]}) @@ -333,26 +393,33 @@ def foo(): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - logs1 = chain.head_state.receipts[-1].logs[-2] - logs2 = chain.head_state.receipts[-1].logs[-1] - event_id1 = utils.bytes_to_int(utils.sha3(bytes('MyLog(int128,bytes)', 'utf-8'))) - event_id2 = utils.bytes_to_int(utils.sha3(bytes('YourLog(address,bytes)', 'utf-8'))) + tx_hash = c.foo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + + logs1 = receipt['logs'][0] + logs2 = receipt['logs'][1] + event_id1 = keccak(bytes('MyLog(int128,bytes)', 'utf-8')) + event_id2 = keccak(bytes('YourLog(address,bytes)', 'utf-8')) + # Event id is always the first topic - assert logs1.topics[0] == event_id1 - assert logs2.topics[0] == event_id2 - # Event ids are calculated correctly - assert c.translator.event_data[event_id1] - assert c.translator.event_data[event_id2] + assert logs1['topics'][0] == event_id1.hex() + assert logs2['topics'][0] == event_id2.hex() # Event abi is created correctly - assert c.translator.event_data[event_id1] == {'types': ['int128', 'bytes'], 'name': 'MyLog', 'names': ['arg1', 'arg2'], 'indexed': [True, False], 'anonymous': False} - assert c.translator.event_data[event_id2] == {'types': ['address', 'bytes'], 'name': 'YourLog', 'names': ['arg1', 'arg2'], 'indexed': [True, False], 'anonymous': False} + assert c._classic_contract.abi[0] == {'name': 'MyLog', 'inputs': [{'type': 'int128', 'name': 'arg1', 'indexed': True}, {'type': 'bytes', 'name': 'arg2', 'indexed': False}], 'anonymous': False, 'type': 'event'} + assert c._classic_contract.abi[1] == {'name': 'YourLog', 'inputs': [{'type': 'address', 'name': 'arg1', 'indexed': True}, {'type': 'bytes', 'name': 'arg2', 'indexed': False}], 'anonymous': False, 'type': 'event'} + # Event is decoded correctly - assert c.translator.decode_event(logs1.topics, logs1.data) == {'arg1': 1, 'arg2': b'bar', '_event_type': b'MyLog'} - assert c.translator.decode_event(logs2.topics, logs2.data) == {'arg1': '0x' + c.address.hex(), 'arg2': b'house', '_event_type': b'YourLog'} + logs = get_logs(tx_hash, c, 'MyLog') + args = logs[0].args + assert args.arg1 == 1 + assert args.arg2 == b'bar' + logs = get_logs(tx_hash, c, 'YourLog') + args = logs[0].args + assert args.arg1 == c.address + assert args.arg2 == b'house' -def test_fails_when_input_is_the_wrong_type(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_fails_when_input_is_the_wrong_type(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(int128)}) @@ -360,11 +427,11 @@ def test_fails_when_input_is_the_wrong_type(t, assert_tx_failed, get_contract_wi def foo_(): log.MyLog('yo') """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), TypeMismatchException) -def test_fails_when_topic_is_the_wrong_size(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_fails_when_topic_is_the_wrong_size(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(bytes[3])}) @@ -372,11 +439,11 @@ def test_fails_when_topic_is_the_wrong_size(t, assert_tx_failed, get_contract_wi def foo(): log.MyLog('bars') """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), TypeMismatchException) -def test_fails_when_input_topic_is_the_wrong_size(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_fails_when_input_topic_is_the_wrong_size(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(bytes[3])}) @@ -384,11 +451,11 @@ def test_fails_when_input_topic_is_the_wrong_size(t, assert_tx_failed, get_contr def foo(arg1: bytes[4]): log.MyLog(arg1) """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), TypeMismatchException) -def test_fails_when_data_is_the_wrong_size(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_fails_when_data_is_the_wrong_size(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: bytes[3]}) @@ -396,11 +463,11 @@ def test_fails_when_data_is_the_wrong_size(t, assert_tx_failed, get_contract_wit def foo(): log.MyLog('bars') """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), TypeMismatchException) -def test_fails_when_input_data_is_the_wrong_size(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_fails_when_input_data_is_the_wrong_size(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: bytes[3]}) @@ -408,11 +475,11 @@ def test_fails_when_input_data_is_the_wrong_size(t, assert_tx_failed, get_contra def foo(arg1: bytes[4]): log.MyLog(arg1) """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), TypeMismatchException) -def test_fails_when_topic_is_over_32_bytes(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_fails_when_topic_is_over_32_bytes(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(bytes[100])}) @@ -420,22 +487,22 @@ def test_fails_when_topic_is_over_32_bytes(t, assert_tx_failed, get_contract_wit def foo(): pass """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), VariableDeclarationException) -def test_logging_fails_with_over_three_topics(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_logging_fails_with_over_three_topics(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(int128), arg2: indexed(int128), arg3: indexed(int128), arg4: indexed(int128)}) @public def __init__(): log.MyLog(1, 2, 3, 4) """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), VariableDeclarationException) -def test_logging_fails_with_duplicate_log_names(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_logging_fails_with_duplicate_log_names(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({}) MyLog: event({}) @@ -444,22 +511,22 @@ def test_logging_fails_with_duplicate_log_names(t, assert_tx_failed, get_contrac def foo(): log.MyLog() """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), VariableDeclarationException) -def test_logging_fails_with_when_log_is_undeclared(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_logging_fails_with_when_log_is_undeclared(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ @public def foo(): log.MyLog() """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), VariableDeclarationException) -def test_logging_fails_with_topic_type_mismatch(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_logging_fails_with_topic_type_mismatch(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: indexed(int128)}) @@ -467,11 +534,11 @@ def test_logging_fails_with_topic_type_mismatch(t, assert_tx_failed, get_contrac def foo(): log.MyLog(self) """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), TypeMismatchException) -def test_logging_fails_with_data_type_mismatch(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_logging_fails_with_data_type_mismatch(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: bytes[3]}) @@ -479,20 +546,20 @@ def test_logging_fails_with_data_type_mismatch(t, assert_tx_failed, get_contract def foo(): log.MyLog(self) """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), TypeMismatchException) -def test_logging_fails_after_a_global_declaration(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_logging_fails_after_a_global_declaration(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ age: int128 MyLog: event({arg1: bytes[3]}) """ - t.s = chain + assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), StructureException) -def test_logging_fails_after_a_function_declaration(t, assert_tx_failed, get_contract_with_gas_estimation): +def test_logging_fails_after_a_function_declaration(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ @public def foo(): @@ -503,7 +570,7 @@ def foo(): assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), StructureException) -def test_logging_fails_when_number_of_arguments_is_greater_than_declaration(t, assert_tx_failed, get_contract_with_gas_estimation): +def test_logging_fails_when_number_of_arguments_is_greater_than_declaration(assert_tx_failed, get_contract_with_gas_estimation): loggy_code = """ MyLog: event({arg1: int128}) @@ -525,7 +592,7 @@ def foo(): assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), VariableDeclarationException) -def test_loggy_code(get_contract_with_gas_estimation, chain): +def test_loggy_code(w3, tester, get_contract_with_gas_estimation): loggy_code = """ s: bytes[100] @@ -548,20 +615,33 @@ def ioo(inp: bytes[100]): """ c = get_contract_with_gas_estimation(loggy_code) - c.foo() - assert chain.head_state.receipts[-1].logs[0].data == b'moo' - c.goo() - assert chain.head_state.receipts[-1].logs[0].data == b'moo2' - assert tuple(chain.head_state.receipts[-1].logs[0].topics) == (0x1234567812345678123456781234567812345678123456781234567812345678,) - c.hoo() - assert chain.head_state.receipts[-1].logs[0].data == b'moo3' - c.ioo(b"moo4") - assert chain.head_state.receipts[-1].logs[0].data == b'moo4' + + tx_hash = c.foo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + logs = receipt['logs'] + + assert w3.toText(logs[0]['data']) == 'moo' + tx_hash = c.goo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + logs = receipt['logs'] + assert w3.toText(logs[0]['data']) == 'moo2' + assert logs[0]['topics'][0] == '0x1234567812345678123456781234567812345678123456781234567812345678' + + tx_hash = c.hoo(transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + logs = receipt['logs'] + assert w3.toText(logs[0]['data']) == 'moo3' + + tx_hash = c.ioo(b"moo4", transact={}) + receipt = tester.get_transaction_receipt(tx_hash.hex()) + logs = receipt['logs'] + assert w3.toText(logs[0]['data']) == 'moo4' + print("Passed raw log tests") -def test_variable_list_packing(t, get_last_log, get_contract_with_gas_estimation, chain): - t.s = chain +def test_variable_list_packing(get_logs, get_contract_with_gas_estimation): + code = """ Bar: event({_value: int128[4]}) @@ -572,12 +652,13 @@ def foo(): """ c = get_contract_with_gas_estimation(code) - c.foo() - assert get_last_log(t, c)["_value"] == [1, 2, 3, 4] + tx_hash = c.foo(transact={}) + logs = get_logs(tx_hash, c, 'Bar') + assert logs[0].args._value == [1, 2, 3, 4] -def test_literal_list_packing(t, get_last_log, get_contract_with_gas_estimation, chain): - t.s = chain +def test_literal_list_packing(get_logs, get_contract_with_gas_estimation): + code = """ Bar: event({_value: int128[4]}) @@ -587,12 +668,13 @@ def foo(): """ c = get_contract_with_gas_estimation(code) - c.foo() - assert get_last_log(t, c)["_value"] == [1, 2, 3, 4] + tx_hash = c.foo(transact={}) + logs = get_logs(tx_hash, c, 'Bar') + assert logs[0].args._value == [1, 2, 3, 4] + +def test_storage_list_packing(get_logs, bytes_helper, get_contract_with_gas_estimation): -def test_storage_list_packing(t, get_last_log, bytes_helper, get_contract_with_gas_estimation, chain): - t.s = chain code = """ Bar: event({_value: int128[4]}) x: int128[4] @@ -607,15 +689,17 @@ def set_list(): """ c = get_contract_with_gas_estimation(code) - c.foo() - assert get_last_log(t, c)["_value"] == [0, 0, 0, 0] - c.set_list() - c.foo() - assert get_last_log(t, c)["_value"] == [1, 2, 3, 4] + tx_hash = c.foo(transact={}) + logs = get_logs(tx_hash, c, 'Bar') + assert logs[0].args._value == [0, 0, 0, 0] + c.set_list(transact={}) + tx_hash = c.foo(transact={}) + logs = get_logs(tx_hash, c, 'Bar') + assert logs[0].args._value == [1, 2, 3, 4] -def test_passed_list_packing(t, get_last_log, get_contract_with_gas_estimation, chain): - t.s = chain +def test_passed_list_packing(get_logs, get_contract_with_gas_estimation): + code = """ Bar: event({_value: int128[4]}) @@ -625,13 +709,12 @@ def foo(barbaric: int128[4]): """ c = get_contract_with_gas_estimation(code) - c.foo([4, 5, 6, 7]) - assert get_last_log(t, c)["_value"] == [4, 5, 6, 7] - + tx_hash = c.foo([4, 5, 6, 7], transact={}) + logs = get_logs(tx_hash, c, 'Bar') + assert logs[0].args._value == [4, 5, 6, 7] -def test_variable_decimal_list_packing(t, get_last_log, get_contract_with_gas_estimation, chain): - t.s = chain +def test_variable_decimal_list_packing(get_logs, get_contract_with_gas_estimation): code = """ Bar: event({_value: decimal[4]}) @@ -641,12 +724,13 @@ def foo(): """ c = get_contract_with_gas_estimation(code) - c.foo() - assert get_last_log(t, c)["_value"] == [1.11, 2.22, 3.33, 4.44] + tx_hash = c.foo(transact={}) + logs = get_logs(tx_hash, c, 'Bar') + assert logs[0].args._value == [Decimal('1.11'), Decimal('2.22'), Decimal('3.33'), Decimal('4.44')] -def test_storage_byte_packing(t, get_last_log, bytes_helper, get_contract_with_gas_estimation, chain): - t.s = chain +def test_storage_byte_packing(get_logs, bytes_helper, get_contract_with_gas_estimation): + code = """ MyLog: event({arg1: bytes[29]}) x:bytes[5] @@ -661,15 +745,17 @@ def setbytez(): """ c = get_contract_with_gas_estimation(code) - c.foo() - assert get_last_log(t, c)['arg1'] == b'' - c.setbytez() - c.foo() - assert get_last_log(t, c)['arg1'] == b'hello' + tx_hash = c.foo(0, transact={}) + logs = get_logs(tx_hash, c, 'MyLog') + assert logs[0].args.arg1 == b'' + c.setbytez(transact={}) + tx_hash = c.foo(0, transact={}) + logs = get_logs(tx_hash, c, 'MyLog') + assert logs[0].args.arg1 == b'hello' + +def test_storage_decimal_list_packing(get_logs, bytes_helper, get_contract_with_gas_estimation): -def test_storage_decimal_list_packing(t, get_last_log, bytes_helper, get_contract_with_gas_estimation, chain): - t.s = chain code = """ Bar: event({_value: decimal[4]}) x: decimal[4] @@ -684,11 +770,13 @@ def set_list(): """ c = get_contract_with_gas_estimation(code) - c.foo() - assert get_last_log(t, c)["_value"] == [0, 0, 0, 0] - c.set_list() - c.foo() - assert get_last_log(t, c)["_value"] == [1.33, 2.33, 3.33, 4.33] + tx_hash = c.foo(transact={}) + logs = get_logs(tx_hash, c, 'Bar') + assert logs[0].args._value == [Decimal('0'), Decimal('0'), Decimal('0'), Decimal('0')] + c.set_list(transact={}) + tx_hash = c.foo(transact={}) + logs = get_logs(tx_hash, c, 'Bar') + assert logs[0].args._value == [Decimal('1.33'), Decimal('2.33'), Decimal('3.33'), Decimal('4.33')] def test_logging_fails_when_declartation_is_too_big(assert_tx_failed, get_contract_with_gas_estimation): @@ -709,8 +797,7 @@ def foo(inp: bytes[33]): assert_tx_failed(lambda: get_contract_with_gas_estimation(code), TypeMismatchException) -def test_2nd_var_list_packing(t, get_last_log, get_contract_with_gas_estimation, chain): - t.s = chain +def test_2nd_var_list_packing(get_logs, get_contract_with_gas_estimation): code = """ Bar: event({arg1: int128, arg2: int128[4]}) @@ -721,12 +808,11 @@ def foo(): """ c = get_contract_with_gas_estimation(code) - c.foo() - assert get_last_log(t, c)["arg2"] == [1, 2, 3, 4] + tx_hash = c.foo(transact={}) + assert get_logs(tx_hash, c, 'Bar')[0].args.arg2 == [1, 2, 3, 4] -def test_2nd_var_storage_list_packing(t, get_last_log, get_contract_with_gas_estimation, chain): - t.s = chain +def test_2nd_var_storage_list_packing(get_logs, get_contract_with_gas_estimation): code = """ Bar: event({arg1: int128, arg2: int128[4]}) x: int128[4] @@ -741,15 +827,14 @@ def set_list(): """ c = get_contract_with_gas_estimation(code) - c.foo() - assert get_last_log(t, c)["arg2"] == [0, 0, 0, 0] - c.set_list() - c.foo() - assert get_last_log(t, c)["arg2"] == [1, 2, 3, 4] + tx_hash = c.foo(transact={}) + assert get_logs(tx_hash, c, 'Bar')[0].args.arg2 == [0, 0, 0, 0] + c.set_list(transact={}) + tx_hash = c.foo(transact={}) + assert get_logs(tx_hash, c, 'Bar')[0].args.arg2 == [1, 2, 3, 4] -def test_mixed_var_list_packing(t, get_last_log, get_contract_with_gas_estimation, chain): - t.s = chain +def test_mixed_var_list_packing(get_logs, get_contract_with_gas_estimation): code = """ Bar: event({arg1: int128, arg2: int128[4], arg3 :bytes[4], arg4: int128[3], arg5: int128[2]}) x: int128[4] @@ -770,16 +855,16 @@ def set_list(): """ c = get_contract_with_gas_estimation(code) - c.foo() - log = get_last_log(t, c) - assert log["arg2"] == [0, 0, 0, 0] - assert log["arg3"] == b"test" - assert log["arg4"] == [7, 8, 9] - assert log["arg5"] == [1024, 2048] - c.set_list() - c.foo() - log = get_last_log(t, c) - assert log["arg2"] == [1, 2, 3, 4] - assert log["arg3"] == b"test" - assert log["arg4"] == [7, 8, 9] - assert log["arg5"] == [1024, 2048] + tx_hash = c.foo(transact={}) + log = get_logs(tx_hash, c, 'Bar')[0] + assert log.args["arg2"] == [0, 0, 0, 0] + assert log.args["arg3"] == b"test" + assert log.args["arg4"] == [7, 8, 9] + assert log.args["arg5"] == [1024, 2048] + c.set_list(transact={}) + tx_hash = c.foo(transact={}) + log = get_logs(tx_hash, c, 'Bar')[0] + assert log.args["arg2"] == [1, 2, 3, 4] + assert log.args["arg3"] == b"test" + assert log.args["arg4"] == [7, 8, 9] + assert log.args["arg5"] == [1024, 2048] diff --git a/tests/parser/features/test_logging_bytes_extended.py b/tests/parser/features/test_logging_bytes_extended.py index 029514993f..1b42c4f09d 100644 --- a/tests/parser/features/test_logging_bytes_extended.py +++ b/tests/parser/features/test_logging_bytes_extended.py @@ -1,6 +1,6 @@ -def test_bytes_logging_extended(t, get_contract_with_gas_estimation, get_logs, chain): +def test_bytes_logging_extended(get_contract_with_gas_estimation, get_logs): code = """ MyLog: event({arg1: int128, arg2: bytes[64], arg3: int128}) @@ -10,15 +10,14 @@ def foo(): """ c = get_contract_with_gas_estimation(code) - c.foo() - receipt = chain.head_state.receipts[-1] - log = get_logs(receipt, c) - assert log[0]['arg1'] == 667788 - assert log[0]['arg2'] == b"hello" * 9 - assert log[0]['arg3'] == 334455 + log = get_logs(c.foo(transact={}), c, 'MyLog') + + assert log[0].args.arg1 == 667788 + assert log[0].args.arg2 == b"hello" * 9 + assert log[0].args.arg3 == 334455 -def test_bytes_logging_extended_variables(t, get_contract_with_gas_estimation, get_logs, chain): +def test_bytes_logging_extended_variables(get_contract_with_gas_estimation, get_logs): code = """ MyLog: event({arg1: bytes[64], arg2: bytes[64], arg3: bytes[64]}) @@ -31,15 +30,14 @@ def foo(): """ c = get_contract_with_gas_estimation(code) - c.foo() - receipt = chain.head_state.receipts[-1] - log = get_logs(receipt, c) - assert log[0]['arg1'] == b"hello" * 9 - assert log[0]['arg2'] == b"hello" * 8 - assert log[0]['arg3'] == b"hello" * 7 + log = get_logs(c.foo(transact={}), c, 'MyLog') + assert log[0].args.arg1 == b"hello" * 9 + assert log[0].args.arg2 == b"hello" * 8 + assert log[0].args.arg3 == b"hello" * 7 -def test_bytes_logging_extended_passthrough(t, get_contract_with_gas_estimation, get_logs, chain): + +def test_bytes_logging_extended_passthrough(get_contract_with_gas_estimation, get_logs): code = """ MyLog: event({arg1: int128, arg2: bytes[64], arg3: int128}) @@ -49,15 +47,15 @@ def foo(a: int128, b: bytes[64], c: int128): """ c = get_contract_with_gas_estimation(code) - c.foo(333, b"flower" * 8, 444) - receipt = chain.head_state.receipts[-1] - log = get_logs(receipt, c) - assert log[0]['arg1'] == 333 - assert log[0]['arg2'] == b"flower" * 8 - assert log[0]['arg3'] == 444 + + log = get_logs(c.foo(333, b"flower" * 8, 444, transact={}), c, 'MyLog') + + assert log[0].args.arg1 == 333 + assert log[0].args.arg2 == b"flower" * 8 + assert log[0].args.arg3 == 444 -def test_bytes_logging_extended_storage(t, get_contract_with_gas_estimation, get_logs, chain): +def test_bytes_logging_extended_storage(get_contract_with_gas_estimation, get_logs): code = """ MyLog: event({arg1: int128, arg2: bytes[64], arg3: int128}) a: int128 @@ -77,22 +75,22 @@ def set(x: int128, y: bytes[64], z: int128): c = get_contract_with_gas_estimation(code) c.foo() - receipt = chain.head_state.receipts[-1] - log = get_logs(receipt, c) - assert log[0]['arg1'] == 0 - assert log[0]['arg2'] == b"" - assert log[0]['arg3'] == 0 + log = get_logs(c.foo(transact={}), c, 'MyLog') - c.set(333, b"flower" * 8, 444) - c.foo() - receipt = chain.head_state.receipts[-1] - log = get_logs(receipt, c) - assert log[0]['arg1'] == 333 - assert log[0]['arg2'] == b"flower" * 8 - assert log[0]['arg3'] == 444 + assert log[0].args.arg1 == 0 + assert log[0].args.arg2 == b"" + assert log[0].args.arg3 == 0 + + c.set(333, b"flower" * 8, 444, transact={}) + + log = get_logs(c.foo(transact={}), c, 'MyLog')[0] + assert log.args.arg1 == 333 + assert log.args.arg2 == b"flower" * 8 + assert log.args.arg3 == 444 -def test_bytes_logging_extended_mixed_with_lists(t, get_contract_with_gas_estimation, get_logs, chain): + +def test_bytes_logging_extended_mixed_with_lists(get_contract_with_gas_estimation, get_logs): code = """ MyLog: event({ arg1: int128[2][2], @@ -112,10 +110,9 @@ def foo(): """ c = get_contract_with_gas_estimation(code) - c.foo() - receipt = chain.head_state.receipts[-1] - log = get_logs(receipt, c) - assert log[0]['arg1'] == [[24, 26], [12, 10]] - assert log[0]['arg2'] == b"hello" * 9 - assert log[0]['arg3'] == 314159 - assert log[0]['arg4'] == b"help" * 11 + log = get_logs(c.foo(transact={}), c, 'MyLog')[0] + + assert log.args.arg1 == [[24, 26], [12, 10]] + assert log.args.arg2 == b"hello" * 9 + assert log.args.arg3 == 314159 + assert log.args.arg4 == b"help" * 11 diff --git a/tests/parser/features/test_map_delete.py b/tests/parser/features/test_map_delete.py index 6fb64c2185..8ec7dc50be 100644 --- a/tests/parser/features/test_map_delete.py +++ b/tests/parser/features/test_map_delete.py @@ -19,11 +19,11 @@ def delete(key: bytes32): c = get_contract_with_gas_estimation(code) - assert c.get("test") == b'\x00' * 32 - c.set("test", "value") - assert c.get("test")[:5] == b"value" - c.delete("test") - assert c.get("test") == b'\x00' * 32 + assert c.get(b"test") == b'\x00' * 32 + c.set(b"test", b"value", transact={}) + assert c.get(b"test")[:5] == b"value" + c.delete(b"test", transact={}) + assert c.get(b"test") == b'\x00' * 32 def test_map_delete_nested(get_contract_with_gas_estimation): @@ -45,11 +45,11 @@ def delete(key1: bytes32, key2: bytes32): c = get_contract_with_gas_estimation(code) - assert c.get("test1", "test2") == b'\x00' * 32 - c.set("test1", "test2", "value") - assert c.get("test1", "test2")[:5] == b"value" - c.delete("test1", "test2") - assert c.get("test1", "test2") == b'\x00' * 32 + assert c.get(b"test1", b"test2") == b'\x00' * 32 + c.set(b"test1", b"test2", b"value", transact={}) + assert c.get(b"test1", b"test2")[:5] == b"value" + c.delete(b"test1", b"test2", transact={}) + assert c.get(b"test1", b"test2") == b'\x00' * 32 def test_map_delete_struct(get_contract_with_gas_estimation): @@ -79,7 +79,7 @@ def delete(): c = get_contract_with_gas_estimation(code) assert c.get() == [0, 0] - c.set() + c.set(transact={}) assert c.get() == [333, 444] - c.delete() + c.delete(transact={}) assert c.get() == [0, 0] diff --git a/tests/parser/functions/rlp/conftest.py b/tests/parser/functions/rlp/conftest.py index 84997ecc98..87d9a1d458 100644 --- a/tests/parser/functions/rlp/conftest.py +++ b/tests/parser/functions/rlp/conftest.py @@ -1,29 +1,22 @@ import pytest -import rlp +import eth_tester + from vyper import utils as vyper_utils -from ethereum import transactions, messages -@pytest.fixture -def inject_tx(utils, chain): - def inject_tx(txhex): - tx = rlp.decode(utils.decode_hex(txhex[2:]), transactions.Transaction) - chain.head_state.set_balance(tx.sender, tx.startgas * tx.gasprice) - chain.chain.state.set_balance(tx.sender, tx.startgas * tx.gasprice) - messages.apply_transaction(chain.head_state, tx) - chain.block.transactions.append(tx) - contract_address = utils.sha3(rlp.encode([tx.sender, 0]))[12:] - assert chain.head_state.get_code(contract_address) - chain.mine(1) - chain.head_state.gas_limit = 10**9 - return contract_address - return inject_tx +@pytest.fixture(autouse=True) +def patch_large_gas_limit(monkeypatch): + monkeypatch.setattr(eth_tester.backends.pyevm.main, 'GENESIS_GAS_LIMIT', 10**9) @pytest.fixture -def fake_tx(inject_tx): +def fake_tx(tester, w3): def fake_tx(): - address = inject_tx("0xf9035b808506fc23ac0083045f788080b903486103305660006109ac5260006109cc527f0100000000000000000000000000000000000000000000000000000000000000600035046109ec526000610a0c5260006109005260c06109ec51101515585760f86109ec51101561006e5760bf6109ec510336141558576001610a0c52610098565b60013560f76109ec51036020035260005160f66109ec510301361415585760f66109ec5103610a0c525b61022060016064818352015b36610a0c511015156100b557610291565b7f0100000000000000000000000000000000000000000000000000000000000000610a0c5135046109ec526109cc5160206109ac51026040015260016109ac51016109ac5260806109ec51101561013b5760016109cc5161044001526001610a0c516109cc5161046001376001610a0c5101610a0c5260216109cc51016109cc52610281565b60b86109ec5110156101d15760806109ec51036109cc51610440015260806109ec51036001610a0c51016109cc51610460013760816109ec5114156101ac5760807f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350410151558575b607f6109ec5103610a0c5101610a0c5260606109ec51036109cc51016109cc52610280565b60c06109ec51101561027d576001610a0c51013560b76109ec510360200352600051610a2c526038610a2c5110157f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350402155857610a2c516109cc516104400152610a2c5160b66109ec5103610a0c51016109cc516104600137610a2c5160b66109ec5103610a0c510101610a0c526020610a2c51016109cc51016109cc5261027f565bfe5b5b5b81516001018083528114156100a4575b5050601f6109ac511115155857602060206109ac5102016109005260206109005103610a0c5261022060016064818352015b6000610a0c5112156102d45761030a565b61090051610a0c516040015101610a0c51610900516104400301526020610a0c5103610a0c5281516001018083528114156102c3575b50506109cc516109005101610420526109cc5161090051016109005161044003f35b61000461033003610004600039610004610330036000f31b2d4f") - assert vyper_utils.bytes_to_int(address) == vyper_utils.RLP_DECODER_ADDRESS - return address + tx_hex = "0xf9035b808506fc23ac0083045f788080b903486103305660006109ac5260006109cc527f0100000000000000000000000000000000000000000000000000000000000000600035046109ec526000610a0c5260006109005260c06109ec51101515585760f86109ec51101561006e5760bf6109ec510336141558576001610a0c52610098565b60013560f76109ec51036020035260005160f66109ec510301361415585760f66109ec5103610a0c525b61022060016064818352015b36610a0c511015156100b557610291565b7f0100000000000000000000000000000000000000000000000000000000000000610a0c5135046109ec526109cc5160206109ac51026040015260016109ac51016109ac5260806109ec51101561013b5760016109cc5161044001526001610a0c516109cc5161046001376001610a0c5101610a0c5260216109cc51016109cc52610281565b60b86109ec5110156101d15760806109ec51036109cc51610440015260806109ec51036001610a0c51016109cc51610460013760816109ec5114156101ac5760807f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350410151558575b607f6109ec5103610a0c5101610a0c5260606109ec51036109cc51016109cc52610280565b60c06109ec51101561027d576001610a0c51013560b76109ec510360200352600051610a2c526038610a2c5110157f01000000000000000000000000000000000000000000000000000000000000006001610a0c5101350402155857610a2c516109cc516104400152610a2c5160b66109ec5103610a0c51016109cc516104600137610a2c5160b66109ec5103610a0c510101610a0c526020610a2c51016109cc51016109cc5261027f565bfe5b5b5b81516001018083528114156100a4575b5050601f6109ac511115155857602060206109ac5102016109005260206109005103610a0c5261022060016064818352015b6000610a0c5112156102d45761030a565b61090051610a0c516040015101610a0c51610900516104400301526020610a0c5103610a0c5281516001018083528114156102c3575b50506109cc516109005101610420526109cc5161090051016109005161044003f35b61000461033003610004600039610004610330036000f31b2d4f" + w3.eth.sendTransaction({'to': '0x39ba083c30fCe59883775Fc729bBE1f9dE4DEe11', 'value': 10**17}) + tx_hash = w3.eth.sendRawTransaction(tx_hex) + receipt = w3.eth.getTransactionReceipt(tx_hash) + contract_address = receipt.contractAddress + assert vyper_utils.RLP_DECODER_ADDRESS == w3.toInt(hexstr=contract_address) + return contract_address return fake_tx diff --git a/tests/parser/functions/rlp/test_rlp_list.py b/tests/parser/functions/rlp/test_rlp_list.py index ca78468fcf..584c475287 100644 --- a/tests/parser/functions/rlp/test_rlp_list.py +++ b/tests/parser/functions/rlp/test_rlp_list.py @@ -1,7 +1,7 @@ import rlp -def test_rlp_decoder_code(t, assert_tx_failed, get_contract_with_gas_estimation, fake_tx): +def test_rlp_decoder_code(w3, assert_tx_failed, get_contract_with_gas_estimation, fake_tx): fake_tx() rlp_decoder_code = """ @@ -107,5 +107,5 @@ def yolo(raw_utxo: bytes[1024]) -> (address, int128, int128): assert_tx_failed(lambda: c.too(rlp.encode([b'\x00']))) assert c.loo(rlp.encode([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])) == 55 assert c.woo(rlp.encode([b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'10', b'11', b'12', b'13', b'14', b'15'])) == b'123456789101112131415' - assert c.yolo(rlp.encode([t.a0, 1, 2])) == ['0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1', 1, 2] + assert c.yolo(rlp.encode([w3.toBytes(hexstr=w3.eth.accounts[0]), 1, 2])) == [w3.eth.accounts[0], 1, 2] print('Passed RLP decoder tests') diff --git a/tests/parser/functions/test_block.py b/tests/parser/functions/test_block.py index 7249e69496..3a91bf0347 100644 --- a/tests/parser/functions/test_block.py +++ b/tests/parser/functions/test_block.py @@ -1,5 +1,5 @@ -def test_block_number(get_contract_with_gas_estimation, chain): - chain.mine(1) +def test_block_number(get_contract_with_gas_estimation, w3): + w3.testing.mine(1) block_number_code = """ @public @@ -10,8 +10,8 @@ def block_number() -> int128: assert c.block_number() == 2 -def test_blockhash(get_contract_with_gas_estimation, chain): - chain.mine(1) +def test_blockhash(get_contract_with_gas_estimation, w3): + w3.testing.mine(1) block_number_code = """ @public diff --git a/tests/parser/functions/test_block_number.py b/tests/parser/functions/test_block_number.py index 45b17e8a19..79fa24696a 100644 --- a/tests/parser/functions/test_block_number.py +++ b/tests/parser/functions/test_block_number.py @@ -1,11 +1,12 @@ -def test_block_number(get_contract_with_gas_estimation, chain): - chain.mine(1) - +def test_block_number(get_contract_with_gas_estimation, w3): block_number_code = """ @public def block_number() -> int128: return block.number -""" + """ c = get_contract_with_gas_estimation(block_number_code) + + assert c.block_number() == 1 + w3.testing.mine(1) assert c.block_number() == 2 diff --git a/tests/parser/functions/test_ceil.py b/tests/parser/functions/test_ceil.py index d026992092..33f6a6c30d 100644 --- a/tests/parser/functions/test_ceil.py +++ b/tests/parser/functions/test_ceil.py @@ -1,3 +1,6 @@ +from decimal import Decimal + + def test_ceil(get_contract_with_gas_estimation): code = """ x: decimal @@ -94,5 +97,5 @@ def ceil_param(p: decimal) -> int128: assert c.fos() == -5472 assert c.fot() == -170141183460469231731687303715884105727 assert c.fou() == -3 - assert c.ceil_param(-0.5) == 0 - assert c.ceil_param(-7777777.7777777) == -7777777 + assert c.ceil_param(Decimal('-0.5')) == 0 + assert c.ceil_param(Decimal('-7777777.7777777')) == -7777777 diff --git a/tests/parser/functions/test_convert.py b/tests/parser/functions/test_convert.py index 6f3155622b..d507c01c4e 100644 --- a/tests/parser/functions/test_convert.py +++ b/tests/parser/functions/test_convert.py @@ -1,4 +1,4 @@ -def test_convert_to_num(chain, get_contract_with_gas_estimation, assert_tx_failed): +def test_convert_to_num(get_contract_with_gas_estimation, assert_tx_failed): code = """ a: int128 b: uint256 @@ -48,7 +48,7 @@ def zero_bytes(inp: bytes[1]) -> int128: assert c.zero_bytes(b'\x00') == 0 -def test_convert_to_uint256(t, chain, get_contract, utils, assert_tx_failed): +def test_convert_to_uint256(get_contract, assert_tx_failed): code = """ a: int128 b: bytes32 @@ -75,7 +75,7 @@ def bytes32_to_uint256() -> (uint256, uint256): assert c.bytes32_to_uint256() == [1, 1] -def test_convert_to_decimal(t, chain, get_contract, utils, assert_tx_failed): +def test_convert_to_decimal(get_contract, assert_tx_failed): code = """ a: int128 b: decimal @@ -92,7 +92,7 @@ def int128_to_decimal(inp: int128) -> (decimal, decimal, decimal): assert c.int128_to_decimal(1) == [1.0, 1.0, 1.0] -def test_convert_to_bytes32(t, get_contract_with_gas_estimation, bytes_helper): +def test_convert_to_bytes32(w3, get_contract_with_gas_estimation, bytes_helper): code = """ a: int128 b: uint256 @@ -132,5 +132,5 @@ def bytes_to_bytes32(inp: bytes[32]) -> (bytes32, bytes32): c = get_contract_with_gas_estimation(code) assert c.int128_to_bytes32(1) == [bytes_helper('', 31) + b'\x01'] * 3 assert c.uint256_to_bytes32(1) == [bytes_helper('', 31) + b'\x01'] * 3 - assert c.address_to_bytes32(t.a0) == [bytes_helper('', 12) + t.a0] * 2 + assert c.address_to_bytes32(w3.eth.accounts[0]) == [bytes_helper('', 12) + w3.toBytes(hexstr=w3.eth.accounts[0])] * 2 assert c.bytes_to_bytes32(bytes_helper('', 32)) == [bytes_helper('', 32)] * 2 diff --git a/tests/parser/functions/test_ecrecover.py b/tests/parser/functions/test_ecrecover.py index 8919a9aa18..ad8782ac29 100644 --- a/tests/parser/functions/test_ecrecover.py +++ b/tests/parser/functions/test_ecrecover.py @@ -1,4 +1,7 @@ -def test_ecrecover_test(get_contract_with_gas_estimation, utils): +from eth_account import Account + + +def test_ecrecover_test(get_contract_with_gas_estimation): ecrecover_test = """ @public def test_ecrecover(h: bytes32, v:uint256, r:uint256, s:uint256) -> address: @@ -13,10 +16,12 @@ def test_ecrecover2() -> address: """ c = get_contract_with_gas_estimation(ecrecover_test) + h = b'\x35' * 32 - k = b'\x46' * 32 - v, r, S = utils.ecsign(h, k) - assert c.test_ecrecover(h, v, r, S) == '0x' + utils.encode_hex(utils.privtoaddr(k)) - assert c.test_ecrecover2() == '0x' + utils.encode_hex(utils.privtoaddr(k)) + local_account = Account.privateKeyToAccount(b'\x46' * 32) + sig = local_account.signHash(h) + + assert c.test_ecrecover(h, sig.v, sig.r, sig.s) == local_account.address + assert c.test_ecrecover2() == local_account.address print("Passed ecrecover test") diff --git a/tests/parser/functions/test_extract32.py b/tests/parser/functions/test_extract32.py index fc9e024d70..38dadd6c57 100644 --- a/tests/parser/functions/test_extract32.py +++ b/tests/parser/functions/test_extract32.py @@ -1,7 +1,6 @@ -from ethereum.tools import tester -def test_extract32_extraction(get_contract_with_gas_estimation): +def test_extract32_extraction(assert_tx_failed, get_contract_with_gas_estimation): extract32_code = """ y: bytes[100] @public @@ -40,12 +39,7 @@ def extrakt32_storage(index: int128, inp: bytes[100]) -> bytes32: for S, i in test_cases: expected_result = S[i: i + 32] if 0 <= i <= len(S) - 32 else None if expected_result is None: - try: - c.extrakt32(S, i) - success = True - except tester.TransactionFailed: - success = False - assert not success + assert_tx_failed(lambda: c.extrakt32(S, i)) else: assert c.extrakt32(S, i) == expected_result assert c.extrakt32_mem(S, i) == expected_result @@ -54,7 +48,7 @@ def extrakt32_storage(index: int128, inp: bytes[100]) -> bytes32: print("Passed bytes32 extraction test") -def test_extract32_code(get_contract_with_gas_estimation): +def test_extract32_code(assert_tx_failed, get_contract_with_gas_estimation): extract32_code = """ @public def foo(inp: bytes[32]) -> int128: @@ -80,22 +74,15 @@ def foq(inp: bytes[32]) -> address: c = get_contract_with_gas_estimation(extract32_code) assert c.foo(b"\x00" * 30 + b"\x01\x01") == 257 assert c.bar(b"\x00" * 30 + b"\x01\x01") == 257 - try: - c.foo(b"\x80" + b"\x00" * 30) - success = True - except tester.TransactionFailed: - success = False - assert not success + + assert_tx_failed(lambda: c.foo(b"\x80" + b"\x00" * 30)) + assert c.bar(b"\x80" + b"\x00" * 31) == 2**255 assert c.baz(b"crow" * 8) == b"crow" * 8 assert c.fop(b"crow" * 8) == b"crow" * 8 assert c.foq(b"\x00" * 12 + b"3" * 20) == "0x" + "3" * 40 - try: - c.foq(b"crow" * 8) - success = True - except tester.TransactionFailed: - success = False - assert not success + + assert_tx_failed(lambda: c.foq(b"crow" * 8)) print('Passed extract32 test') diff --git a/tests/parser/functions/test_floor.py b/tests/parser/functions/test_floor.py index b837bfc8bd..612b5cdcef 100644 --- a/tests/parser/functions/test_floor.py +++ b/tests/parser/functions/test_floor.py @@ -1,3 +1,6 @@ +from decimal import Decimal + + def test_floor(get_contract_with_gas_estimation): code = """ x: decimal @@ -100,5 +103,5 @@ def floor_param(p: decimal) -> int128: assert c.fos() == -1 assert c.fot() == -170141183460469231731687303715884105728 assert c.fou() == -4 - assert c.floor_param(-5.6) == -6 - assert c.floor_param(-0.0000000001) == -1 + assert c.floor_param(Decimal('-5.6')) == -6 + assert c.floor_param(Decimal('-0.0000000001')) == -1 diff --git a/tests/parser/functions/test_is_contract.py b/tests/parser/functions/test_is_contract.py index b98b05c22d..d269573209 100644 --- a/tests/parser/functions/test_is_contract.py +++ b/tests/parser/functions/test_is_contract.py @@ -1,4 +1,4 @@ -def test_is_contract(t, get_contract_with_gas_estimation): +def test_is_contract(w3, get_contract_with_gas_estimation): contract_1 = """ @public def foo(arg1: address) -> bool: @@ -11,14 +11,15 @@ def foo(arg1: address) -> bool: def foo(arg1: address) -> bool: return arg1.is_contract """ + a0, a1 = w3.eth.accounts[:2] c1 = get_contract_with_gas_estimation(contract_1) c2 = get_contract_with_gas_estimation(contract_2) assert c1.foo(c1.address) is True assert c1.foo(c2.address) is True - assert c1.foo(t.a1) is False - assert c1.foo(t.a3) is False + assert c1.foo(a1) is False + assert c1.foo(a0) is False assert c2.foo(c1.address) is True assert c2.foo(c2.address) is True - assert c2.foo(t.a1) is False - assert c2.foo(t.a3) is False + assert c2.foo(a1) is False + assert c2.foo(a0) is False diff --git a/tests/parser/functions/test_minmax.py b/tests/parser/functions/test_minmax.py index a760de2ed6..37146f1ab5 100644 --- a/tests/parser/functions/test_minmax.py +++ b/tests/parser/functions/test_minmax.py @@ -1,3 +1,6 @@ +from decimal import Decimal + + def test_minmax(get_contract_with_gas_estimation): minmax_test = """ @public @@ -10,7 +13,7 @@ def goo() -> uint256: """ c = get_contract_with_gas_estimation(minmax_test) - assert c.foo() == 58223.123 + assert c.foo() == Decimal('58223.123') assert c.goo() == 83 print("Passed min/max test") diff --git a/tests/parser/functions/test_raw_call.py b/tests/parser/functions/test_raw_call.py index e81c4d862d..e541b999b3 100644 --- a/tests/parser/functions/test_raw_call.py +++ b/tests/parser/functions/test_raw_call.py @@ -1,4 +1,3 @@ -from ethereum.tools import tester def test_caller_code(get_contract_with_gas_estimation): @@ -24,7 +23,7 @@ def baz() -> bytes[7]: print('Passed raw call test') -def test_multiple_levels(get_contract_with_gas_estimation, chain): +def test_multiple_levels(w3, get_contract_with_gas_estimation): inner_code = """ @public def returnten() -> int128: @@ -48,17 +47,21 @@ def create_and_return_forwarder(inp: address) -> address: c2 = get_contract_with_gas_estimation(outer_code) assert c2.create_and_call_returnten(c.address) == 10 + c2.create_and_call_returnten(c.address, transact={}) expected_forwarder_code_mask = b'`.`\x0c`\x009`.`\x00\xf36`\x00`\x007a\x10\x00`\x006`\x00s\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Z\xf4\x15XWa\x10\x00`\x00\xf3'[12:] - c3 = c2.create_and_return_forwarder(c.address) - assert chain.head_state.get_code(c3)[:15] == expected_forwarder_code_mask[:15] - assert chain.head_state.get_code(c3)[35:] == expected_forwarder_code_mask[35:] + c3 = c2.create_and_return_forwarder(c.address, call={}) + c2.create_and_return_forwarder(c.address, transact={}) + + c3_contract_code = w3.toBytes(w3.eth.getCode(c3)) + assert c3_contract_code[:15] == expected_forwarder_code_mask[:15] + assert c3_contract_code[35:] == expected_forwarder_code_mask[35:] print('Passed forwarder test') # TODO: This one is special - print('Gas consumed: %d' % (chain.head_state.receipts[-1].gas_used - chain.head_state.receipts[-2].gas_used - chain.last_tx.intrinsic_gas_used)) + # print('Gas consumed: %d' % (chain.head_state.receipts[-1].gas_used - chain.head_state.receipts[-2].gas_used - chain.last_tx.intrinsic_gas_used)) -def test_multiple_levels2(get_contract_with_gas_estimation): +def test_multiple_levels2(assert_tx_failed, get_contract_with_gas_estimation): inner_code = """ @public def returnten() -> int128: @@ -81,11 +84,7 @@ def create_and_return_forwarder(inp: address) -> address: """ c2 = get_contract_with_gas_estimation(outer_code) - try: - c2.create_and_call_returnten(c.address) - success = True - except tester.TransactionFailed: - success = False - assert not success + + assert_tx_failed(lambda: c2.create_and_call_returnten(c.address)) print('Passed forwarder exception test') diff --git a/tests/parser/functions/test_return_tuple.py b/tests/parser/functions/test_return_tuple.py index 7aae4c2773..e4ceebcc9f 100644 --- a/tests/parser/functions/test_return_tuple.py +++ b/tests/parser/functions/test_return_tuple.py @@ -50,10 +50,10 @@ def out_very_long_bytes() -> (int128, bytes[1024], int128, address): c = get_contract_with_gas_estimation(code) assert c.out() == [3333, "0x0000000000000000000000000000000000000001"] - assert c.out_literals() == [1, "0x0000000000000000000000000000000000000000", b"random"] + assert c.out_literals() == [1, None, b"random"] assert c.out_bytes_first() == [b"test", 1234] - assert c.out_bytes_a(5555555, "test") == [5555555, b"test"] - assert c.out_bytes_b(5555555, "test") == [b"test", 5555555, b"test"] + assert c.out_bytes_a(5555555, b"test") == [5555555, b"test"] + assert c.out_bytes_b(5555555, b"test") == [b"test", 5555555, b"test"] assert c.four() == [1234, b"bytes", b"test", 4321] assert c.out_chunk() == [b"hello", 5678, b"world"] assert c.out_very_long_bytes() == [5555, long_string.encode(), 6666, "0x0000000000000000000000000000000000001234"] @@ -67,7 +67,7 @@ def out_literals() -> (int128, address, bytes[6]): """ c = get_contract_with_gas_estimation(code) - assert c.translator.function_data['out_literals']['decode_types'] == ['int128', 'address', 'bytes'] + assert c._classic_contract.abi[0]['outputs'] == [{'type': 'int128', 'name': 'out'}, {'type': 'address', 'name': 'out'}, {'type': 'bytes', 'name': 'out'}] def test_return_tuple_assign(get_contract_with_gas_estimation): @@ -89,7 +89,7 @@ def test() -> (int128, address, bytes[10]): c = get_contract_with_gas_estimation(code) - assert c.out_literals() == c.test() == [1, "0x0000000000000000000000000000000000000000", b"random"] + assert c.out_literals() == c.test() == [1, None, b"random"] def test_return_tuple_assign_storage(get_contract_with_gas_estimation): @@ -112,4 +112,4 @@ def test() -> (int128, bytes[20], address, bytes[20]): c = get_contract_with_gas_estimation(code) - assert c.out_literals() == [1, b"testtesttest", "0x0000000000000000000000000000000000000000", b"random"] + assert c.out_literals() == [1, b"testtesttest", None, b"random"] diff --git a/tests/parser/functions/test_send.py b/tests/parser/functions/test_send.py index 6bee18980f..0742c17626 100644 --- a/tests/parser/functions/test_send.py +++ b/tests/parser/functions/test_send.py @@ -1,4 +1,4 @@ -def test_send(assert_tx_failed, chain): +def test_send(assert_tx_failed, get_contract): send_test = """ @public def foo(): @@ -8,7 +8,7 @@ def foo(): def fop(): send(msg.sender, 10) """ - c = chain.contract(send_test, language='vyper', value=10) - assert_tx_failed(lambda: c.foo()) - c.fop() - assert_tx_failed(lambda: c.fop()) + c = get_contract(send_test, value=10) + assert_tx_failed(lambda: c.foo(transact={})) + c.fop(transact={}) + assert_tx_failed(lambda: c.fop(transact={})) diff --git a/tests/parser/functions/test_sha3.py b/tests/parser/functions/test_sha3.py index 36c661ea38..62d6ed5f99 100644 --- a/tests/parser/functions/test_sha3.py +++ b/tests/parser/functions/test_sha3.py @@ -1,4 +1,4 @@ -def test_hash_code(get_contract_with_gas_estimation, utils): +def test_hash_code(get_contract_with_gas_estimation, keccak): hash_code = """ @public def foo(inp: bytes[100]) -> bytes32: @@ -11,9 +11,9 @@ def bar() -> bytes32: c = get_contract_with_gas_estimation(hash_code) for inp in (b"", b"cow", b"s" * 31, b"\xff" * 32, b"\n" * 33, b"g" * 64, b"h" * 65): - assert c.foo(inp) == utils.sha3(inp) + assert '0x' + c.foo(inp).hex() == keccak(inp).hex() - assert c.bar() == utils.sha3("inp") + assert '0x' + c.bar().hex() == keccak(b"inp").hex() def test_hash_code2(get_contract_with_gas_estimation): @@ -49,19 +49,19 @@ def try32(inp: bytes32) -> bool: return sha3(inp) == sha3(self.test) """ c = get_contract_with_gas_estimation(hash_code3) - c.set_test(b"") + c.set_test(b"", transact={}) assert c.tryy(b"") is True assert c.trymem(b"") is True assert c.tryy(b"cow") is False - c.set_test(b"cow") + c.set_test(b"cow", transact={}) assert c.tryy(b"") is False assert c.tryy(b"cow") is True - c.set_test(b"\x35" * 32) + c.set_test(b"\x35" * 32, transact={}) assert c.tryy(b"\x35" * 32) is True assert c.trymem(b"\x35" * 32) is True assert c.try32(b"\x35" * 32) is True assert c.tryy(b"\x35" * 33) is False - c.set_test(b"\x35" * 33) + c.set_test(b"\x35" * 33, transact={}) assert c.tryy(b"\x35" * 32) is False assert c.trymem(b"\x35" * 32) is False assert c.try32(b"\x35" * 32) is False diff --git a/tests/parser/functions/test_slice.py b/tests/parser/functions/test_slice.py index 49791a4978..ce2709a471 100644 --- a/tests/parser/functions/test_slice.py +++ b/tests/parser/functions/test_slice.py @@ -1,5 +1,3 @@ -import pytest -from ethereum.tools import tester def test_test_slice(get_contract_with_gas_estimation): @@ -38,7 +36,6 @@ def slice_tower_test(inp1: bytes[50]) -> bytes[50]: inp = slice(inp, start=1, len=30 - i * 2) return inp """ - c = get_contract_with_gas_estimation(test_slice2) x = c.slice_tower_test(b"abcdefghijklmnopqrstuvwxyz1234") assert x == b"klmnopqrst", x @@ -75,7 +72,7 @@ def bar(inp1: bytes[50]) -> int128: print('Passed storage slice test') -def test_test_slice4(get_contract_with_gas_estimation): +def test_test_slice4(get_contract_with_gas_estimation, assert_tx_failed): test_slice4 = """ @public def foo(inp: bytes[10], start: int128, len: int128) -> bytes[10]: @@ -90,14 +87,10 @@ def foo(inp: bytes[10], start: int128, len: int128) -> bytes[10]: assert c.foo(b"badminton", 1, 0) == b"" assert c.foo(b"badminton", 9, 0) == b"" - with pytest.raises(tester.TransactionFailed): - c.foo(b"badminton", 0, 10) - with pytest.raises(tester.TransactionFailed): - c.foo(b"badminton", 1, 9) - with pytest.raises(tester.TransactionFailed): - c.foo(b"badminton", 9, 1) - with pytest.raises(tester.TransactionFailed): - c.foo(b"badminton", 10, 0) + assert_tx_failed(lambda: c.foo(b"badminton", 0, 10)) + assert_tx_failed(lambda: c.foo(b"badminton", 1, 9)) + assert_tx_failed(lambda: c.foo(b"badminton", 9, 1)) + assert_tx_failed(lambda: c.foo(b"badminton", 10, 0)) print('Passed slice edge case test') diff --git a/tests/parser/globals/test_getters.py b/tests/parser/globals/test_getters.py index 5f18a7b163..12b79df760 100644 --- a/tests/parser/globals/test_getters.py +++ b/tests/parser/globals/test_getters.py @@ -13,7 +13,7 @@ def foo() -> int128: """ c = get_contract_with_gas_estimation_for_constants(state_accessor) - c.oo() + c.oo(transact={}) assert c.foo() == 5 print('Passed basic state accessor test') diff --git a/tests/parser/globals/test_globals.py b/tests/parser/globals/test_globals.py index 99f73a674d..6486cc58c3 100644 --- a/tests/parser/globals/test_globals.py +++ b/tests/parser/globals/test_globals.py @@ -16,7 +16,7 @@ def returnMoose() -> int128: return self.var.a * 10 + self.var.b """ - c = get_contract_with_gas_estimation(permanent_variables_test, args=[5, 7]) + c = get_contract_with_gas_estimation(permanent_variables_test, *[5, 7]) assert c.returnMoose() == 57 print('Passed init argument and variable member test') diff --git a/tests/parser/globals/test_setters.py b/tests/parser/globals/test_setters.py index 0235b37b62..910c8bd235 100644 --- a/tests/parser/globals/test_setters.py +++ b/tests/parser/globals/test_setters.py @@ -59,7 +59,9 @@ def jop() -> int128: c = get_contract_with_gas_estimation(multi_setter_test) assert c.foo() == 321 + c.foo(transact={}) assert c.fop() == 654321 + c.fop(transact={}) assert c.goo() == 321 assert c.gop() == 654321 assert c.hoo() == 0 diff --git a/tests/parser/integration/test_basics.py b/tests/parser/integration/test_basics.py index a890c8d232..1f5db1daa2 100644 --- a/tests/parser/integration/test_basics.py +++ b/tests/parser/integration/test_basics.py @@ -21,7 +21,7 @@ def foo(x: int128) -> int128: print('Passed basic code test') -def test_selfcall_code_3(get_contract_with_gas_estimation, utils): +def test_selfcall_code_3(get_contract_with_gas_estimation, keccak): selfcall_code_3 = """ @public def _hashy2(x: bytes[100]) -> bytes32: @@ -41,7 +41,7 @@ def returnten() -> int128: """ c = get_contract_with_gas_estimation(selfcall_code_3) - assert c.return_hash_of_cow_x_30() == utils.sha3(b'cow' * 30) + assert c.return_hash_of_cow_x_30() == keccak(b'cow' * 30) assert c.returnten() == 10 print("Passed single variable-size argument self-call test") diff --git a/tests/parser/integration/test_crowdfund.py b/tests/parser/integration/test_crowdfund.py index 365497378b..33369fef9c 100644 --- a/tests/parser/integration/test_crowdfund.py +++ b/tests/parser/integration/test_crowdfund.py @@ -1,4 +1,4 @@ -def test_crowdfund(t, chain, get_contract_with_gas_estimation_for_constants): +def test_crowdfund(w3, tester, get_contract_with_gas_estimation_for_constants): crowdfund = """ funders: {sender: address, value: wei_value}[int128] @@ -58,39 +58,39 @@ def refund(): self.refundIndex = ind + 30 """ - - c = get_contract_with_gas_estimation_for_constants(crowdfund, args=[t.a1, 50, 600]) - c.participate(value=5) - assert c.timelimit() == 600 - assert c.deadline() - c.timestamp() == 600 + a0, a1, a2, a3, a4, a5, a6 = w3.eth.accounts[:7] + c = get_contract_with_gas_estimation_for_constants(crowdfund, *[a1, 50, 60]) + c.participate(transact={'value': 5}) + assert c.timelimit() == 60 + assert c.deadline() - c.timestamp() == 59 assert not c.expired() assert not c.reached() - c.participate(value=49) + c.participate(transact={'value': 49}) assert c.reached() - pre_bal = chain.head_state.get_balance(t.a1) - chain.head_state.timestamp += 1000 + pre_bal = w3.eth.getBalance(a1) + w3.testing.mine(100) assert c.expired() - c.finalize() - post_bal = chain.head_state.get_balance(t.a1) + c.finalize(transact={}) + post_bal = w3.eth.getBalance(a1) assert post_bal - pre_bal == 54 - c = get_contract_with_gas_estimation_for_constants(crowdfund, args=[t.a1, 50, 600]) - c.participate(value=1, sender=t.k3) - c.participate(value=2, sender=t.k4) - c.participate(value=3, sender=t.k5) - c.participate(value=4, sender=t.k6) - chain.head_state.timestamp += 1000 + c = get_contract_with_gas_estimation_for_constants(crowdfund, *[a1, 50, 60]) + c.participate(transact={'value': 1, 'from': a3}) + c.participate(transact={'value': 2, 'from': a4}) + c.participate(transact={'value': 3, 'from': a5}) + c.participate(transact={'value': 4, 'from': a6}) + w3.testing.mine(100) assert c.expired() assert not c.reached() - pre_bals = [chain.head_state.get_balance(x) for x in [t.a3, t.a4, t.a5, t.a6]] - c.refund() - post_bals = [chain.head_state.get_balance(x) for x in [t.a3, t.a4, t.a5, t.a6]] + pre_bals = [w3.eth.getBalance(x) for x in [a3, a4, a5, a6]] + c.refund(transact={}) + post_bals = [w3.eth.getBalance(x) for x in [a3, a4, a5, a6]] assert [y - x for x, y in zip(pre_bals, post_bals)] == [1, 2, 3, 4] print('Passed composite crowdfund test') -def test_crowdfund2(t, chain, get_contract_with_gas_estimation_for_constants): +def test_crowdfund2(w3, tester, get_contract_with_gas_estimation_for_constants): crowdfund2 = """ funders: {sender: address, value: wei_value}[int128] @@ -148,34 +148,34 @@ def refund(): self.refundIndex = ind + 30 """ + a0, a1, a2, a3, a4, a5, a6 = w3.eth.accounts[:7] + c = get_contract_with_gas_estimation_for_constants(crowdfund2, *[a1, 50, 60]) - c = get_contract_with_gas_estimation_for_constants(crowdfund2, args=[t.a1, 50, 600]) - - c.participate(value=5) - assert c.timelimit() == 600 - assert c.deadline() - c.timestamp() == 600 + c.participate(transact={'value': 5}) + assert c.timelimit() == 60 + assert c.deadline() - c.timestamp() == 59 assert not c.expired() assert not c.reached() - c.participate(value=49) + c.participate(transact={'value': 49}) assert c.reached() - pre_bal = chain.head_state.get_balance(t.a1) - chain.head_state.timestamp += 1000 + pre_bal = w3.eth.getBalance(a1) + w3.testing.mine(100) assert c.expired() - c.finalize() - post_bal = chain.head_state.get_balance(t.a1) + c.finalize(transact={}) + post_bal = w3.eth.getBalance(a1) assert post_bal - pre_bal == 54 - c = get_contract_with_gas_estimation_for_constants(crowdfund2, args=[t.a1, 50, 600]) - c.participate(value=1, sender=t.k3) - c.participate(value=2, sender=t.k4) - c.participate(value=3, sender=t.k5) - c.participate(value=4, sender=t.k6) - chain.head_state.timestamp += 1000 + c = get_contract_with_gas_estimation_for_constants(crowdfund2, *[a1, 50, 60]) + c.participate(transact={'value': 1, 'from': a3}) + c.participate(transact={'value': 2, 'from': a4}) + c.participate(transact={'value': 3, 'from': a5}) + c.participate(transact={'value': 4, 'from': a6}) + w3.testing.mine(100) assert c.expired() assert not c.reached() - pre_bals = [chain.head_state.get_balance(x) for x in [t.a3, t.a4, t.a5, t.a6]] - c.refund() - post_bals = [chain.head_state.get_balance(x) for x in [t.a3, t.a4, t.a5, t.a6]] + pre_bals = [w3.eth.getBalance(x) for x in [a3, a4, a5, a6]] + c.refund(transact={}) + post_bals = [w3.eth.getBalance(x) for x in [a3, a4, a5, a6]] assert [y - x for x, y in zip(pre_bals, post_bals)] == [1, 2, 3, 4] print('Passed second composite crowdfund test') diff --git a/tests/parser/integration/test_escrow.py b/tests/parser/integration/test_escrow.py index c6d35339e6..7143a88e7c 100644 --- a/tests/parser/integration/test_escrow.py +++ b/tests/parser/integration/test_escrow.py @@ -1,7 +1,7 @@ -from ethereum.tools import tester +# from ethereum.tools import tester -def test_arbitration_code(t, get_contract_with_gas_estimation): +def test_arbitration_code(w3, get_contract_with_gas_estimation, assert_tx_failed): arbitration_code = """ buyer: address seller: address @@ -25,21 +25,16 @@ def refund(): send(self.buyer, self.balance) """ - + a0, a1, a2 = w3.eth.accounts[:3] c = get_contract_with_gas_estimation(arbitration_code, value=1) - c.setup(t.a1, t.a2, sender=t.k0) - try: - c.finalize(sender=t.k1) - success = True - except tester.TransactionFailed: - success = False - assert not success - c.finalize(sender=t.k0) + c.setup(a1, a2, transact={}) + assert_tx_failed(lambda: c.finalize(transact={'from': a1})) + c.finalize(transact={}) print('Passed escrow test') -def test_arbitration_code_with_init(t, get_contract_with_gas_estimation): +def test_arbitration_code_with_init(w3, assert_tx_failed, get_contract_with_gas_estimation): arbitration_code_with_init = """ buyer: address seller: address @@ -63,15 +58,9 @@ def refund(): assert msg.sender == self.seller or msg.sender == self.arbitrator send(self.buyer, self.balance) """ - - c = get_contract_with_gas_estimation(arbitration_code_with_init, - args=[t.a1, t.a2], sender=t.k0, value=1) - try: - c.finalize(sender=t.k1) - success = True - except t.TransactionFailed: - success = False - assert not success - c.finalize(sender=t.k0) + a0, a1, a2 = w3.eth.accounts[:3] + c = get_contract_with_gas_estimation(arbitration_code_with_init, *[a1, a2], value=1) + assert_tx_failed(lambda: c.finalize(transact={'from': a1})) + c.finalize(transact={'from': a0}) print('Passed escrow test with initializer') diff --git a/tests/parser/types/numbers/test_decimals.py b/tests/parser/types/numbers/test_decimals.py index 6ad36df5f6..0b10f22b87 100644 --- a/tests/parser/types/numbers/test_decimals.py +++ b/tests/parser/types/numbers/test_decimals.py @@ -1,4 +1,7 @@ -def test_decimal_test(chain, check_gas, get_contract_with_gas_estimation): +from decimal import Decimal + + +def test_decimal_test(get_contract_with_gas_estimation): decimal_test = """ @public def foo() -> int128: @@ -59,7 +62,7 @@ def foop() -> int128: """ c = get_contract_with_gas_estimation(decimal_test) - pre_txs = len(chain.head_state.receipts) + assert c.foo() == 999 assert c.fop() == 999 assert c.foq() == 999 @@ -74,10 +77,8 @@ def foop() -> int128: assert c.foom() == 999 assert c.foon() == 999 assert c.foop() == 999 - post_txs = len(chain.head_state.receipts) print('Passed basic addition, subtraction and multiplication tests') - check_gas(decimal_test, num_txs=(post_txs - pre_txs)) def test_harder_decimal_test(get_contract_with_gas_estimation): @@ -112,18 +113,18 @@ def iarg() -> wei_value: return x """ c = get_contract_with_gas_estimation(harder_decimal_test) - assert c.phooey(1.2) == 20736.0 - assert c.phooey(-1.2) == 20736.0 - assert c.arg(-3.7) == -3.7 - assert c.arg(3.7) == 3.7 - assert c.garg() == 6.75 - assert c.harg() == 9.0 - assert c.iarg() == 14 + assert c.phooey(Decimal('1.2')) == Decimal('20736.0') + assert c.phooey(Decimal('-1.2')) == Decimal('20736.0') + assert c.arg(Decimal('-3.7')) == Decimal('-3.7') + assert c.arg(Decimal('3.7')) == Decimal('3.7') + assert c.garg() == Decimal('6.75') + assert c.harg() == Decimal('9.0') + assert c.iarg() == Decimal('14') print('Passed fractional multiplication test') -def test_mul_overflow(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_mul_overflow(assert_tx_failed, get_contract_with_gas_estimation): mul_code = """ @public @@ -134,8 +135,7 @@ def _num_mul(x: decimal, y: int128) -> decimal: c = get_contract_with_gas_estimation(mul_code) - t.s = chain - NUM_1 = 85070591730234615865843651857942052864.0 + NUM_1 = Decimal('85070591730234615865843651857942052864.0') NUM_2 = 136112946768375385385349842973 assert_tx_failed(lambda: c._num_mul(NUM_1, NUM_2)) diff --git a/tests/parser/types/numbers/test_int128.py b/tests/parser/types/numbers/test_int128.py index 327dbee17a..f73e0b2860 100644 --- a/tests/parser/types/numbers/test_int128.py +++ b/tests/parser/types/numbers/test_int128.py @@ -1,4 +1,5 @@ from vyper.exceptions import TypeMismatchException +from decimal import Decimal def test_exponents_with_nums(get_contract_with_gas_estimation): @@ -25,9 +26,9 @@ def foo(inp: int128) -> decimal: return y """ c = get_contract_with_gas_estimation(code) - assert c.foo(2) == 2.5 - assert c.foo(10) == .5 - assert c.foo(50) == .1 + assert c.foo(2) == Decimal('2.5') + assert c.foo(10) == Decimal('.5') + assert c.foo(50) == Decimal('0.1') def test_decimal_divided_by_num(get_contract_with_gas_estimation): @@ -38,12 +39,12 @@ def foo(inp: decimal) -> decimal: return y """ c = get_contract_with_gas_estimation(code) - assert c.foo(1) == .2 - assert c.foo(.5) == .1 - assert c.foo(.2) == .04 + assert c.foo(Decimal('1')) == Decimal('0.2') + assert c.foo(Decimal('.5')) == Decimal('0.1') + assert c.foo(Decimal('.2')) == Decimal('.04') -def test_negative_nums(t, get_contract_with_gas_estimation, chain): +def test_negative_nums(get_contract_with_gas_estimation): negative_nums_code = """ @public def _negative_num() -> int128: @@ -55,7 +56,6 @@ def _negative_exp() -> int128: """ c = get_contract_with_gas_estimation(negative_nums_code) - t.s = chain assert c._negative_num() == -1 assert c._negative_exp() == -3 @@ -76,7 +76,7 @@ def foo() -> int128(wei): assert c.foo() == 4 -def test_num_bound(t, assert_tx_failed, get_contract_with_gas_estimation, chain): +def test_num_bound(assert_tx_failed, get_contract_with_gas_estimation): num_bound_code = """ @public def _num(x: int128) -> int128: @@ -105,7 +105,6 @@ def _num_min() -> int128: c = get_contract_with_gas_estimation(num_bound_code) - t.s = chain NUM_MAX = 2**127 - 1 NUM_MIN = -2**127 assert c._num_add(NUM_MAX, 0) == NUM_MAX diff --git a/tests/parser/types/numbers/test_uint256.py b/tests/parser/types/numbers/test_uint256.py index 063d3e029a..3e364993f9 100644 --- a/tests/parser/types/numbers/test_uint256.py +++ b/tests/parser/types/numbers/test_uint256.py @@ -1,7 +1,7 @@ -from ethereum.abi import ValueOutOfBounds +# from ethereum.abi import ValueOutOfBounds -def test_uint256_code(t, chain, assert_tx_failed, get_contract_with_gas_estimation): +def test_uint256_code(assert_tx_failed, get_contract_with_gas_estimation): uint256_code = """ @public def _uint256_add(x: uint256, y: uint256) -> uint256: @@ -40,7 +40,6 @@ def _uint256_le(x: uint256, y: uint256) -> bool: x = 126416208461208640982146408124 y = 7128468721412412459 - t.s = chain uint256_MAX = 2 ** 256 - 1 # Max possible uint256 value assert c._uint256_add(x, y) == x + y assert c._uint256_add(0, y) == y @@ -73,7 +72,7 @@ def _uint256_le(x: uint256, y: uint256) -> bool: print("Passed uint256 operation tests") -def test_uint256_mod(t, chain, assert_tx_failed, get_contract_with_gas_estimation): +def test_uint256_mod(assert_tx_failed, get_contract_with_gas_estimation): uint256_code = """ @public def _uint256_mod(x: uint256, y: uint256) -> uint256: @@ -89,7 +88,6 @@ def _uint256_mulmod(x: uint256, y: uint256, z: uint256) -> uint256: """ c = get_contract_with_gas_estimation(uint256_code) - t.s = chain assert c._uint256_mod(3, 2) == 1 assert c._uint256_mod(34, 32) == 2 @@ -106,7 +104,7 @@ def _uint256_mulmod(x: uint256, y: uint256, z: uint256) -> uint256: assert_tx_failed(lambda: c._uint256_mulmod(2, 2, 0)) -def test_uint256_with_exponents(t, chain, assert_tx_failed, get_contract_with_gas_estimation): +def test_uint256_with_exponents(assert_tx_failed, get_contract_with_gas_estimation): exp_code = """ @public def _uint256_exp(x: uint256, y: uint256) -> uint256: @@ -114,7 +112,6 @@ def _uint256_exp(x: uint256, y: uint256) -> uint256: """ c = get_contract_with_gas_estimation(exp_code) - t.s = chain assert c._uint256_exp(2, 0) == 1 assert c._uint256_exp(2, 1) == 2 @@ -124,7 +121,7 @@ def _uint256_exp(x: uint256, y: uint256) -> uint256: assert c._uint256_exp(7**23, 3) == 7**69 -def test_uint256_to_num_casting(t, chain, assert_tx_failed, get_contract_with_gas_estimation): +def test_uint256_to_num_casting(assert_tx_failed, get_contract_with_gas_estimation): code = """ @public def _uint256_to_num(x: int128(uint256)) -> int128: @@ -142,11 +139,10 @@ def built_in_conversion(x: uint256) -> int128: c = get_contract_with_gas_estimation(code) # Ensure uint256 function signature. - assert c.translator.function_data['_uint256_to_num']['encode_types'] == ['uint256'] + assert c._classic_contract.functions.abi[0]['inputs'][0]['type'] == 'uint256' assert c._uint256_to_num(1) == 1 assert c._uint256_to_num((2**127) - 1) == 2**127 - 1 - t.s = chain assert_tx_failed(lambda: c._uint256_to_num((2**128)) == 0) assert c._uint256_to_num_call(1) == 1 @@ -154,7 +150,7 @@ def built_in_conversion(x: uint256) -> int128: assert c._uint256_to_num_call(2**127 - 1) == c.built_in_conversion(2**127 - 1) # Pass in negative int. - assert_tx_failed(lambda: c._uint256_to_num(-1) != -1, ValueOutOfBounds) + # assert_tx_failed(lambda: c._uint256_to_num(-1) != -1, ValueOutOfBounds) # Make sure it can't be coherced into a negative number. assert_tx_failed(lambda: c._uint256_to_num_call(2**127)) diff --git a/tests/parser/types/test_bytes.py b/tests/parser/types/test_bytes.py index 7f50a7089a..aa983d91fa 100644 --- a/tests/parser/types/test_bytes.py +++ b/tests/parser/types/test_bytes.py @@ -1,9 +1,10 @@ -import pytest -from ethereum.tools import tester -from vyper.exceptions import ParserException, TypeMismatchException +from vyper.exceptions import ( + ParserException, + TypeMismatchException +) -def test_test_bytes(get_contract_with_gas_estimation): +def test_test_bytes(get_contract_with_gas_estimation, assert_tx_failed): test_bytes = """ @public def foo(x: bytes[100]) -> bytes[100]: @@ -21,8 +22,7 @@ def foo(x: bytes[100]) -> bytes[100]: print('Passed max-length bytes test') # test for greater than 100 bytes, should raise exception - with pytest.raises(tester.TransactionFailed): - c.foo(b'\x35' * 101) + assert_tx_failed(lambda: c.foo(b'\x35' * 101)) print('Passed input-too-long test') @@ -80,16 +80,16 @@ def get_xy() -> int128: """ c = get_contract_with_gas_estimation(test_bytes3) - c.set_maa(b"pig") + c.set_maa(b"pig", transact={}) assert c.get_maa() == b"pig" assert c.get_maa2() == b"pig" - c.set_maa2(b"") + c.set_maa2(b"", transact={}) assert c.get_maa() == b"" assert c.get_maa2() == b"" - c.set_maa(b"\x44" * 60) + c.set_maa(b"\x44" * 60, transact={}) assert c.get_maa() == b"\x44" * 60 assert c.get_maa2() == b"\x44" * 60 - c.set_maa2(b"mongoose") + c.set_maa2(b"mongoose", transact={}) assert c.get_maa() == b"mongoose" assert c.get_xy() == 999 @@ -113,8 +113,8 @@ def bar(inp: bytes[60]) -> bytes[60]: """ c = get_contract_with_gas_estimation(test_bytes4) - assert c.foo() == b"", c.foo() - assert c.bar() == b"" + assert c.foo(b"") == b"", c.foo() + assert c.bar(b"") == b"" print('Passed string deleting test') @@ -152,12 +152,12 @@ def quz(inp1: bytes[40], inp2: bytes[45]): """ c = get_contract_with_gas_estimation(test_bytes5) - c.foo(b"cow", b"horse") + c.foo(b"cow", b"horse", transact={}) assert c.check1() == b"cow" assert c.check2() == b"horse" assert c.bar(b"pig", b"moose") == b"pig" assert c.bat(b"pig", b"moose") == b"moose" - c.quz(b"badminton", b"fluffysheep") + c.quz(b"badminton", b"fluffysheep", transact={}) assert c.check1() == b"badminton" assert c.check2() == b"fluffysheep" @@ -217,12 +217,12 @@ def testsome_storage(y: bytes[1]) -> bool: c = get_contract_with_gas_estimation(bytes_to_num_code) assert c.getsome() == b'\x0e' - assert c.testsome('a') - assert c.testsome('\x61') + assert c.testsome(b'a') + assert c.testsome(b'\x61') assert c.testsome(0b1100001.to_bytes(1, 'big')) - assert not c.testsome('b') - assert c.testsome_storage('a') - assert not c.testsome_storage('x') + assert not c.testsome(b'b') + assert c.testsome_storage(b'a') + assert not c.testsome_storage(b'x') def test_bytes_comparison_fail_size_mismatch(assert_compile_failed, get_contract_with_gas_estimation): diff --git a/vyper/compiler.py b/vyper/compiler.py index 1e120671c5..9ff9aa67dd 100644 --- a/vyper/compiler.py +++ b/vyper/compiler.py @@ -34,16 +34,3 @@ def mk_full_signature(code, *args, **kwargs): if func_name in gas_estimates and func_name != '__init__': abi[idx]['gas'] = gas_estimates[func_name] return abi - - -# Dummy object, as some tools expect this interface -class Compiler(object): - - def compile(self, code, *args, **kwargs): - return compile(code, *args, **kwargs) - - def mk_full_signature(self, code, *args, **kwargs): - return mk_full_signature(code, *args, **kwargs) - - def gas_estimate(self, code, *args, **kwargs): - return gas_estimate(code, *args, **kwargs) # pragma: no test diff --git a/vyper/opcodes.py b/vyper/opcodes.py index 5b173d7e06..1e6cebfa5d 100644 --- a/vyper/opcodes.py +++ b/vyper/opcodes.py @@ -47,7 +47,7 @@ 'MSTORE': [0x52, 2, 0, 3], 'MSTORE8': [0x53, 2, 0, 3], 'SLOAD': [0x54, 1, 1, 200], - 'SSTORE': [0x55, 2, 0, 5000], + 'SSTORE': [0x55, 2, 0, 20000], 'JUMP': [0x56, 1, 0, 8], 'JUMPI': [0x57, 2, 0, 10], 'PC': [0x58, 0, 1, 2], diff --git a/vyper/parser/expr.py b/vyper/parser/expr.py index c19bd364b8..99e81ee3c5 100644 --- a/vyper/parser/expr.py +++ b/vyper/parser/expr.py @@ -175,10 +175,12 @@ def attribute(self): if not is_base_type(addr.typ, 'address'): raise TypeMismatchException("Type mismatch: codesize keyword expects an address as input", self.expr) if self.expr.attr == 'codesize': + eval_code = ['extcodesize', addr] output_type = 'int128' else: + eval_code = ['gt', ['extcodesize', addr], 0] output_type = 'bool' - return LLLnode.from_list(['extcodesize', addr], typ=BaseType(output_type), location=None, pos=getpos(self.expr)) + return LLLnode.from_list(eval_code, typ=BaseType(output_type), location=None, pos=getpos(self.expr)) # self.x: global attribute elif isinstance(self.expr.value, ast.Name) and self.expr.value.id == "self": if self.expr.attr not in self.context.globals: diff --git a/vyper/parser/parser.py b/vyper/parser/parser.py index ae9bdbb4ac..3ac0c35b8b 100644 --- a/vyper/parser/parser.py +++ b/vyper/parser/parser.py @@ -730,9 +730,8 @@ def pack_logging_topics(event_id, args, expected_topics, context, pos): return topics -def pack_args_by_32( - holder, maxlen, arg, typ, context, placeholder, *, - pos, dynamic_offset_counter=None, datamem_start=None): +def pack_args_by_32(holder, maxlen, arg, typ, context, placeholder, + dynamic_offset_counter=None, datamem_start=None, zero_pad_i=None, pos=None): """ Copy necessary variables to pre-allocated memory section. @@ -772,6 +771,17 @@ def pack_args_by_32( typ=typ, location='memory', annotation="pack_args_by_32:dest_placeholder") copier = make_byte_array_copier(dest_placeholder, source_expr.lll_node) holder.append(copier) + # Add zero padding. + new_maxlen = ceil32(source_expr.lll_node.typ.maxlen) + + holder.append( + ['with', '_bytearray_loc', dest_placeholder, + ['seq', + ['repeat', zero_pad_i, ['mload', '_bytearray_loc'], new_maxlen, + ['seq', + ['if', ['ge', ['mload', zero_pad_i], new_maxlen], 'break'], # stay within allocated bounds + ['mstore8', ['add', ['add', '_bytearray_loc', 32], ['mload', zero_pad_i]], 0]]]]] + ) # Increment offset counter. increment_counter = LLLnode.from_list( ['mstore', dynamic_offset_counter, @@ -824,12 +834,15 @@ def pack_logging_data(expected_data, args, context, pos): return ['seq'], 0, None, 0 holder = ['seq'] maxlen = len(args) * 32 # total size of all packed args (upper limit) + requires_dynamic_offset = any([isinstance(data.typ, ByteArrayType) for data in expected_data]) if requires_dynamic_offset: + zero_pad_i = context.new_placeholder(BaseType('uint256')) # Iterator used to zero pad memory. dynamic_offset_counter = context.new_placeholder(BaseType(32)) dynamic_placeholder = context.new_placeholder(BaseType(32)) else: dynamic_offset_counter = None + zero_pad_i = None # Populate static placeholders. placeholder_map = {} @@ -838,7 +851,7 @@ def pack_logging_data(expected_data, args, context, pos): placeholder = context.new_placeholder(BaseType(32)) placeholder_map[i] = placeholder if not isinstance(typ, ByteArrayType): - holder, maxlen = pack_args_by_32(holder, maxlen, arg, typ, context, placeholder, pos=pos) + holder, maxlen = pack_args_by_32(holder, maxlen, arg, typ, context, placeholder, zero_pad_i=zero_pad_i, pos=pos) # Dynamic position starts right after the static args. if requires_dynamic_offset: @@ -868,6 +881,7 @@ def pack_logging_data(expected_data, args, context, pos): placeholder=placeholder_map[i], datamem_start=datamem_start, dynamic_offset_counter=dynamic_offset_counter, + zero_pad_i=zero_pad_i, pos=pos ) diff --git a/vyper/parser/parser_utils.py b/vyper/parser/parser_utils.py index 018f0f516f..4ce3a565bc 100644 --- a/vyper/parser/parser_utils.py +++ b/vyper/parser/parser_utils.py @@ -306,7 +306,7 @@ def make_byte_slice_copier(destination, source, length, max_length): if source.location == "memory" and destination.location == "memory": return LLLnode.from_list(['with', '_l', max_length, ['pop', ['call', 18 + max_length // 10, 4, 0, source, - '_l', destination, '_l']]], typ=None, annotation='copy byte slice') + '_l', destination, '_l']]], typ=None, annotation='copy byte slice dest: %s' % str(destination)) # Copy over data if isinstance(source.typ, NullType): loader = 0 diff --git a/vyper/parser/stmt.py b/vyper/parser/stmt.py index 0c3a6d9d88..46d6223cb4 100644 --- a/vyper/parser/stmt.py +++ b/vyper/parser/stmt.py @@ -413,23 +413,42 @@ def parse_return(self): if sub.typ.maxlen > self.context.return_type.maxlen: raise TypeMismatchException("Cannot cast from greater max-length %d to shorter max-length %d" % (sub.typ.maxlen, self.context.return_type.maxlen), self.stmt.value) + + zero_padder = LLLnode.from_list(['pass']) + if sub.typ.maxlen > 0: + zero_pad_i = self.context.new_placeholder(BaseType('uint256')) # Iterator used to zero pad memory. + zero_padder = LLLnode.from_list( + ['repeat', zero_pad_i, ['mload', '_loc'], sub.typ.maxlen, + ['seq', + ['if', ['gt', ['mload', zero_pad_i], sub.typ.maxlen], 'break'], # stay within allocated bounds + ['mstore8', ['add', ['add', 32, '_loc'], ['mload', zero_pad_i]], 0]]], + annotation="Zero pad" + ) + # Returning something already in memory if sub.location == 'memory': - return LLLnode.from_list(['with', '_loc', sub, - ['seq', - ['mstore', ['sub', '_loc', 32], 32], - ['return', ['sub', '_loc', 32], ['ceil32', ['add', ['mload', '_loc'], 64]]]]], typ=None, pos=getpos(self.stmt)) + return LLLnode.from_list( + ['with', '_loc', sub, + ['seq', + ['mstore', ['sub', '_loc', 32], 32], + zero_padder, + ['return', ['sub', '_loc', 32], ['ceil32', ['add', ['mload', '_loc'], 64]]]]], typ=None, pos=getpos(self.stmt)) + # Copying from storage elif sub.location == 'storage': # Instantiate a byte array at some index fake_byte_array = LLLnode(self.context.get_next_mem() + 32, typ=sub.typ, location='memory', pos=getpos(self.stmt)) - o = ['seq', + o = [ + 'with', '_loc', self.context.get_next_mem() + 32, + ['seq', # Copy the data to this byte array make_byte_array_copier(fake_byte_array, sub), # Store the number 32 before it for ABI formatting purposes ['mstore', self.context.get_next_mem(), 32], + zero_padder, # Return it ['return', self.context.get_next_mem(), ['add', ['ceil32', ['mload', self.context.get_next_mem() + 32]], 64]]] + ] return LLLnode.from_list(o, typ=None, pos=getpos(self.stmt)) else: raise Exception("Invalid location: %s" % sub.location) diff --git a/vyper/types/types.py b/vyper/types/types.py index 429cece357..52331a53a8 100644 --- a/vyper/types/types.py +++ b/vyper/types/types.py @@ -167,7 +167,7 @@ def canonicalize_type(t, is_indexed=False): elif t == 'int128' and uint256_override: return 'uint256' elif t == 'decimal': - return 'decimal10' + return 'fixed168x10' elif t == 'bool': return 'bool' elif t == 'uint256':