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 to_json(self) -> Dict[str, Any]: return { 'signers': [signer.to_json() for signer in self._signers], 'witnesses': [witness.to_json() for witness in self._witnesses], 'attributes': [attr.to_json() for attr in self._attributes], 'script': to_hex_str(self._script) }
def _nef_hash(self) -> str: """ Gets the string representation of the hash of the nef file :return: the hex string representation of the hash """ return to_hex_str(self._nef.script_hash)
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_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 to_json(self, path: Union[str, UInt160], method: str, *args: Any) -> Dict[str, Any]: return { 'path': path if isinstance(path, str) else '', 'scripthash': str(path) if isinstance(path, UInt160) else None, 'method': method, 'arguments': [contract_parameter_to_json(x) for x in args], 'storage': self._storage.to_json(), 'contracts': [{ 'nef': contract_path } for contract_path in self._contract_paths], 'signerAccounts': [to_hex_str(address) for address in self._accounts], 'height': self.height, 'blocks': [block.to_json() for block in self.blocks] }
def __str__(self) -> str: """ Convert the data to a human readable format (data is in reverse byte order). """ return to_hex_str(self._data)
def is_valid_identifier(self, item: str) -> bool: # valid identifiers are nef path or a representation of the script hash return (item == self._nef_path or item == self._script_hash or item == to_hex_str(self._script_hash))
def __str__(self) -> str: return '[{0}] {1}'.format(to_hex_str(self.origin), self._message)
def __str__(self) -> str: return '[{0}] {1}'.format(to_hex_str(self.origin), self._event_name)
def test_ghost_transfer(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) properties = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'properties', token) 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) # check owner before ghost_owner_of_before = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'ownerOf', token) print("owner of before: " + str(ghost_owner_of_before)) # transfer result = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'transfer', self.OTHER_ACCOUNT_1, token, None, signer_accounts=[aux_address], expected_result_type=bool) self.assertEqual(True, result) # check owner after ghost_owner_of_after = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'ownerOf', token) print("owner of after: " + str(ghost_owner_of_after)) self.assertEqual(ghost_owner_of_after, self.OTHER_ACCOUNT_1) # check balances after ghost_balance_after_transfer = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'balanceOf', aux_address) ghost_supply_after_transfer = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'totalSupply') print("balance nft after transfer: " + str(ghost_balance_after_transfer)) self.assertEqual(0, ghost_balance_after_transfer) self.assertEqual(1, ghost_supply_after_transfer) # try to transfer non existing token id with self.assertRaises(TestExecutionException, msg=self.ASSERT_RESULTED_FALSE_MSG): result = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'transfer', self.OTHER_ACCOUNT_1, bytes('thisisanonexistingtoken', 'utf-8'), None, signer_accounts=[aux_address], expected_result_type=bool) self.print_notif(engine.notifications)
def test_ghost_gas_cost(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(aux_address, add_amount) # mint token with no meta, no lock content, no royalties token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', aux_address, bytes(1), bytes(0), bytes(0), None, signer_accounts=[aux_address], expected_result_type=bytes) gasConsumed = str(int(engine.gas_consumed) / 10 ** 8) print("token with no meta, no lock content, no royalties: " + gasConsumed + " GAS") # mint token with meta, no lock content, no royalties token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', aux_address, self.TOKEN_META, bytes(0), bytes(0), None, signer_accounts=[aux_address], expected_result_type=bytes) gasConsumed = str(int(engine.gas_consumed) / 10 ** 8) print("token with meta, no lock content, no royalties: " + gasConsumed + " GAS") # mint token with meta, lock content, no royalties token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', aux_address, self.TOKEN_META, self.LOCK_CONTENT, bytes(0), None, signer_accounts=[aux_address], expected_result_type=bytes) gasConsumed = str(int(engine.gas_consumed) / 10 ** 8) print("token with meta, lock content, no royalties: " + gasConsumed + " GAS") # mint token with meta, no lock content, royalties token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', aux_address, self.TOKEN_META, bytes(0), self.ROYALTIES, None, signer_accounts=[aux_address], expected_result_type=bytes) gasConsumed = str(int(engine.gas_consumed) / 10 ** 8) print("token with meta, no lock content, royalties: " + gasConsumed + " GAS") # mint token with meta, lock content, royalties 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) gasConsumed = str(int(engine.gas_consumed) / 10 ** 8) print("token with meta, lock content, royalties: " + gasConsumed + " GAS") tokenMeta = bytes('{ "name": "GHOST3", "description": "A ghost shows up", "image": "{some image URI}", "name": "GHOST3", "description": "A ghost shows up", "image": "{some image URI}", "name": "GHOST3", "description": "A ghost shows up", "image": "{some image URI}", "name": "GHOST3", "description": "A ghost shows up", "image": "{some image URI}", "tokenURI": "{some URI}" }', 'utf-8') lockedContent = bytes('123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910', 'utf-8') royalties = bytes('[{"address": "someaddress", "value": 20}, {"address": "someaddress2", "value": 30},{"address": "someaddress", "value": 20}, {"address": "someaddress2", "value": 30},{"address": "someaddress", "value": 20}, {"address": "someaddress2", "value": 30}]', 'utf-8') # mint high end token token = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'mint', aux_address, tokenMeta, lockedContent, royalties, None, signer_accounts=[aux_address], expected_result_type=bytes) gasConsumed = str(int(engine.gas_consumed) / 10 ** 8) print("token with heavy meta, heavy lock content, heavy royalties: " + gasConsumed + " GAS") # get locked content content = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'getLockedContent', token, signer_accounts=[aux_address], expected_result_type=bytes) gasConsumed = str(int(engine.gas_consumed) / 10 ** 8) print("get locked content: " + gasConsumed + " GAS") # burn token burn = self.run_smart_contract(engine, self.CONTRACT_PATH_NEF, 'burn', token, signer_accounts=[aux_address], expected_result_type=bool) gasConsumed = str(int(engine.gas_consumed) / 10 ** 8) print("burn: " + gasConsumed + " GAS")