Skip to content
This repository was archived by the owner on Nov 15, 2021. It is now read-only.

Gracefully handle NEP-5 balance query failures #744

Merged
merged 2 commits into from
Dec 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ All notable changes to this project are documented in this file.
- Fix unnecessary default bootstrap warning for mainnet showing.
- Add GET and OPTIONS request functionality for JSON-RPC servers
- Fix ``gzip`` failure in current implementation of ExtendedJsonRpcApi
- Gracefully handle balance query failures of NEP-5 tokens.


[0.8.2] 2018-10-31
Expand Down
10 changes: 5 additions & 5 deletions neo/Prompt/Commands/Invoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def TestInvokeContract(wallet, args, withdrawal_tx=None,
for index, iarg in enumerate(contract.Code.ParameterList):
param, abort = gather_param(index, iarg)
if abort:
return None, None, None, None
return None, None, None, None, False
params.append(param)
params.reverse()

Expand Down Expand Up @@ -225,7 +225,7 @@ def TestInvokeContract(wallet, args, withdrawal_tx=None,

print("Contract %s not found" % args[0])

return None, None, None, None
return None, None, None, None, False


def make_unique_script_attr(attributes):
Expand Down Expand Up @@ -368,18 +368,18 @@ def test_invoke(script, wallet, outputs, withdrawal_tx=None,
wallet_tx.outputs = outputs
wallet_tx.Attributes = [] if invoke_attrs is None else deepcopy(invoke_attrs)

return wallet_tx, net_fee, engine.ResultStack.Items, engine.ops_processed
return wallet_tx, net_fee, engine.ResultStack.Items, engine.ops_processed, success

# this allows you to to test invocations that fail
else:
wallet_tx.outputs = outputs
wallet_tx.Attributes = [] if invoke_attrs is None else deepcopy(invoke_attrs)
return wallet_tx, min_fee, [], engine.ops_processed
return wallet_tx, min_fee, [], engine.ops_processed, success

except Exception as e:
service.ExecutionCompleted(engine, False, e)

return None, None, None, None
return None, None, None, None, False


def test_deploy_and_invoke(deploy_script, invoke_args, wallet,
Expand Down
44 changes: 24 additions & 20 deletions neo/Wallets/NEP5Token.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,20 +133,24 @@ def GetBalance(self, wallet, address, as_string=False):
sb = ScriptBuilder()
sb.EmitAppCallWithOperationAndArgs(self.ScriptHash, 'balanceOf', [addr])

tx, fee, results, num_ops = test_invoke(sb.ToArray(), wallet, [])

try:
val = results[0].GetBigInteger()
precision_divisor = pow(10, self.decimals)
balance = Decimal(val) / Decimal(precision_divisor)
if as_string:
formatter_str = '.%sf' % self.decimals
balance_str = format(balance, formatter_str)
return balance_str
return balance
except Exception as e:
logger.error("could not get balance: %s " % e)
traceback.print_stack()
tx, fee, results, num_ops, engine_success = test_invoke(sb.ToArray(), wallet, [])
if engine_success:
try:
val = results[0].GetBigInteger()
precision_divisor = pow(10, self.decimals)
balance = Decimal(val) / Decimal(precision_divisor)
if as_string:
formatter_str = '.%sf' % self.decimals
balance_str = format(balance, formatter_str)
return balance_str
return balance
except Exception as e:
logger.error("could not get balance: %s " % e)
traceback.print_stack()
else:
addr_str = Crypto.ToAddress(UInt160(data=addr))
logger.error(
f"Could not get balance of address {addr_str} for token contract {self.ScriptHash}. VM execution failed. Make sure the contract exists on the network and that it adheres to the NEP-5 standard")

return 0

Expand Down Expand Up @@ -175,7 +179,7 @@ def Transfer(self, wallet, from_addr, to_addr, amount, tx_attributes=None):
[parse_param(from_addr, wallet), parse_param(to_addr, wallet),
parse_param(amount)])

tx, fee, results, num_ops = test_invoke(sb.ToArray(), wallet, [], from_addr=from_addr, invoke_attrs=tx_attributes)
tx, fee, results, num_ops, engine_success = test_invoke(sb.ToArray(), wallet, [], from_addr=from_addr, invoke_attrs=tx_attributes)

return tx, fee, results

Expand All @@ -199,7 +203,7 @@ def TransferFrom(self, wallet, from_addr, to_addr, amount):
invoke_args = [self.ScriptHash.ToString(), 'transferFrom',
[parse_param(from_addr, wallet), parse_param(to_addr, wallet), parse_param(amount)]]

tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args, None, True)
tx, fee, results, num_ops, engine_success = TestInvokeContract(wallet, invoke_args, None, True)

return tx, fee, results

Expand All @@ -221,7 +225,7 @@ def Allowance(self, wallet, owner_addr, requestor_addr):
invoke_args = [self.ScriptHash.ToString(), 'allowance',
[parse_param(owner_addr, wallet), parse_param(requestor_addr, wallet)]]

tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args, None, True)
tx, fee, results, num_ops, engine_success = TestInvokeContract(wallet, invoke_args, None, True)

return tx, fee, results

Expand All @@ -244,7 +248,7 @@ def Approve(self, wallet, owner_addr, requestor_addr, amount):
invoke_args = [self.ScriptHash.ToString(), 'approve',
[parse_param(owner_addr, wallet), parse_param(requestor_addr, wallet), parse_param(amount)]]

tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args, None, True)
tx, fee, results, num_ops, engine_success = TestInvokeContract(wallet, invoke_args, None, True)

return tx, fee, results

Expand All @@ -267,7 +271,7 @@ def Mint(self, wallet, mint_to_addr, attachment_args, invoke_attrs=None):

invoke_args = invoke_args + attachment_args

tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args, None, True, from_addr=mint_to_addr, invoke_attrs=invoke_attrs)
tx, fee, results, num_ops, engine_success = TestInvokeContract(wallet, invoke_args, None, True, from_addr=mint_to_addr, invoke_attrs=invoke_attrs)

return tx, fee, results

Expand All @@ -288,7 +292,7 @@ def CrowdsaleRegister(self, wallet, register_addresses, from_addr=None):
invoke_args = [self.ScriptHash.ToString(), 'crowdsale_register',
[parse_param(p, wallet) for p in register_addresses]]

tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args, None, True, from_addr)
tx, fee, results, num_ops, engine_success = TestInvokeContract(wallet, invoke_args, None, True, from_addr)

return tx, fee, results

Expand Down
4 changes: 2 additions & 2 deletions neo/bin/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ def test_invoke_contract(self, args):
args, invoke_attrs = get_tx_attr_from_args(args)
args, owners = get_owners_from_params(args)
if args and len(args) > 0:
tx, fee, results, num_ops = TestInvokeContract(self.Wallet, args, from_addr=from_addr, invoke_attrs=invoke_attrs, owners=owners)
tx, fee, results, num_ops, engine_success = TestInvokeContract(self.Wallet, args, from_addr=from_addr, invoke_attrs=invoke_attrs, owners=owners)

if tx is not None and results is not None:

Expand Down Expand Up @@ -787,7 +787,7 @@ def load_smart_contract(self, args):

if contract_script is not None:

tx, fee, results, num_ops = test_invoke(contract_script, self.Wallet, [], from_addr=from_addr)
tx, fee, results, num_ops, engine_success = test_invoke(contract_script, self.Wallet, [], from_addr=from_addr)

if tx is not None and results is not None:
print(
Expand Down