def test_call_passes_return_code(vm): transaction = UnsignedUserAccountTransaction(**merge( DEFAULT_TX_PARAMS, { "nonce": get_nonce(vm), "destination": NOOP_CONTRACT_ADDRESS, "access_list": DEFAULT_TX_PARAMS["access_list"] + [[NOOP_CONTRACT_ADDRESS]], })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) assert computation.is_success assert big_endian_to_int(computation.output) == 1 # success transaction = UnsignedUserAccountTransaction(**merge( DEFAULT_TX_PARAMS, { "nonce": get_nonce(vm), "destination": FAILING_CONTRACT_ADDRESS, "access_list": DEFAULT_TX_PARAMS["access_list"] + [[FAILING_CONTRACT_ADDRESS]], })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) assert computation.is_success assert big_endian_to_int(computation.output) == 0 # failure
def test_call_transfers_value(vm): vm_state = vm.state with vm_state.state_db() as state_db: balance_sender_before = state_db.get_balance(ACCOUNT_ADDRESS) balance_destination_before = state_db.get_balance(DESTINATION_ADDRESS) # Update state_root manually vm.block.header.state_root = vm_state.state_root transaction = UnsignedUserAccountTransaction( **merge(DEFAULT_TX_PARAMS, { "nonce": get_nonce(vm), "value": 10 })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) assert computation.is_success vm_state = vm.state with vm_state.state_db() as state_db: balance_sender_after = state_db.get_balance(ACCOUNT_ADDRESS) balance_destination_after = state_db.get_balance(DESTINATION_ADDRESS) # Update state_root manually vm.block.header.state_root = vm_state.state_root assert balance_sender_after == balance_sender_before - 10 assert balance_destination_after == balance_destination_before + 10
def test_call_does_not_revert_nonce(vm): nonce_before = get_nonce(vm) transaction = UnsignedUserAccountTransaction(**merge(DEFAULT_TX_PARAMS, { "nonce": nonce_before, "destination": FAILING_CONTRACT_ADDRESS, "access_list": DEFAULT_TX_PARAMS["access_list"] + [[FAILING_CONTRACT_ADDRESS]], })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) assert computation.is_success assert get_nonce(vm) == nonce_before + 1
def test_no_call_if_not_enough_gas(vm): transaction = UnsignedUserAccountTransaction(**merge(DEFAULT_TX_PARAMS, { "nonce": get_nonce(vm), "destination": NOOP_CONTRACT_ADDRESS, "gas": 80000, "access_list": DEFAULT_TX_PARAMS["access_list"] + [[NOOP_CONTRACT_ADDRESS]], })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) assert computation.is_error # a little remains, but not enough to make the call assert computation.get_gas_remaining() > 0
def test_call_increments_nonce(vm): computation, _ = vm.apply_transaction(SIGNED_DEFAULT_TRANSACTION) assert computation.is_success assert get_nonce(vm) == 1 transaction = UnsignedUserAccountTransaction(**merge(DEFAULT_TX_PARAMS, { "nonce": 1, })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) assert computation.is_success assert get_nonce(vm) == 2
def test_call_checks_nonce(vm): computation, _ = vm.apply_transaction(SIGNED_DEFAULT_TRANSACTION) assert computation.is_success computation, _ = vm.apply_transaction(SIGNED_DEFAULT_TRANSACTION) assert computation.is_error transaction = UnsignedUserAccountTransaction(**merge(DEFAULT_TX_PARAMS, { "nonce": 2, })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) assert computation.is_error
def test_call_uses_data(vm, data, hash): transaction = UnsignedUserAccountTransaction(**merge(DEFAULT_TX_PARAMS, { "nonce": get_nonce(vm), "destination": DATA_LOGGING_CONTRACT_ADDRESS, "msg_data": data, "access_list": DEFAULT_TX_PARAMS["access_list"] + [[DATA_LOGGING_CONTRACT_ADDRESS]], })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) assert computation.is_success logs = computation.get_log_entries() assert len(logs) == 1 logged_hash = logs[0][-1] assert logged_hash == hash
def test_call_uses_remaining_gas(vm): transaction = UnsignedUserAccountTransaction(**merge(DEFAULT_TX_PARAMS, { "nonce": get_nonce(vm), "destination": GAS_LOGGING_CONTRACT_ADDRESS, "gas": 1 * 1000 * 1000, "access_list": DEFAULT_TX_PARAMS["access_list"] + [[GAS_LOGGING_CONTRACT_ADDRESS]], })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) assert computation.is_success logs = computation.get_log_entries() assert len(logs) == 1 logged_gas = big_endian_to_int(logs[0][-1]) assert logged_gas > 900 * 1000 # some gas will have been consumed earlier
def test_call_checks_block_range(vm, min_block, max_block, valid): assert vm.block.number == 10 transaction = UnsignedUserAccountTransaction(**merge(DEFAULT_TX_PARAMS, { "nonce": get_nonce(vm), "min_block": min_block, "max_block": max_block, })).as_signed_transaction(PRIVATE_KEY) computation, _ = vm.apply_transaction(transaction) if valid: assert computation.is_success else: assert computation.is_error
def test_validation(key, value): # construct object with valid parameters, apply invalid values afterwards # this ensures object creation succeeds tx = UnsignedUserAccountTransaction(**VALID_PARAMS) with pytest.raises(ValidationError): setattr(tx, key, value) tx.validate() tx = UserAccountTransaction(**merge(VALID_PARAMS, { "v": 27, "r": 1, "s": 1 })) with pytest.raises(ValidationError): setattr(tx, key, value) tx.validate()
def unsigned_transaction(): return UnsignedUserAccountTransaction(**VALID_PARAMS)
"max_block": UINT_256_MAX, "nonce": 0, "msg_data": b"", "access_list": DEFAULT_BASE_TX_PARAMS["access_list"] + [ [DESTINATION_ADDRESS], ], "gas_price": 0, }) SIGNED_DEFAULT_TRANSACTION = UnsignedUserAccountTransaction( **merge(DEFAULT_TX_PARAMS, { "nonce": 0, })).as_signed_transaction(PRIVATE_KEY) DEFAULT_V = SIGNED_DEFAULT_TRANSACTION.v DEFAULT_R = SIGNED_DEFAULT_TRANSACTION.r DEFAULT_S = SIGNED_DEFAULT_TRANSACTION.s @pytest.fixture def vm(): header = CollationHeader( shard_id=0, expected_period_number=2, period_start_prevhash=decode_hex( "3c4cc7b99c7eb9281e9a8d15cd4b2f98c5df085e929f15388c699b41cdde78d7" ), parent_hash=ZERO_HASH32,