def test_ghost_multi_mint(self): engine = self.prepare_testengine() engine.add_contract(self.CONTRACT_PATH_NEF.replace('.py', '.nef')) aux_path = self.get_contract_path('test_native', 'auxiliary_contract.py') output, manifest = self.compile_and_save(self.CONTRACT_PATH_NEF.replace('.nef', '.py')) ghost_address = hash160(output) print(to_hex_str(ghost_address)) output, manifest = self.compile_and_save(aux_path) aux_address = hash160(output) print(to_hex_str(aux_address)) # when deploying, the contract will mint tokens to the owner deploy_event = engine.get_events('Deployed') self.assertEqual(1, len(deploy_event)) self.assertEqual(2, len(deploy_event[0].arguments)) # add some gas for fees add_amount = 10 * 10 ** 8 engine.add_gas(aux_address, add_amount) # define custom meta & lock & royalties for multi tokenMeta = [ bytes('{ "name": "GHOST", "description": "A ghost shows up", "image": "{some image URI}", "tokenURI": "{some URI}" }', 'utf-8'), bytes('{ "name": "GHOST2", "description": "A ghost shows up", "image": "{some image URI}", "tokenURI": "{some URI}" }', 'utf-8'), bytes('{ "name": "GHOST3", "description": "A ghost shows up", "image": "{some image URI}", "tokenURI": "{some URI}" }', 'utf-8') ] lockedContent = [ bytes('123', 'utf-8'), bytes('456', 'utf-8'), bytes('789', 'utf-8'), ] royalties = [ bytes('[{"address": "someaddress", "value": 20}, {"address": "someaddress2", "value": 30}]', 'utf-8'), bytes('[{"address": "someaddress3", "value": 20}, {"address": "someaddress4", "value": 30}]', 'utf-8'), bytes('[{"address": "someaddress5", "value": 20}, {"address": "someaddress6", "value": 30}]', 'utf-8'), ] # check tokens iterator before ghost_tokens_before = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'tokens', expected_result_type=InteropInterface) self.assertEqual(InteropInterface, ghost_tokens_before) # multiMint result = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'multiMint', aux_address, tokenMeta, lockedContent, royalties, None, signer_accounts=[aux_address], expected_result_type=list) print("result: " + str(result)) # check tokens iterator after ghost_tokens_after = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'tokens', expected_result_type=InteropInterface) print("tokens after: " + str(ghost_tokens_after)) # check balances after ghost_balance_after = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'balanceOf', aux_address) self.assertEqual(3, ghost_balance_after) ghost_supply_after = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'totalSupply') self.assertEqual(3, ghost_supply_after) self.print_notif(engine.notifications)
def test_ghost_onNEP11Payment(self): engine = self.prepare_testengine() engine.add_contract(self.CONTRACT_PATH_NEF.replace('.py', '.nef')) aux_path = self.get_contract_path('test_native', 'auxiliary_contract.py') output, manifest = self.compile_and_save(self.CONTRACT_PATH_NEF.replace('.nef', '.py')) ghost_address = hash160(output) print(to_hex_str(ghost_address)) output, manifest = self.compile_and_save(aux_path) aux_address = hash160(output) print(to_hex_str(aux_address)) # add some gas for fees add_amount = 10 * 10 ** 8 engine.add_gas(self.OTHER_ACCOUNT_1, add_amount) # mint token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', self.OTHER_ACCOUNT_1, self.TOKEN_META, self.LOCK_CONTENT, self.ROYALTIES, None, signer_accounts=[self.OTHER_ACCOUNT_1], expected_result_type=bytes) # the smart contract will abort if any address calls the NEP11 onPayment method with self.assertRaises(TestExecutionException, msg=self.ABORTED_CONTRACT_MSG): result = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'onNEP11Payment', self.OTHER_ACCOUNT_1, 1, token, None, signer_accounts=[self.OTHER_ACCOUNT_1], expected_result_type=bool)
def test_ghost_mint(self): engine = self.prepare_testengine() engine.add_contract(self.CONTRACT_PATH_NEF.replace('.py', '.nef')) aux_path = self.get_contract_path('test_native', 'auxiliary_contract.py') output, manifest = self.compile_and_save(self.CONTRACT_PATH_NEF.replace('.nef', '.py')) ghost_address = hash160(output) print(to_hex_str(ghost_address)) output, manifest = self.compile_and_save(aux_path) aux_address = hash160(output) print(to_hex_str(aux_address)) # when deploying, the contract will mint tokens to the owner deploy_event = engine.get_events('Deployed') self.assertEqual(1, len(deploy_event)) self.assertEqual(2, len(deploy_event[0].arguments)) # should fail because account does not have enough for fees with self.assertRaises(TestExecutionException, msg=self.ASSERT_RESULTED_FALSE_MSG): self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', # aux_address, self.TOKEN_META, self.LOCK_CONTENT, self.ROYALTIES, None, aux_address, bytes(0), bytes(0), bytes(0), None, signer_accounts=[aux_address], expected_result_type=bytes) # add some gas for fees add_amount = 10 * 10 ** 8 engine.add_gas(aux_address, add_amount) # should succeed now that account has enough fees token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', aux_address, self.TOKEN_META, self.LOCK_CONTENT, self.ROYALTIES, None, signer_accounts=[aux_address], expected_result_type=bytes) print("get props now: ") properties = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'properties', token, expected_result_type=bytes) print("props: " + str(properties)) royalties = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'getRoyalties', token, expected_result_type=bytes) print("royalties: " + str(royalties)) print('non existing props:') with self.assertRaises(TestExecutionException, msg='An unhandled exception was thrown. Unable to parse metadata'): properties = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'properties', bytes('thisisanonexistingtoken', 'utf-8'), expected_result_type=bytes) print("props: " + str(properties)) # check balances after ghost_amount_after = self.run_smart_contract(engine, GAS_SCRIPT, 'balanceOf', ghost_address) gas_aux_after = self.run_smart_contract(engine, GAS_SCRIPT, 'balanceOf', aux_address) print("ghost gas amount: " + str(ghost_amount_after)) print("aux gas amount: " + str(gas_aux_after)) ghost_balance_after = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'balanceOf', aux_address) print("balance nft: " + str(ghost_balance_after)) ghost_supply_after = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'totalSupply') print("supply nft: " + str(ghost_supply_after)) self.assertEqual(1, ghost_supply_after) self.print_notif(engine.notifications)
def test_amm_onNEP17Payment(self): transferred_amount = 10 * 10 ** 8 path = self.get_contract_path('amm.py') path_aux = self.get_contract_path('examples/test_native', 'auxiliary_contract.py') path_zneo = self.get_contract_path('wrapped_neo.py') path_zgas = self.get_contract_path('wrapped_gas.py') engine = TestEngine() engine.add_contract(path.replace('.py', '.nef')) engine.add_contract(path_zneo.replace('.py', '.nef')) engine.add_contract(path_zgas.replace('.py', '.nef')) output, manifest = self.compile_and_save(path) amm_address = hash160(output) output, manifest = self.compile_and_save(path_aux) aux_address = hash160(output) output, manifest = self.compile_and_save(path_zneo) zneo_address = hash160(output) output, manifest = self.compile_and_save(path_zgas) zgas_address = hash160(output) result = self.run_smart_contract(engine, path, 'deploy', signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result) result = self.run_smart_contract(engine, path, 'set_address', zneo_address, zgas_address, signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result) # the smart contract will abort if some address other than zNEO or zGAS calls the onPayment method with self.assertRaises(TestExecutionException, msg=self.ABORTED_CONTRACT_MSG): self.run_smart_contract(engine, path, 'onNEP17Payment', aux_address, transferred_amount, None, signer_accounts=[aux_address]) engine.add_neo(aux_address, transferred_amount) # adding the transferred_amount into the aux_address result = self.run_smart_contract(engine, path_aux, 'calling_transfer', NEO_SCRIPT, aux_address, zneo_address, transferred_amount, None, signer_accounts=[aux_address], expected_result_type=bool) self.assertEqual(True, result) # the AMM will accept this transaction, but there is no reason to send tokens directly to the smart contract. # to send tokens to the AMM you should use the add_liquidity function result = self.run_smart_contract(engine, path_aux, 'calling_transfer', zneo_address, aux_address, amm_address, transferred_amount, None, signer_accounts=[aux_address], expected_result_type=bool) self.assertEqual(True, result)
def test_HTLC_withdraw(self): path = self.get_contract_path('HTLC.py') engine = TestEngine() example_contract = self.get_contract_path( 'test_native/example_contract_for_htlc.py') transferred_amount_neo = 10 * 10**8 transferred_amount_gas = 10000 * 10**8 output, manifest = self.compile_and_save(example_contract) contract_address1 = bytes(range(20)) contract_address2 = hash160(output) output, manifest = self.compile_and_save(path) htlc_address = hash160(output) engine.add_neo(contract_address1, transferred_amount_neo) engine.add_gas(contract_address2, transferred_amount_gas) # deploying smart contract result = self.run_smart_contract( engine, path, 'deploy', signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result) # starting atomic swap by using the atomic_swap method result = self.run_smart_contract( engine, path, 'atomic_swap', contract_address1, NEO, transferred_amount_neo, contract_address2, GAS, transferred_amount_gas, hash160(String('unit test').to_bytes()), signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result) # won't be able to withdraw, because no one transferred cryptocurrency to the smart contract result = self.run_smart_contract( engine, path, 'withdraw', 'unit test', signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(False, result)
def test_destroy_contract(self): call_flag = Integer(CallFlags.ALL).to_byte_array(signed=True, min_length=1) expected_output = ( Opcode.NEWARRAY0 + Opcode.PUSHDATA1 + Integer(len(Interop.DestroyContract.method_name)).to_byte_array( min_length=1) + String(Interop.DestroyContract.method_name).to_bytes() + Opcode.PUSHDATA1 + Integer(len( constants.MANAGEMENT_SCRIPT)).to_byte_array(min_length=1) + constants.MANAGEMENT_SCRIPT + Opcode.PUSHDATA1 + Integer(len(call_flag)).to_byte_array(min_length=1) + call_flag + Opcode.ROT + Opcode.ROT + Opcode.SYSCALL + Interop.CallContract.interop_method_hash + Opcode.DROP + Opcode.RET) path = self.get_contract_path('DestroyContract.py') output = Boa3.compile(path) self.assertEqual(expected_output, output) engine = TestEngine() result = self.run_smart_contract(engine, path, 'Main') self.assertIsVoid(result) script_hash = hash160(output) call_contract_path = self.get_contract_path('CallScriptHash.py') with self.assertRaises(TestExecutionException): self.run_smart_contract(engine, call_contract_path, 'Main', script_hash, 'Main', [])
def test_nep17_onPayment(self): transferred_amount = 10 * 10**8 # 10 tokens path = self.get_contract_path('NEP17.py') engine = TestEngine() engine.add_contract(path.replace('.py', '.nef')) output, manifest = self.compile_and_save(path) nep17_address = hash160(output) test_address = bytes(range(20)) result = self.run_smart_contract( engine, path, 'deploy', signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result) engine.add_neo(test_address, transferred_amount) # fire the Transfer event if sender is NEO when transferring to NEP17 script hash neo_balance_sender_before = self.run_smart_contract( engine, NEO_SCRIPT, 'balanceOf', test_address) neo_balance_nep17_before = self.run_smart_contract( engine, NEO_SCRIPT, 'balanceOf', nep17_address) nep17_balance_sender_before = self.run_smart_contract( engine, path, 'balanceOf', test_address)
def test_call_contract(self): path = self.get_contract_path('CallScriptHash.py') call_contract_path = self.get_contract_path('test_sc/arithmetic_test', 'Addition.py') Boa3.compile_and_save(call_contract_path) contract, manifest = self.get_output(call_contract_path) call_hash = hash160(contract) call_contract_path = call_contract_path.replace('.py', '.nef') engine = TestEngine() with self.assertRaises(TestExecutionException, msg=self.CALLED_CONTRACT_DOES_NOT_EXIST_MSG): self.run_smart_contract(engine, path, 'Main', call_hash, 'add', [1, 2]) engine.add_contract(call_contract_path) result = self.run_smart_contract(engine, path, 'Main', call_hash, 'add', [1, 2]) self.assertEqual(3, result) result = self.run_smart_contract(engine, path, 'Main', call_hash, 'add', [-42, -24]) self.assertEqual(-66, result) result = self.run_smart_contract(engine, path, 'Main', call_hash, 'add', [-42, 24]) self.assertEqual(-18, result)
def test_call_contract_without_args(self): call_flag = Integer(CallFlags.ALL).to_byte_array(signed=True, min_length=1) expected_output = ( Opcode.INITSLOT + b'\x00' + b'\x02' + Opcode.NEWARRAY0 + Opcode.LDARG1 + Opcode.LDARG0 + Opcode.PUSHDATA1 + Integer(len(call_flag)).to_byte_array(min_length=1) + call_flag + Opcode.ROT + Opcode.ROT + Opcode.SYSCALL + Interop.CallContract.interop_method_hash + Opcode.RET) path = self.get_contract_path('CallScriptHashWithoutArgs.py') output = Boa3.compile(path) self.assertEqual(expected_output, output) call_contract_path = self.get_contract_path('test_sc/list_test', 'IntList.py') Boa3.compile_and_save(call_contract_path) contract, manifest = self.get_output(call_contract_path) call_hash = hash160(contract) call_contract_path = call_contract_path.replace('.py', '.nef') engine = TestEngine() with self.assertRaises(TestExecutionException, msg=self.CALLED_CONTRACT_DOES_NOT_EXIST_MSG): self.run_smart_contract(engine, path, 'Main', call_hash, 'Main') engine.add_contract(call_contract_path) result = self.run_smart_contract(engine, path, 'Main', call_hash, 'Main') self.assertEqual([1, 2, 3], result)
def test_get_notifications(self): path = self.get_contract_path('GetNotifications.py') output, manifest = self.compile_and_save(path) script = hash160(output) engine = TestEngine() result = self.run_smart_contract(engine, path, 'without_param', []) self.assertEqual([], result) engine = TestEngine() result = self.run_smart_contract(engine, path, 'without_param', [1, 2, 3]) expected_result = [] for x in [1, 2, 3]: expected_result.append([script, 'notify', [x]]) self.assertEqual(expected_result, result) engine = TestEngine() result = self.run_smart_contract(engine, path, 'with_param', [], script) self.assertEqual([], result) engine = TestEngine() result = self.run_smart_contract(engine, path, 'with_param', [1, 2, 3], script) expected_result = [] for x in [1, 2, 3]: expected_result.append([script, 'notify', [x]]) self.assertEqual(expected_result, result) engine = TestEngine() result = self.run_smart_contract(engine, path, 'with_param', [1, 2, 3], b'\x01' * 20) self.assertEqual([], result)
def test_notification_get_variables(self): path = self.get_contract_path('NotificationGetVariables.py') output, manifest = self.compile_and_save(path) script = hash160(output) engine = TestEngine() result = self.run_smart_contract(engine, path, 'script_hash', [], expected_result_type=bytes) self.assertEqual(len(engine.notifications), 0) self.assertEqual(bytes(20), result) result = self.run_smart_contract(engine, path, 'event_name', []) self.assertEqual(len(engine.notifications), 0) self.assertEqual('', result) result = self.run_smart_contract(engine, path, 'state', []) self.assertEqual(len(engine.notifications), 0) self.assertEqual([], result) result = self.run_smart_contract(engine, path, 'script_hash', [1]) self.assertEqual(len(engine.notifications), 1) self.assertEqual(script, result) result = self.run_smart_contract(engine, path, 'event_name', [1]) self.assertEqual(len(engine.notifications), 1) self.assertEqual('notify', result) result = self.run_smart_contract(engine, path, 'state', [1]) self.assertEqual(len(engine.notifications), 1) self.assertEqual([1], result) result = self.run_smart_contract(engine, path, 'state', ['1']) self.assertEqual(len(engine.notifications), 1) self.assertEqual(['1'], result)
def test_boa2_op_call_test(self): path = self.get_contract_path('OpCallBoa2Test.py') engine = TestEngine() result = self.run_smart_contract(engine, path, 'main', 'omin', 4, 4) self.assertEqual(4, result) result = self.run_smart_contract(engine, path, 'main', 'omin', -4, 4) self.assertEqual(-4, result) result = self.run_smart_contract(engine, path, 'main', 'omin', 16, 0) self.assertEqual(0, result) result = self.run_smart_contract(engine, path, 'main', 'omax', 4, 4) self.assertEqual(4, result) result = self.run_smart_contract(engine, path, 'main', 'omax', -4, 4) self.assertEqual(4, result) result = self.run_smart_contract(engine, path, 'main', 'omax', 16, 0) self.assertEqual(16, result) from boa3.neo.cryptography import sha256, hash160 from boa3.neo.vm.type.String import String result = self.run_smart_contract(engine, path, 'main', 'sha256', 'abc', 4) self.assertEqual(sha256(String('abc').to_bytes()), result) result = self.run_smart_contract(engine, path, 'main', 'hash160', 'abc', 4) self.assertEqual(hash160(String('abc').to_bytes()), result)
def test_bytes_script_hash(self): from boa3.neo import cryptography, to_script_hash input = b'\x01\x02\x03' expected_output = cryptography.hash160(input) output = to_script_hash(input) self.assertEqual(expected_output, output)
def test_integer_script_hash(self): from boa3.neo import cryptography, to_script_hash input = Integer(123).to_byte_array() expected_output = cryptography.hash160(input) output = to_script_hash(input) self.assertEqual(expected_output, output)
def test_string_script_hash(self): from boa3.neo import cryptography, to_script_hash input = String('123').to_bytes() expected_output = cryptography.hash160(input) output = to_script_hash(input) self.assertEqual(expected_output, output)
def test_HTLC_atomic_swap(self): path = self.get_contract_path('HTLC.py') engine = TestEngine() # can not atomic_swap() without deploying first result = self.run_smart_contract( engine, path, 'atomic_swap', self.OWNER_SCRIPT_HASH, NEO_SCRIPT, 10 * 10**8, self.OTHER_ACCOUNT_1, GAS_SCRIPT, 10000 * 10**8, hash160(String('unit test').to_bytes()), signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(False, result) # deploying contract result = self.run_smart_contract( engine, path, 'deploy', signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result) # starting atomic swap by using the atomic_swap method result = self.run_smart_contract( engine, path, 'atomic_swap', self.OWNER_SCRIPT_HASH, NEO_SCRIPT, 10 * 10**8, self.OTHER_ACCOUNT_1, GAS_SCRIPT, 10000 * 10**8, hash160(String('unit test').to_bytes()), signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result)
def test_amm_set_address(self): path = self.get_contract_path('amm.py') path_zneo = self.get_contract_path('wrapped_neo.py') path_zgas = self.get_contract_path('wrapped_gas.py') engine = TestEngine() engine.add_contract(path_zneo.replace('.py', '.nef')) engine.add_contract(path_zgas.replace('.py', '.nef')) output, manifest = self.compile_and_save(path_zneo) zneo_address = hash160(output) output, manifest = self.compile_and_save(path_zgas) zgas_address = hash160(output) # won't work because the contract must have been deployed before result = self.run_smart_contract(engine, path, 'set_address', zneo_address, zgas_address, signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(False, result) result = self.run_smart_contract(engine, path, 'deploy', signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result) # won't work because it needs the owner signature result = self.run_smart_contract(engine, path, 'set_address', zneo_address, zgas_address, signer_accounts=[self.OTHER_ACCOUNT_1], expected_result_type=bool) self.assertEqual(False, result) # it will work now result = self.run_smart_contract(engine, path, 'set_address', zneo_address, zgas_address, signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result) # initialize will work once result = self.run_smart_contract(engine, path, 'set_address', zneo_address, zgas_address, signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(False, result)
def test_ghost_pause(self): engine = self.prepare_testengine() engine.add_contract(self.CONTRACT_PATH_NEF.replace('.py', '.nef')) aux_path = self.get_contract_path('test_native', 'auxiliary_contract.py') output, manifest = self.compile_and_save(self.CONTRACT_PATH_NEF.replace('.nef', '.py')) ghost_address = hash160(output) print(to_hex_str(ghost_address)) output, manifest = self.compile_and_save(aux_path) aux_address = hash160(output) print(to_hex_str(aux_address)) # when deploying, the contract will mint tokens to the owner deploy_event = engine.get_events('Deployed') self.assertEqual(1, len(deploy_event)) self.assertEqual(2, len(deploy_event[0].arguments)) # add some gas for fees add_amount = 10 * 10 ** 8 engine.add_gas(aux_address, add_amount) # pause contract fee = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'updatePause', True, signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=int) # should fail because contract is paused with self.assertRaises(TestExecutionException, msg=self.ASSERT_RESULTED_FALSE_MSG): token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', aux_address, self.TOKEN_META, self.LOCK_CONTENT, self.ROYALTIES, None, signer_accounts=[aux_address], expected_result_type=bytes) # unpause contract fee = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'updatePause', False, signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=int) # mint token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', aux_address, self.TOKEN_META, self.LOCK_CONTENT, self.ROYALTIES, None, signer_accounts=[aux_address], expected_result_type=bytes) self.print_notif(engine.notifications)
def test_HTLC_onPayment(self): path = self.get_contract_path('HTLC.py') engine = TestEngine() example_contract = self.get_contract_path( 'test_native/example_contract_for_htlc.py') transferred_amount_neo = 10 * 10**8 transferred_amount_gas = 10000 * 10**8 output, manifest = self.compile_and_save(example_contract) contract_address1 = bytes(range(20)) contract_address2 = hash160(output) output, manifest = self.compile_and_save(path) htlc_address = hash160(output) engine.add_neo(contract_address1, transferred_amount_neo) engine.add_gas(contract_address2, transferred_amount_gas) # deploying contract result = self.run_smart_contract( engine, path, 'deploy', signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result) # starting atomic swap result = self.run_smart_contract( engine, path, 'atomic_swap', contract_address1, NEO, transferred_amount_neo, contract_address2, GAS, transferred_amount_gas, hash160(String('unit test').to_bytes()), signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=bool) self.assertEqual(True, result)
def test_address_script_hash(self): from base58 import b58decode from boa3.neo import cryptography, to_script_hash input = String('Nd7eAuHsKvvzHzSPyuJQALcYCcUrcwvm5W').to_bytes() expected_output = b58decode(input)[1:21] wrong_output = cryptography.hash160(input) output = to_script_hash(input) self.assertNotEqual(wrong_output, output) self.assertEqual(expected_output, output)
def test_destroy_contract(self): path = self.get_contract_path('DestroyContract.py') output = Boa3.compile(path) engine = TestEngine() result = self.run_smart_contract(engine, path, 'Main') self.assertIsVoid(result) script_hash = hash160(output) call_contract_path = self.get_contract_path('CallScriptHash.py') with self.assertRaises(TestExecutionException): self.run_smart_contract(engine, call_contract_path, 'Main', script_hash, 'Main', [])
def test_ghost_locked_content(self): engine = self.prepare_testengine() engine.add_contract(self.CONTRACT_PATH_NEF.replace('.py', '.nef')) output, manifest = self.compile_and_save(self.CONTRACT_PATH_NEF.replace('.nef', '.py')) ghost_address = hash160(output) # when deploying, the contract will mint tokens to the owner deploy_event = engine.get_events('Deployed') self.assertEqual(1, len(deploy_event)) self.assertEqual(2, len(deploy_event[0].arguments)) # add some gas for fees add_amount = 10 * 10 ** 8 engine.add_gas(self.OTHER_ACCOUNT_1, add_amount) # check if enough balance balance = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'getFeeBalance', signer_accounts=[self.OWNER_SCRIPT_HASH], expected_result_type=int) self.assertEqual(0, balance) # mint + getLockedContentViewCount token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', self.OTHER_ACCOUNT_1, self.TOKEN_META, self.LOCK_CONTENT, self.ROYALTIES, None, signer_accounts=[self.OTHER_ACCOUNT_1], expected_result_type=bytes) views = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'getLockedContentViewCount', token, expected_result_type=int) # should have 0 views self.assertEqual(0, views) # getLockedContent content = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'getLockedContent', token, signer_accounts=[self.OTHER_ACCOUNT_1], expected_result_type=bytes) self.assertEqual(b'lockedContent', content) # getLockedContentViewCount should have 1 view views = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'getLockedContentViewCount', token, expected_result_type=int) print("views: " + str(views)) self.assertEqual(1, views) # reset views and test getLockedContentViewCount with 100 views views = 0 for i in range(0, 100): views += self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'getLockedContentViewCount', token, expected_result_type=int) self.assertEqual(100, views) self.print_notif(engine.notifications)
def test_ghost_burn(self): engine = self.prepare_testengine() engine.add_contract(self.CONTRACT_PATH_NEF.replace('.py', '.nef')) aux_path = self.get_contract_path('test_native', 'auxiliary_contract.py') output, manifest = self.compile_and_save(self.CONTRACT_PATH_NEF.replace('.nef', '.py')) ghost_address = hash160(output) print(to_hex_str(ghost_address)) output, manifest = self.compile_and_save(aux_path) aux_address = hash160(output) print(to_hex_str(aux_address)) # when deploying, the contract will mint tokens to the owner deploy_event = engine.get_events('Deployed') self.assertEqual(1, len(deploy_event)) self.assertEqual(2, len(deploy_event[0].arguments)) # add some gas for fees add_amount = 10 * 10 ** 8 engine.add_gas(aux_address, add_amount) # mint token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', aux_address, self.TOKEN_META, self.LOCK_CONTENT, self.ROYALTIES, None, signer_accounts=[aux_address], expected_result_type=bytes) # burn burn = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'burn', token, signer_accounts=[aux_address], expected_result_type=bool) print("props: " + str(burn)) # check balances after ghost_balance_after = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'balanceOf', aux_address) self.assertEqual(0, ghost_balance_after) ghost_supply_after = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'totalSupply') self.assertEqual(0, ghost_supply_after) self.print_notif(engine.notifications)
def test_ghost_onNEP17Payment(self): engine = self.prepare_testengine() engine.add_contract(self.CONTRACT_PATH_NEF.replace('.py', '.nef')) aux_path = self.get_contract_path('test_native', 'auxiliary_contract.py') output, manifest = self.compile_and_save(self.CONTRACT_PATH_NEF.replace('.nef', '.py')) ghost_address = hash160(output) print(to_hex_str(ghost_address)) output, manifest = self.compile_and_save(aux_path) aux_address = hash160(output) print(to_hex_str(aux_address)) # when deploying, the contract will mint tokens to the owner deploy_event = engine.get_events('Deployed') self.assertEqual(1, len(deploy_event)) self.assertEqual(2, len(deploy_event[0].arguments)) # add some gas for fees add_amount = 10 * 10 ** 8 engine.add_gas(aux_address, add_amount) # the smart contract will abort if some address other than GAS calls the NEP17 onPayment method with self.assertRaises(TestExecutionException, msg=self.ABORTED_CONTRACT_MSG): self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'onNEP17Payment', aux_address, add_amount, None, signer_accounts=[aux_address])
def test_notification_set_variables(self): path = self.get_contract_path('NotificationSetVariables.py') output, manifest = self.compile_and_save(path) script = hash160(output) engine = TestEngine() result = self.run_smart_contract(engine, path, 'script_hash', script, expected_result_type=bytes) self.assertEqual(script, result) result = self.run_smart_contract(engine, path, 'event_name', 'unit test') self.assertEqual('unit test', result) result = self.run_smart_contract(engine, path, 'state', (1, 2, 3)) self.assertEqual([1, 2, 3], result)
def test_get_contract(self): from boa3.neo3.contracts import CallFlags call_flag = Integer(CallFlags.ALL).to_byte_array(signed=True, min_length=1) expected_output = ( Opcode.INITSLOT + b'\x00\x01' + Opcode.LDARG0 + Opcode.PUSH1 + Opcode.PACK + Opcode.PUSHDATA1 + Integer(len(Interop.GetContract.method_name)).to_byte_array(min_length=1) + String(Interop.GetContract.method_name).to_bytes() + Opcode.PUSHDATA1 + Integer(len(constants.MANAGEMENT_SCRIPT)).to_byte_array(min_length=1) + constants.MANAGEMENT_SCRIPT + Opcode.PUSHDATA1 + Integer(len(call_flag)).to_byte_array(min_length=1) + call_flag + Opcode.ROT + Opcode.ROT + Opcode.SYSCALL + Interop.CallContract.interop_method_hash + Opcode.RET ) path = self.get_contract_path('GetContract.py') output = Boa3.compile(path) self.assertEqual(expected_output, output) engine = TestEngine() result = self.run_smart_contract(engine, path, 'main', bytes(20)) self.assertIsNone(result) call_contract_path = self.get_contract_path('test_sc/arithmetic_test', 'Addition.py') Boa3.compile_and_save(call_contract_path) script, manifest = self.get_output(call_contract_path) nef, manifest = self.get_bytes_output(call_contract_path) call_hash = hash160(script) call_contract_path = call_contract_path.replace('.py', '.nef') engine.add_contract(call_contract_path) arg_manifest = json.dumps(manifest, separators=(',', ':')) result = self.run_smart_contract(engine, path, 'main', call_hash) self.assertEqual(5, len(result)) self.assertEqual(call_hash, result[2]) self.assertEqual(nef, result[3])
def test_oracle_request(self): path = self.get_contract_path('OracleRequestCall.py') output, manifest = self.compile_and_save(path) contract_script = hash160(output) engine = TestEngine() test_url = 'abc' request_filter = 'ABC' callback = '123' gas_for_response = 1_0000000 result = self.run_smart_contract(engine, path, 'oracle_call', test_url, request_filter, callback, None, gas_for_response) self.assertIsVoid(result) oracle_requests = engine.get_events('OracleRequest', constants.ORACLE_SCRIPT) self.assertEqual(1, len(oracle_requests)) self.assertEqual(4, len(oracle_requests[0].arguments)) self.assertEqual(contract_script, oracle_requests[0].arguments[1]) self.assertEqual(test_url, oracle_requests[0].arguments[2]) self.assertEqual(request_filter, oracle_requests[0].arguments[3]) request_id = oracle_requests[0].arguments[0] with self.assertRaises(TestExecutionException): # callback function doesn't exist self.run_oracle_response(engine, request_id, OracleResponseCode.Success, b'12345') test_url = 'abc' request_filter = 'ABC' callback = 'test_callback' gas_for_response = 1_0000000 result = self.run_smart_contract(engine, path, 'oracle_call', test_url, request_filter, callback, None, gas_for_response) self.assertIsVoid(result) oracle_requests = engine.get_events('OracleRequest', constants.ORACLE_SCRIPT) self.assertEqual(2, len(oracle_requests)) self.assertEqual(4, len(oracle_requests[1].arguments)) request_id = oracle_requests[1].arguments[0] with self.assertRaises(TestExecutionException) as engine_exception: # TODO: remove this assertRaises when calling the native OracleContract is fixed result = self.run_oracle_response(engine, request_id, OracleResponseCode.Success, b'12345') self.assertIsVoid(result)
def test_htlc_atomic_swap(self): path = self.get_contract_path('htlc.py') engine = TestEngine() # starting atomic swap by using the atomic_swap method result = self.run_smart_contract( engine, path, 'atomic_swap', self.OWNER_SCRIPT_HASH, constants.NEO_SCRIPT, 10 * 10**8, self.OTHER_ACCOUNT_1, constants.GAS_SCRIPT, 10000 * 10**8, hash160(String('unit test').to_bytes()), signer_accounts=[self.OWNER_SCRIPT_HASH]) self.assertEqual(True, result)
def test_call_contract_without_args(self): path = self.get_contract_path('CallScriptHashWithoutArgs.py') call_contract_path = self.get_contract_path('test_sc/list_test', 'IntList.py') Boa3.compile_and_save(call_contract_path) contract, manifest = self.get_output(call_contract_path) call_hash = hash160(contract) call_contract_path = call_contract_path.replace('.py', '.nef') engine = TestEngine() with self.assertRaises(TestExecutionException, msg=self.CALLED_CONTRACT_DOES_NOT_EXIST_MSG): self.run_smart_contract(engine, path, 'Main', call_hash, 'Main') engine.add_contract(call_contract_path) result = self.run_smart_contract(engine, path, 'Main', call_hash, 'Main') self.assertEqual([1, 2, 3], result)
def to_script_hash(data_bytes: bytes) -> bytes: """ Converts a data to a script hash. :param data_bytes: data to hash. :type data_bytes: bytearray or bytes :return: the scripthash of the data :rtype: bytes """ from boa3.neo import cryptography from base58 import b58decode try: base58_decoded = b58decode(data_bytes)[1:] # first byte is the address version from boa3.constants import SIZE_OF_INT160 return bytes(base58_decoded[:SIZE_OF_INT160]) except BaseException: return cryptography.hash160(data_bytes)