def token_send_blog(wallet, args): if len(args) != 4: print( "please provide a token symbol, from address, to address, and amount sb" ) return False contract = args[0] send_from = args[1] send_to = args[2] amount = 0 # allowance = token_get_allowance(wallet, args[:-1], verbose=False) if True: invoke_args = [ contract, 'output', [ parse_param(send_from, wallet), parse_param(send_to, wallet), parse_param(amount) ] ] print(invoke_args) tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args, None, True, send_from) if tx is not None and results is not None and len(results) > 0: if results[0].GetBigInteger() == 1: return InvokeContract(wallet, tx, fee) return False
def Transfer(self, wallet, from_addr, to_addr, amount, tx_attributes=None): """ Transfer a specified amount of the NEP5Token to another address. Args: wallet (neo.Wallets.Wallet): a wallet instance. from_addr (str): public address of the account to transfer the given amount from. to_addr (str): public address of the account to transfer the given amount to. amount (int): quantity to send. tx_attributes (list): a list of TransactionAtribute objects. Returns: tuple: InvocationTransaction: the transaction. int: the transaction fee. list: the neo VM evaluationstack results. """ if not tx_attributes: tx_attributes = [] sb = ScriptBuilder() sb.EmitAppCallWithOperationAndArgs(self.ScriptHash, 'transfer', [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) return tx, fee, results
def GetBalance(self, wallet, address, as_string=False): if type(address) is UInt160: address = Crypto.ToAddress(address) invoke_args = [ self.ScriptHash.ToString(), parse_param('balanceOf'), [parse_param(address)] ] tx, fee, balanceResults, num_ops = TestInvokeContract( wallet, invoke_args, None, False) try: val = balanceResults[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() return 0
def LoadContract(args): if len(args) < 5: print( "please specify contract to load like such: 'import contract {path} {params} {return_type} {needs_storage} {needs_dynamic_invoke}'" ) return path = args[0] params = parse_param(args[1], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') return_type = BigInteger(ContractParameterType.FromString(args[2]).value) needs_storage = bool(parse_param(args[3])) needs_dynamic_invoke = bool(parse_param(args[4])) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke script = None if '.py' in path: print("Please load a compiled .avm file") return False with open(path, 'rb') as f: content = f.read() try: content = binascii.unhexlify(content) except Exception as e: pass script = content if script is not None: plist = params try: plist = bytearray(binascii.unhexlify(params)) except Exception as e: plist = bytearray(b'\x10') function_code = FunctionCode(script=script, param_list=bytearray(plist), return_type=return_type, contract_properties=contract_properties) return function_code print("error loading contract for path %s" % path) return None
def GatherLoadedContractParams(args, script): if len(args) < 4: raise Exception( "please specify contract properties like {params} {return_type} {needs_storage} {needs_dynamic_invoke}" ) params = parse_param(args[0], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') return_type = BigInteger(ContractParameterType.FromString(args[1]).value) needs_storage = bool(parse_param(args[2])) needs_dynamic_invoke = bool(parse_param(args[3])) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke out = generate_deploy_script(script, contract_properties=contract_properties, return_type=return_type, parameter_list=params) return out
def test_NFT_3_mint(self): output = Compiler.instance().load('nft_template.py').default out = output.write() TestContract.dispatched_events = [] # mint another token owner = bytearray(TOKEN_CONTRACT_OWNER) tx, results, total_ops, engine = TestBuild(out, ['mintToken', parse_param([owner,2,'token2ROData','https://example.com/images/2.png','token2ROData'])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), True) # it should dispatch an event self.assertEqual(len(TestContract.dispatched_events), 8) evt = TestContract.dispatched_events[0] self.assertIsInstance(evt, NotifyEvent) self.assertEqual(evt.addr_to, self.wallet_1_script_hash) # now the total circulation should be bigger tx, results, total_ops, engine = TestBuild(out, ['totalSupply', '[]'], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 2) # trying to mint a token with an existing token ID should fail owner = bytearray(TOKEN_CONTRACT_OWNER) tx, results, total_ops, engine = TestBuild(out, ['mintToken', parse_param([owner,2,'token2ROData','https://example.com/images/2.png','token2ROData'])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 0)
def test_NFT_1(self): output = Compiler.instance().load('nft_template.py').default out = output.write() tx, results, total_ops, engine = TestBuild(out, ['name', '[]'], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString(), TOKEN_NAME) tx, results, total_ops, engine = TestBuild(out, ['symbol', '[]'], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString(), TOKEN_SYMBOL) tx, results, total_ops, engine = TestBuild(out, ['decimals', '[]'], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), TOKEN_DECIMALS) tx, results, total_ops, engine = TestBuild(out, ['nonexistentmethod', '[]'], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 0) # mint a token owner = bytearray(TOKEN_CONTRACT_OWNER) tx, results, total_ops, engine = TestBuild(out, ['mintToken', parse_param([owner,1,'token1ROData','https://example.com/images/1.png','token1ROData'])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), True) # now circulation should be equal to 1 tx, results, total_ops, engine = TestBuild(out, ['totalSupply', '[]'], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 1) # now the owner should have a balance of 1 tx, results, total_ops, engine = TestBuild(out, ['balanceOf', parse_param([bytearray(TOKEN_CONTRACT_OWNER)])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 1)
def Query(self, wallet): if self.name is not None: # don't query twice return invoke_args = [self.ScriptHash.ToString(), parse_param('name'), []] invoke_args2 = [self.ScriptHash.ToString(), parse_param('symbol'), []] invoke_args3 = [ self.ScriptHash.ToString(), parse_param('decimals'), [] ] tx, fee, nameResults, num_ops = TestInvokeContract( wallet, invoke_args, None, False) tx, fee, symbolResults, num_ops = TestInvokeContract( wallet, invoke_args2, None, False) tx, fee, decimalResults, num_ops = TestInvokeContract( wallet, invoke_args3, None, False) try: self.name = nameResults[0].GetString() self.symbol = symbolResults[0].GetString() self.decimals = decimalResults[0].GetBigInteger() return True except Exception as e: logger.error("could not query token %s " % e) return False
def GatherLoadedContractParams(args, script): if len(args) < 5: raise Exception("please specify contract properties like {needs_storage} {needs_dynamic_invoke} {is_payable} {params} {return_type}") params = parse_param(args[3], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') try: for p in binascii.unhexlify(params): if p == ContractParameterType.Void.value: raise ValueError("Void is not a valid input parameter type") except binascii.Error: pass return_type = BigInteger(ContractParameterType.FromString(args[4]).value) needs_storage = bool(parse_param(args[0])) needs_dynamic_invoke = bool(parse_param(args[1])) is_payable = bool(parse_param(args[2])) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke if is_payable: contract_properties += ContractPropertyState.Payable out = generate_deploy_script(script, contract_properties=contract_properties, return_type=return_type, parameter_list=params) return out
def TransferFrom(self, wallet, from_addr, to_addr, amount): """ Transfer a specified amount of a token from the wallet specified in the `from_addr` to the `to_addr` if the originator `wallet` has been approved to do so. Args: wallet (neo.Wallets.Wallet): a wallet instance. from_addr (str): public address of the account to transfer the given amount from. to_addr (str): public address of the account to transfer the given amount to. amount (int): quantity to send. Returns: tuple: InvocationTransaction: the transaction. int: the transaction fee. list: the neo VM evaluation stack results. """ 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) return tx, fee, results
def Approve(self, wallet, owner_addr, requestor_addr, amount): """ Approve the `requestor_addr` account to transfer `amount` of tokens from the `owner_addr` acount. Args: wallet (neo.Wallets.Wallet): a wallet instance. owner_addr (str): public address of the account to transfer the given amount from. requestor_addr (str): public address of the account that requests the transfer. amount (int): quantity to send. Returns: tuple: InvocationTransaction: the transaction. int: the transaction fee. list: the neo VM evaluation stack results. """ 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) return tx, fee, results
def LoadContract(args): if len(args) < 4: print( "please specify contract to load like such: 'import contract {path} {params} {return_type} {needs_storage}'" ) return path = args[0] params = parse_param(args[1], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') return_type = parse_param(args[2], ignore_int=True, prefer_hex=False) if type(return_type) is str: return_type = return_type.encode('utf-8') needs_storage = bool(parse_param(args[3])) script = None if '.py' in path: print("Please load a compiled .avm file") return False with open(path, 'rb') as f: content = f.read() try: content = binascii.unhexlify(content) except Exception as e: pass script = content if script is not None: plist = params try: plist = bytearray(binascii.unhexlify(params)) except Exception as e: plist = bytearray(b'\x10') function_code = FunctionCode( script=script, param_list=bytearray(plist), return_type=binascii.unhexlify(return_type), needs_storage=needs_storage) return function_code print("error loading contract for path %s" % path) return None
def LoadContract(args): if len(args) < 5: print("please specify contract to load like such: 'import contract {path} {params} {return_type} {needs_storage} {needs_dynamic_invoke}'") return path = args[0] params = parse_param(args[1], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') return_type = bytearray(binascii.unhexlify(str(args[2]).encode('utf-8'))) needs_storage = bool(parse_param(args[3])) needs_dynamic_invoke = bool(parse_param(args[4])) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke script = None if '.py' in path: print("Please load a compiled .avm file") return False with open(path, 'rb') as f: content = f.read() try: content = binascii.unhexlify(content) except Exception as e: pass script = content if script is not None: plist = params try: plist = bytearray(binascii.unhexlify(params)) except Exception as e: plist = bytearray(b'\x10') function_code = FunctionCode(script=script, param_list=bytearray(plist), return_type=return_type, contract_properties=contract_properties) return function_code print("error loading contract for path %s" % path) return None
def test_2_SmartNEP5(self): timestamp = round(time.time()) test_neo_acc = 'NEO'+ str(timestamp)[-8:] test_neo_acc2 = 'NEO'+ str(timestamp-10000)[-8:] print('=========== NA =============') output = Compiler.instance().load('./nasc.py').default out = output.write() print('===== init =====') tx, results, total_ops, engine = TestBuild(out, ['init', '[]'], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertIn(results[0].GetString() ,['NASC initialized.', 'Uknown operation']) print('===== test =====') tx, results, total_ops, engine = TestBuild(out, ['na_test', '[]'], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString() ,'NASC is up!') tx, results, total_ops, engine = TestBuild(out, ['na_register', parse_param([test_neo_acc, self.wallet_1_script_hash.Data, 4, self.wallet_1_script_hash.Data, 1519912704])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString() , 'Alias registered: '+ test_neo_acc) tx, results, total_ops, engine = TestBuild(out, ['smart_balanceOf', parse_param([test_neo_acc])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger() , 10000) tx, results, total_ops, engine = TestBuild(out, ['na_register', parse_param([test_neo_acc2, self.wallet_3_script_hash.Data, 4, self.wallet_3_script_hash.Data, 1519912704])], self.GetWallet3(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString() , 'Alias registered: '+ test_neo_acc2) print('===== transfer =====') tx, results, total_ops, engine = TestBuild(out, ['smart_transfer', parse_param([test_neo_acc, test_neo_acc2, 500])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString(), 'Transfer completed.') tx, results, total_ops, engine = TestBuild(out, ['smart_balanceOf', parse_param([test_neo_acc2])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger() , 500) print('===== aprove =====') tx, results, total_ops, engine = TestBuild(out, ['smart_approve', parse_param([test_neo_acc, test_neo_acc2, 50])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetByteArray(), b'Spender can withdraw (from your address): 2') print('===== allowance =====') tx, results, total_ops, engine = TestBuild(out, ['smart_allowance', parse_param([test_neo_acc, test_neo_acc2])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetByteArray(), b'Spender can withdraw: 2') print('===== transfeFrom =====') tx, results, total_ops, engine = TestBuild(out, ['smart_transferFrom', parse_param([test_neo_acc2, test_neo_acc, test_neo_acc2, 50])], self.GetWallet3(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString(), 'TransferFrom completed.') print('===== balanceOf =====') tx, results, total_ops, engine = TestBuild(out, ['smart_balanceOf', parse_param([test_neo_acc2])], self.GetWallet1(), '0710', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger() , 550)
def test_ICOTemplate_5_mint(self): output = Compiler.instance().load( '%s/boa_test/example/demo/ICO_Template.py' % TestContract.dirname).default out = output.write() # register an address tx, results, total_ops, engine = TestBuild(out, [ 'crowdsale_register', parse_param([self.wallet_3_script_hash.Data]) ], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 1) TestContract.dispatched_events = [] # test mint tokens, this should return true tx, results, total_ops, engine = TestBuild( out, ['mintTokens', '[]', '--attach-neo=10'], self.GetWallet3(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), True) # it should dispatch an event self.assertEqual(len(TestContract.dispatched_events), 1) evt = TestContract.dispatched_events[0] self.assertIsInstance(evt, NotifyEvent) self.assertEqual(evt.amount, 10 * TOKENS_PER_NEO) self.assertEqual(evt.addr_to, self.wallet_3_script_hash) # test mint tokens again, this should be false since you can't do it twice tx, results, total_ops, engine = TestBuild( out, ['mintTokens', '[]', '--attach-neo=10'], self.GetWallet3(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # now the minter should have a balance tx, results, total_ops, engine = TestBuild( out, ['balanceOf', parse_param([self.wallet_3_script_hash.Data])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 10 * TOKENS_PER_NEO) # now the total circulation should be bigger tx, results, total_ops, engine = TestBuild(out, ['totalSupply', '[]'], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), (10 * TOKENS_PER_NEO) + TOKEN_INITIAL_AMOUNT)
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) return tx, fee, results
def TransferFrom(self, wallet, from_addr, to_addr, amount): invoke_args = [ self.ScriptHash.ToString(), 'transferFrom', [ parse_param(from_addr), parse_param(to_addr), parse_param(amount) ] ] tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args, None, True) return tx, fee, results
async def process_testinvoke_job(self): job_args = self.parser.parseString(self.operation + " " + str(self.job)) job_args = job_args[0:] if len(job_args) != 2: self.logger.error('ERROR! must have only 2 args (operation, params). skipping! %s', job_args) self.job = None self.process_job() return operation_params = parse_param(job_args[1]) if len(operation_params) != self.operation_args_array_length: self.logger.error('ERROR! must have exactly %d operation args, not %d. skipping! %s', self.operation_args_array_length, len(operation_params), job_args) self.job = None self.process_job() return args = [self.smart_contract_hash] + job_args self.logger.debug('processing job: %s', args) result = await self.test_invoke(args, self.expected_result_count, self.test_only, self.from_addr) if not result: # transaction failed? wallet probably out-of-sync (insufficient funds) so reload it self.wallet_needs_recovery = True else: # this job has been invoked, so clear it out. on to the next. self.job = None if self.test_only: # when testing but not relaying transactions, we just continue to the next job self.jobs_processed += 1 self.process_job() else: # transaction successfully relayed? then let's set the tx Hash that we're waiting for self.tx_processing = result.Hash
def GetBalance(self, wallet, address, as_string=False): """ Get the token balance. Args: wallet (neo.Wallets.Wallet): a wallet instance. address (str): public address of the account to get the token balance of. as_string (bool): whether the return value should be a string. Default is False, returning an integer. Returns: int/str: token balance value as int (default), token balanace as string if `as_string` is set to True. 0 if balance retrieval failed. """ addr = parse_param(address, wallet) if isinstance(addr, UInt160): addr = addr.Data 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() return 0
def GetBalance(self, wallet, address, as_string=False): """ Get the token balance. Args: wallet (neo.Wallets.Wallet): a wallet instance. address (str): public address of the account to get the token balance of. as_string (bool): whether the return value should be a string. Default is False, returning an integer. Returns: int/str: token balance value as int (default), token balanace as string if `as_string` is set to True. 0 if balance retrieval failed. """ addr = parse_param(address, wallet) if isinstance(addr, UInt160): addr = addr.Data 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() return 0
def test_ICOTemplate_3_KYC(self): output = Compiler.instance().load('%s/ico_template.py' % TestContract.dirname).default out = output.write() print(output.to_s()) # now transfer tokens to wallet 2 TestContract.dispatched_events = [] # test mint tokens without being kyc verified tx, results, total_ops, engine = TestBuild(out, ['mintTokens', '[]', '--attach-neo=10'], self.GetWallet3(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # Try to register as a non owner tx, results, total_ops, engine = TestBuild(out, ['crowdsale_register', parse_param([self.wallet_3_script_hash.Data])], self.GetWallet3(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # Get status of non registered address tx, results, total_ops, engine = TestBuild(out, ['crowdsale_status', parse_param([self.wallet_3_script_hash.Data])], self.GetWallet3(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) TestContract.dispatched_events = [] # register an address tx, results, total_ops, engine = TestBuild(out, ['crowdsale_register', parse_param([self.wallet_3_script_hash.Data])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 1) # it should dispatch an event self.assertEqual(len(TestContract.dispatched_events), 1) evt = TestContract.dispatched_events[0] # self.assertEqual(evt.event_payload[0], b'kyc_registration') # register 2 addresses at once tx, results, total_ops, engine = TestBuild(out, ['crowdsale_register', parse_param([self.wallet_3_script_hash.Data, self.wallet_2_script_hash.Data])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 2) # now check reg status tx, results, total_ops, engine = TestBuild(out, ['crowdsale_status', parse_param([self.wallet_3_script_hash.Data])], self.GetWallet3(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), True)
def test_ICOTemplate_2(self): output = Compiler.instance().load('%s/ico_template.py' % TestContract.dirname).default out = output.write() # now transfer tokens to wallet 2 TestContract.dispatched_events = [] test_transfer_amount = 2400000001 tx, results, total_ops, engine = TestBuild(out, ['transfer', parse_param([bytearray(TOKEN_OWNER), self.wallet_2_script_hash.Data, test_transfer_amount])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), True) self.assertEqual(len(TestContract.dispatched_events), 1) evt = TestContract.dispatched_events[0] self.assertIsInstance(evt, NotifyEvent) self.assertEqual(evt.addr_from.Data, bytearray(TOKEN_OWNER)) self.assertEqual(evt.addr_to, self.wallet_2_script_hash) self.assertEqual(evt.amount, test_transfer_amount) # now get balance of wallet 2 tx, results, total_ops, engine = TestBuild(out, ['balanceOf', parse_param([self.wallet_2_script_hash.Data])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), test_transfer_amount) # now the owner should have less tx, results, total_ops, engine = TestBuild(out, ['balanceOf', parse_param([bytearray(TOKEN_OWNER)])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), TOKEN_INITIAL_AMOUNT - test_transfer_amount) # now this transfer should fail tx, results, total_ops, engine = TestBuild(out, ['transfer', parse_param([bytearray(TOKEN_OWNER), self.wallet_2_script_hash.Data, TOKEN_INITIAL_AMOUNT])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # this transfer should fail because it is not signed by the 'from' address tx, results, total_ops, engine = TestBuild(out, ['transfer', parse_param([bytearray(TOKEN_OWNER), self.wallet_2_script_hash.Data, 10000])], self.GetWallet3(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # now this transfer should fail, this is from address with no tokens tx, results, total_ops, engine = TestBuild(out, ['transfer', parse_param([self.wallet_3_script_hash.Data, self.wallet_2_script_hash.Data, 1000])], self.GetWallet3(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # get balance of bad data tx, results, total_ops, engine = TestBuild(out, ['balanceOf', parse_param(['abc'])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 0) # get balance no params tx, results, total_ops, engine = TestBuild(out, ['balanceOf', parse_param([])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False)
def RedeemWithdraw(prompter, wallet, args): """ withdraw {CONTRACT_ADDR} {ASSET} {TO_ADDR} {AMOUNT} """ if not wallet: print("please open a wallet") return withdrawal_tx = construct_withdrawal_tx(wallet, args) if withdrawal_tx: outputs = withdrawal_tx.outputs contract_hash = wallet.ToScriptHash(args[0]).ToString() to_addr = wallet.ToScriptHash(args[2]) invoke_args = [ contract_hash, parse_param('getBalance'), [to_addr.Data] ] print("invoke args... %s " % invoke_args) tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args, None, False) print("tx is %s %s" % (withdrawal_tx.outputs, withdrawal_tx.inputs)) if tx is not None and results is not None: print( "\n-------------------------------------------------------------------------------------------------------------------------------------" ) print("Test Withdraw successful") print("Total operations: %s " % num_ops) print("Results %s " % [str(item) for item in results]) print("Withdraw gas cost: %s " % (tx.Gas.value / Fixed8.D)) print("Withdraw Fee: %s " % (fee.value / Fixed8.D)) print( "-------------------------------------------------------------------------------------------------------------------------------------\n" ) print("Enter your password to complete this withdrawal") passwd = prompt("[Password]> ", is_password=True) if not wallet.ValidatePassword(passwd): print("incorrect password") return withdrawal_tx.scripts = [] withdrawal_tx.Script = tx.Script withdrawal_tx.outputs = outputs # tx.scripts = [] # tx.inputs = withdrawal_tx.inputs # tx.outputs = withdrawal_tx.outputs result = InvokeWithdrawTx(wallet, withdrawal_tx, contract_hash) return result else: print("Error testing contract invoke") return
def LoadContract(path, needs_storage, needs_dynamic_invoke, is_payable, params_str, return_type): params = parse_param(params_str, ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') try: for p in binascii.unhexlify(params): if p == ContractParameterType.Void.value: raise ValueError("Void is not a valid input parameter type") except binascii.Error: pass rtype = BigInteger(ContractParameterType.FromString(return_type).value) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke if is_payable: contract_properties += ContractPropertyState.Payable if '.avm' not in path: raise ValueError("Please load a compiled .avm file") script = None with open(path, 'rb') as f: content = f.read() try: content = binascii.unhexlify(content) except Exception as e: pass script = content if script: try: plist = bytearray(binascii.unhexlify(params)) except Exception as e: plist = bytearray(b'\x10') function_code = FunctionCode(script=script, param_list=bytearray(plist), return_type=rtype, contract_properties=contract_properties) return function_code else: raise Exception(f"Error loading contract for path {path}")
def CrowdsaleRegister(self, wallet, register_addresses): 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) return tx, fee, results
def GatherLoadedContractParams(args, script): params = parse_param(args[0], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') return_type = parse_param(args[1], ignore_int=True, prefer_hex=False) if type(return_type) is str: return_type = return_type.encode('utf-8') needs_storage = bool(parse_param(args[2])) out = generate_deploy_script(script, needs_storage=needs_storage, return_type=return_type, parameter_list=params) return out
def test_ICOTemplate_7_reserve(self): output = Compiler.instance().load('%s/ico_template.py' % TestContract.dirname).default out = output.write() burn_amt = 1000000000 * 100000000 reserve_amt = burn_amt * 2 reserve_amt_too_many = burn_amt * 4 tx, results, total_ops, engine = TestBuild(out, ['balanceOf', parse_param([self.wallet_1_script_hash.Data])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 599999997599999999) # reserve for private sale fails CheckWitness tx, results, total_ops, engine = TestBuild(out, ['reserve_private', '[%s]' % reserve_amt], self.GetWallet2(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # cannot reserve too many tx, results, total_ops, engine = TestBuild(out, ['reserve_private', '[%s]' % reserve_amt_too_many], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # reserve success tx, results, total_ops, engine = TestBuild(out, ['reserve_private', '[%s]' % reserve_amt], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), True) tx, results, total_ops, engine = TestBuild(out, ['balanceOf', parse_param([self.wallet_1_script_hash.Data])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 599999997599999999 + reserve_amt) # tokens available for sale tx, results, total_ops, engine = TestBuild(out, ['crowdsale_available', '[]'], self.GetWallet2(), '0705', '05') self.assertEqual(len(results), 1) # self.assertEqual(results[0].GetBigInteger(), 4000000000 * 100000000 - 54000000000000 - burn_amt - reserve_amt) self.assertEqual(results[0].GetBigInteger(), 4000000000 * 100000000 - 50000000000000 - burn_amt - reserve_amt) # can reserve twice tx, results, total_ops, engine = TestBuild(out, ['reserve_private', '[%s]' % 10000], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), True)
def test_ICOTemplate_1(self): output = Compiler.instance().load('%s/ico_template.py' % TestContract.dirname).default out = output.write() # print(output.to_s()) tx, results, total_ops, engine = TestBuild(out, ['name', '[]'], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString(), TOKEN_NAME) tx, results, total_ops, engine = TestBuild(out, ['symbol', '[]'], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString(), TOKEN_SYMBOL) tx, results, total_ops, engine = TestBuild(out, ['decimals', '[]'], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), TOKEN_DECIMALS) tx, results, total_ops, engine = TestBuild(out, ['totalSupply', '[]'], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) # self.assertEqual(results[0].GetBigInteger(), 0) # total supply shall be 10b self.assertEqual(results[0].GetBigInteger(), 1000000000000000000) tx, results, total_ops, engine = TestBuild(out, ['nonexistentmethod', '[]'], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetString(), 'unknown operation') # deploy with wallet 2 should fail CheckWitness tx, results, total_ops, engine = TestBuild(out, ['deploy', '[]'], self.GetWallet2(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) tx, results, total_ops, engine = TestBuild(out, ['deploy', '[]'], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), True) # second time, it should already be deployed and return false tx, results, total_ops, engine = TestBuild(out, ['deploy', '[]'], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # now total supply should be equal to the initial owner amount tx, results, total_ops, engine = TestBuild(out, ['totalSupply', '[]'], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) # self.assertEqual(results[0].GetBigInteger(), TOKEN_INITIAL_AMOUNT) # by new definition, totalSupply shall be TOKEN_TOTAL_SUPPLY self.assertEqual(results[0].GetBigInteger(), TOKEN_TOTAL_SUPPLY) # now the owner should have a balance of the TOKEN_INITIAL_AMOUNT tx, results, total_ops, engine = TestBuild(out, ['balanceOf', parse_param([bytearray(TOKEN_OWNER)])], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), TOKEN_INITIAL_AMOUNT)
def Allowance(self, wallet, owner_addr, requestor_addr): """ Return the amount of tokens that the `requestor_addr` account can transfer from the `owner_addr` account. Args: wallet (neo.Wallets.Wallet): a wallet instance. owner_addr (str): public address of the account to transfer the given amount from. requestor_addr (str): public address of the account that requests the transfer. Returns: tuple: InvocationTransaction: the transaction. int: the transaction fee. list: the neo VM evaluation stack results. """ 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) return tx, fee, results
def test_ICOTemplate_3_personal_cap(self): output = Compiler.instance().load('%s/ico_template.py' % TestContract.dirname).default out = output.write() # check whitelist cap tx, results, total_ops, engine = TestBuild(out, [ 'get_exchangeable_amount', parse_param([ self.wallet_3_script_hash.Data, self.WHITELIST_SALE_PERSONAL_CAP + 1, self.now_in_test ]) ], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 0) # check presale cap tx, results, total_ops, engine = TestBuild(out, [ 'get_exchangeable_amount', parse_param([ self.wallet_3_script_hash.Data, self.PRESALE_PERSONAL_CAP + 1, self.now_in_test + 86400 * 2 ]) ], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 0) # check crowdsale cap tx, results, total_ops, engine = TestBuild(out, [ 'get_exchangeable_amount', parse_param([ self.wallet_3_script_hash.Data, self.CROWDSALE_PERSONAL_CAP + 1, self.now_in_test + 86400 * 4 ]) ], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), 0)
def TransferFrom(self, wallet, from_addr, to_addr, amount): """ Transfer a specified amount of a token from the wallet specified in the `from_addr` to the `to_addr` if the originator `wallet` has been approved to do so. Args: wallet (neo.Wallets.Wallet): a wallet instance. from_addr (str): public address of the account to transfer the given amount from. to_addr (str): public address of the account to transfer the given amount to. amount (int): quantity to send. Returns: tuple: InvocationTransaction: the transaction. int: the transaction fee. list: the neo VM evaluation stack results. """ 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) return tx, fee, results
def lookup_contract_holds(wallet, contract_hash): invoke_args = [contract_hash.ToString(), parse_param('getAllHolds'), []] tx, fee, results, num_ops = TestInvokeContract(wallet, invoke_args, None, False) if tx is not None and len(results) > 0: vins = parse_hold_vins(results) return vins raise Exception("Could not lookup contract holds")
def test_ICOTemplate_4_locked_until(self): output = Compiler.instance().load('%s/ico_template.py' % TestContract.dirname).default out = output.write() tx, results, total_ops, engine = TestBuild(out, [ 'get_locked_until', parse_param([bytearray(ECOSYSTEM_RESERVE_ADDRESS)]) ], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBigInteger(), self.now_in_test + 3 * 30 * 86400) # cannot transfer to locked account test_transfer_amount = 2400000001 tx, results, total_ops, engine = TestBuild(out, [ 'transfer', parse_param([ bytearray(TOKEN_OWNER), bytearray(ECOSYSTEM_RESERVE_ADDRESS), test_transfer_amount ]) ], self.GetWallet1(), '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False) # cannot transfer from locked account tx, results, total_ops, engine = TestBuild( out, [ 'transfer', parse_param([ bytearray(ECOSYSTEM_RESERVE_ADDRESS), bytearray(TOKEN_OWNER), test_transfer_amount ]) ], self.wallet['ECOSYSTEM_RESERVE_ADDRESS'], '0705', '05') self.assertEqual(len(results), 1) self.assertEqual(results[0].GetBoolean(), False)
def GatherLoadedContractParams(args, script): if len(args) < 4: raise Exception("please specify contract properties like {params} {return_type} {needs_storage} {needs_dynamic_invoke}") params = parse_param(args[0], ignore_int=True, prefer_hex=False) if type(params) is str: params = params.encode('utf-8') return_type = bytearray(binascii.unhexlify(str(args[1]).encode('utf-8'))) needs_storage = bool(parse_param(args[2])) needs_dynamic_invoke = bool(parse_param(args[3])) contract_properties = 0 if needs_storage: contract_properties += ContractPropertyState.HasStorage if needs_dynamic_invoke: contract_properties += ContractPropertyState.HasDynamicInvoke out = generate_deploy_script(script, contract_properties=contract_properties, return_type=return_type, parameter_list=params) return out
def Transfer(self, wallet, from_addr, to_addr, amount): """ Transfer a specified amount of the NEP5Token to another address. Args: wallet (neo.Wallets.Wallet): a wallet instance. from_addr (str): public address of the account to transfer the given amount from. to_addr (str): public address of the account to transfer the given amount to. amount (int): quantity to send. Returns: tuple: InvocationTransaction: the transaction. int: the transaction fee. list: the neo VM evaluationstack results. """ sb = ScriptBuilder() sb.EmitAppCallWithOperationAndArgs(self.ScriptHash, 'transfer', [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) return tx, fee, results
def TestInvokeContract(wallet, args): BC = GetBlockchain() contract = BC.GetContract(args[0]) if contract: descripe_contract(contract) verbose = False if 'verbose' in args: verbose = True args.remove('verbose') # params = args[1:] if len(args) > 1 else [] if len(params) > 0 and params[0] == 'describe': return params.reverse() sb = ScriptBuilder() for p in params: item = parse_param(p) sb.push(item) sb.EmitAppCall(contract.Code.ScriptHash().Data) out = sb.ToArray() return test_invoke(out, wallet) else: print("Contract %s not found" % args[0]) return None, None
def CrowdsaleRegister(self, wallet, register_addresses, from_addr=None): """ Register for a crowd sale. Args: wallet (neo.Wallets.Wallet): a wallet instance. register_addresses (str): public address of the account that wants to register for the sale. Returns: tuple: InvocationTransaction: the transaction. int: the transaction fee. list: the neo VM evaluation stack results. """ 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) return tx, fee, results
def test_8_named_addr(self): wallet = self.GetWallet1() AddAlias(wallet, self.wallet_1_addr, 'my_named_addr') named = [n.Title for n in wallet.NamedAddr] self.assertIn('my_named_addr', named) param = 'my_named_addr' addr = lookup_addr_str(wallet, param) self.assertIsInstance(addr, UInt160) self.assertEqual(addr, self.wallet_1_script_hash) presult = parse_param(param, wallet) self.assertIsInstance(presult, bytearray) self.assertEqual(presult, self.wallet_1_script_hash.Data)
def TestInvokeContract(wallet, args, withdrawal_tx=None, parse_params=True, from_addr=None, min_fee=DEFAULT_MIN_FEE): BC = GetBlockchain() contract = BC.GetContract(args[0]) if contract: verbose = False if 'verbose' in args: descripe_contract(contract) verbose = True args.remove('verbose') # params = args[1:] if len(args) > 1 else [] if len(params) > 0 and params[0] == 'describe': return params, neo_to_attach, gas_to_attach = get_asset_attachments(params) params.reverse() sb = ScriptBuilder() for p in params: if parse_params: item = parse_param(p, wallet) else: item = p if type(item) is list: item.reverse() listlength = len(item) for listitem in item: sb.push(listitem) sb.push(listlength) sb.Emit(PACK) else: sb.push(item) sb.EmitAppCall(contract.Code.ScriptHash().Data) out = sb.ToArray() outputs = [] if neo_to_attach: output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash, Value=neo_to_attach, script_hash=contract.Code.ScriptHash(), ) outputs.append(output) if gas_to_attach: output = TransactionOutput(AssetId=Blockchain.SystemCoin().Hash, Value=gas_to_attach, script_hash=contract.Code.ScriptHash()) outputs.append(output) return test_invoke(out, wallet, outputs, withdrawal_tx, from_addr, min_fee) else: print("Contract %s not found" % args[0]) return None, None, None, None
def test_deploy_and_invoke(deploy_script, invoke_args, wallet, from_addr=None, min_fee=DEFAULT_MIN_FEE, invocation_test_mode=True, debug_map=None): bc = GetBlockchain() sn = bc._db.snapshot() accounts = DBCollection(bc._db, sn, DBPrefix.ST_Account, AccountState) assets = DBCollection(bc._db, sn, DBPrefix.ST_Asset, AssetState) validators = DBCollection(bc._db, sn, DBPrefix.ST_Validator, ValidatorState) contracts = DBCollection(bc._db, sn, DBPrefix.ST_Contract, ContractState) storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem) if settings.USE_DEBUG_STORAGE: debug_storage = DebugStorage.instance() debug_sn = debug_storage.db.snapshot() storages = DBCollection(debug_storage.db, debug_sn, DBPrefix.ST_Storage, StorageItem) storages.DebugStorage = True dtx = InvocationTransaction() dtx.Version = 1 dtx.outputs = [] dtx.inputs = [] dtx.scripts = [] dtx.Script = binascii.unhexlify(deploy_script) if from_addr is not None: from_addr = lookup_addr_str(wallet, from_addr) dtx = wallet.MakeTransaction(tx=dtx, from_addr=from_addr) context = ContractParametersContext(dtx) wallet.Sign(context) dtx.scripts = context.GetScripts() script_table = CachedScriptTable(contracts) service = StateMachine(accounts, validators, assets, contracts, storages, None) contract = wallet.GetDefaultContract() dtx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=Crypto.ToScriptHash(contract.Script, unhex=False))] to_dispatch = [] engine = ApplicationEngine( trigger_type=TriggerType.Application, container=dtx, table=script_table, service=service, gas=dtx.Gas, testMode=True ) engine.LoadScript(dtx.Script, False) # first we will execute the test deploy # then right after, we execute the test invoke d_success = engine.Execute() if d_success: items = engine.EvaluationStack.Items contract_state = None for i in items: if type(i) is ContractState: contract_state = i break elif type(i) is InteropInterface: item = i.GetInterface() if type(item) is ContractState: contract_state = item break shash = contract_state.Code.ScriptHash() invoke_args, neo_to_attach, gas_to_attach = get_asset_attachments(invoke_args) invoke_args.reverse() sb = ScriptBuilder() for p in invoke_args: item = parse_param(p, wallet) if type(item) is list: item.reverse() listlength = len(item) for listitem in item: subitem = parse_param(listitem, wallet) sb.push(subitem) sb.push(listlength) sb.Emit(PACK) else: sb.push(item) sb.EmitAppCall(shash.Data) out = sb.ToArray() outputs = [] if neo_to_attach: output = TransactionOutput(AssetId=Blockchain.SystemShare().Hash, Value=neo_to_attach, script_hash=contract_state.Code.ScriptHash(), ) outputs.append(output) if gas_to_attach: output = TransactionOutput(AssetId=Blockchain.SystemCoin().Hash, Value=gas_to_attach, script_hash=contract_state.Code.ScriptHash()) outputs.append(output) itx = InvocationTransaction() itx.Version = 1 itx.outputs = outputs itx.inputs = [] itx.scripts = [] itx.Attributes = [] itx.Script = binascii.unhexlify(out) if len(outputs) < 1: contract = wallet.GetDefaultContract() itx.Attributes = [TransactionAttribute(usage=TransactionAttributeUsage.Script, data=Crypto.ToScriptHash(contract.Script, unhex=False).Data)] itx = wallet.MakeTransaction(tx=itx, from_addr=from_addr) context = ContractParametersContext(itx) wallet.Sign(context) itx.scripts = context.GetScripts() # print("tx: %s " % json.dumps(itx.ToJson(), indent=4)) engine = ApplicationEngine( trigger_type=TriggerType.Application, container=itx, table=script_table, service=service, gas=itx.Gas, testMode=invocation_test_mode ) engine.LoadScript(itx.Script, False) engine.LoadDebugInfoForScriptHash(debug_map, shash.Data) # call execute in its own blocking thread # reactor.stop() i_success = engine.Execute() service.ExecutionCompleted(engine, i_success) to_dispatch = to_dispatch + service.events_to_dispatch for event in to_dispatch: events.emit(event.event_type, event) if i_success: service.TestCommit() if len(service.notifications) > 0: for n in service.notifications: # print("NOTIFICATION : %s " % n) Blockchain.Default().OnNotify(n) logger.info("Used %s Gas " % engine.GasConsumed().ToString()) consumed = engine.GasConsumed() - Fixed8.FromDecimal(10) consumed = consumed.Ceil() if consumed <= Fixed8.Zero(): consumed = min_fee total_ops = engine.ops_processed # set the amount of gas the tx will need itx.Gas = consumed itx.Attributes = [] result = engine.EvaluationStack.Items return itx, result, total_ops, engine else: print("error executing invoke contract...") else: print("error executing deploy contract.....") service.ExecutionCompleted(engine, False, 'error') return None, [], 0, None
def RequestWithdrawFrom(wallet, asset_id, contract_hash, to_addr, amount, require_password=True): asset_type = asset_id.lower() if asset_type not in ['neo', 'gas']: raise Exception('please specify neo or gas to withdraw') readable_addr = to_addr asset_id = get_asset_id(wallet, asset_type) contract = Blockchain.Default().GetContract(contract_hash) shash = contract.Code.ScriptHash() contract_addr = Crypto.ToAddress(shash) to_addr = parse_param(to_addr, wallet) amount = get_asset_amount(amount, asset_id) if shash not in wallet._watch_only: print("Add withdrawal contract address to your watch only: import watch_addr %s " % contract_addr) return False if amount < Fixed8.Zero(): print("Cannot withdraw negative amount") return False unspents = wallet.FindUnspentCoinsByAssetAndTotal( asset_id=asset_id, amount=amount, from_addr=shash, use_standard=False, watch_only_val=64, reverse=True ) if not unspents or len(unspents) == 0: print("no eligible withdrawal vins") return False balance = GetWithdrawalBalance(wallet, shash, to_addr, asset_type) balance_fixed8 = Fixed8(balance) orig_amount = amount if amount <= balance_fixed8: sb = ScriptBuilder() for uns in unspents: if amount > Fixed8.Zero(): to_spend = amount if to_spend > uns.Output.Value: to_spend = uns.Output.Value amount_bytes = bytearray(to_spend.value.to_bytes(8, 'little')) data = to_addr + amount_bytes data = data + uns.RefToBytes() sb.EmitAppCallWithOperationAndData(shash, 'withdraw_%s' % asset_type, data) amount -= uns.Output.Value tx, fee, results, num_ops = test_invoke(sb.ToArray(), wallet, []) for item in results: if not item.GetBoolean(): print("Error performitng withdrawals") return False if require_password: print("\n---------------------------------------------------------------") print("Will make withdrawal request for %s %s from %s to %s " % (orig_amount.ToString(), asset_type, contract_addr, readable_addr)) print("FEE IS %s " % fee.ToString()) print("GAS IS %s " % tx.Gas.ToString()) print("------------------------------------------------------------------\n") print("Enter your password to complete this request") passwd = prompt("[Password]> ", is_password=True) if not wallet.ValidatePassword(passwd): print("incorrect password") return result = InvokeContract(wallet, tx, fee) return result else: print("insufficient balance") return False