-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#86drpnck9 - Refactor example_tests/test_update_contract.py to use Bo…
…aConstructor
- Loading branch information
Showing
1 changed file
with
55 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,101 +1,96 @@ | ||
import json | ||
|
||
from boa3_test.tests.boa_test import BoaTest # needs to be the first import to avoid circular imports | ||
from neo3.contracts.contract import CONTRACT_HASHES | ||
from neo3.wallet import account | ||
|
||
from boa3.internal import constants | ||
from boa3.internal.neo.vm.type.String import String | ||
from boa3.internal.neo3.vm import VMState | ||
from boa3_test.tests.test_drive import neoxp | ||
from boa3_test.tests.test_drive.testrunner.boa_test_runner import BoaTestRunner | ||
from boa3_test.tests import boatestcase | ||
from boa3_test.tests.event import UpdateEvent | ||
|
||
|
||
class TestUpdateContractTemplate(BoaTest): | ||
class TestUpdateContractTemplate(boatestcase.BoaTestCase): | ||
default_folder: str = 'examples' | ||
|
||
OWNER = neoxp.utils.get_account_by_name('owner') | ||
OTHER_ACCOUNT = neoxp.utils.get_account_by_name('testAccount1') | ||
owner: account.Account | ||
other_account: account.Account | ||
|
||
GAS_TO_DEPLOY = 1000 * 10 ** 8 | ||
|
||
def test_update_contract_compile(self): | ||
path = self.get_contract_path('update_contract.py') | ||
path_new = self.get_contract_path('examples/auxiliary_contracts', 'update_contract.py') | ||
self.compile(path) | ||
self.compile(path_new) | ||
@classmethod | ||
def setupTestCase(cls): | ||
cls.owner = cls.node.wallet.account_new(label='owner', password='123') | ||
cls.other_account = cls.node.wallet.account_new(label='otherAccount', password='123') | ||
|
||
def test_update_contract(self): | ||
path, _ = self.get_deploy_file_paths('update_contract.py') | ||
runner = BoaTestRunner(runner_id=self.method_name()) | ||
super().setupTestCase() | ||
|
||
invokes = [] | ||
expected_results = [] | ||
@classmethod | ||
async def asyncSetupClass(cls) -> None: | ||
await super().asyncSetupClass() | ||
|
||
test_account = self.OTHER_ACCOUNT | ||
test_account_script_hash = test_account.script_hash.to_array() | ||
await cls.transfer(CONTRACT_HASHES.GAS_TOKEN, cls.genesis.script_hash, cls.owner.script_hash, 100) | ||
await cls.transfer(CONTRACT_HASHES.GAS_TOKEN, cls.genesis.script_hash, cls.other_account.script_hash, 100) | ||
|
||
runner.add_gas(self.OWNER.address, self.GAS_TO_DEPLOY) | ||
update_contract = runner.deploy_contract(path, account=self.OWNER) | ||
runner.update_contracts(export_checkpoint=True) | ||
await cls.set_up_contract('update_contract.py', signing_account=cls.owner) | ||
|
||
tx_deploy_notifications = runner.get_transaction_result(update_contract.tx_id).executions[0].notifications | ||
# Transfer emitted when deploying the smart contract | ||
self.assertEqual(2, len(tx_deploy_notifications)) | ||
self.assertEqual(1, len([notification | ||
for notification in tx_deploy_notifications if notification.name == 'Transfer'])) | ||
self.assertEqual(1, len([notification | ||
for notification in tx_deploy_notifications if notification.name == 'Deploy'])) | ||
def test_update_contract_compile(self): | ||
self.assertCompile('update_contract.py') | ||
self.assertCompile('update_contract.py', root_folder='examples/auxiliary_contracts') | ||
|
||
async def test_update_contract(self): | ||
# Saving user's balance before calling method to compare it later | ||
tokens_before = runner.call_contract(path, 'balanceOf', test_account_script_hash) | ||
tokens_before, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
# The bugged method is being called and the user is able to receive tokens for free | ||
invokes.append(runner.call_contract(path, 'method', test_account_script_hash)) | ||
expected_results.append(None) | ||
result, notifications = await self.call('method', [self.other_account.script_hash], return_type=None, signing_accounts=[self.other_account]) | ||
self.assertIsNone(result) | ||
|
||
tokens_after = runner.call_contract(path, 'balanceOf', test_account_script_hash) | ||
tokens_after, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
runner.execute() | ||
self.assertEqual(VMState.HALT, runner.vm_state, msg=runner.error) | ||
transfer_events = self.filter_events(notifications, notification_type=boatestcase.Nep17TransferEvent) | ||
self.assertEqual(1, len(transfer_events)) | ||
|
||
# The amount of tokens will be higher after calling the method | ||
self.assertGreater(tokens_after.result, tokens_before.result) | ||
|
||
transfer_events = runner.get_events('Transfer', origin=update_contract) | ||
self.assertEqual(1, len(transfer_events)) | ||
self.assertGreater(tokens_after, tokens_before) | ||
|
||
# new smart contract that has the bug fixed | ||
path_new = self.get_contract_path('examples/auxiliary_contracts', 'update_contract.py') | ||
new_nef, new_manifest = self.get_bytes_output(path_new) | ||
new_nef, new_manifest = self.get_serialized_output(path_new) | ||
|
||
arg_manifest = String(json.dumps(new_manifest, separators=(',', ':'))).to_bytes() | ||
|
||
# The smart contract will be updated to fix the bug in the method | ||
invokes.append(runner.call_contract(path, 'update_sc', new_nef, arg_manifest, None)) | ||
expected_results.append(None) | ||
|
||
runner.execute(account=self.OWNER) | ||
self.assertEqual(VMState.HALT, runner.vm_state, msg=runner.error) | ||
result, notifications = await self.call('update_sc', [new_nef, arg_manifest, None], return_type=None, signing_accounts=[self.owner]) | ||
self.assertIsNone(result) | ||
|
||
# An `Update` event was be emitted after the update | ||
event_update = runner.get_events('Update') | ||
self.assertEqual(1, len(event_update)) | ||
|
||
runner.run_contract(path, 'update_sc', new_nef, arg_manifest, None, account=self.OWNER) | ||
update_events = self.filter_events(notifications, notification_type=UpdateEvent) | ||
self.assertEqual(1, len(update_events)) | ||
|
||
# Saving user's balance before calling method to compare it later | ||
tokens_before = runner.call_contract(path, 'balanceOf', test_account_script_hash) | ||
tokens_before, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
# Now, when method is called, it won't mint new tokens to any user that called it | ||
invokes.append(runner.call_contract(path, 'method', test_account_script_hash)) | ||
expected_results.append(None) | ||
result, notifications = await self.call('method', [self.other_account.script_hash], return_type=None, signing_accounts=[self.other_account]) | ||
self.assertIsNone(result) | ||
|
||
transfer_events = self.filter_events(notifications, notification_type=boatestcase.Nep17TransferEvent) | ||
self.assertEqual(0, len(transfer_events)) | ||
|
||
# The amount of tokens now is the same before and after calling the method | ||
tokens_after = runner.call_contract(path, 'balanceOf', test_account_script_hash) | ||
tokens_after, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
self.assertEqual(tokens_after, tokens_before) | ||
|
||
runner.get_contract(constants.NEO_SCRIPT) | ||
# If the signing account is the owner, then the method works, and it will mint the new tokens | ||
tokens_before, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
runner.execute(account=test_account) | ||
self.assertEqual(VMState.HALT, runner.vm_state, msg=runner.error) | ||
result, notifications = await self.call('method', [self.other_account.script_hash], return_type=None, signing_accounts=[self.owner]) | ||
self.assertIsNone(result) | ||
|
||
self.assertEqual(tokens_after.result, tokens_before.result) | ||
transfer_events = self.filter_events(notifications, notification_type=boatestcase.Nep17TransferEvent) | ||
self.assertEqual(1, len(transfer_events)) | ||
|
||
# The amount of tokens will be higher after calling the method | ||
tokens_after, _ = await self.call('balanceOf', [self.other_account.script_hash], return_type=int) | ||
|
||
for x in range(len(invokes)): | ||
self.assertEqual(expected_results[x], invokes[x].result) | ||
self.assertGreater(tokens_after, tokens_before) |