nucypher / nucypher-contracts

Ethereum contracts supporting TACo applications on the Threshold Network.
18 stars 11 forks source link

Script Upgrade Coordinator on Lynx fails when it tries to update the registry #288

Open manumonti opened 4 months ago

manumonti commented 4 months ago

https://github.com/nucypher/nucypher-contracts/blob/07ce241f1186e46342fc74a213ab81d5a791862f/scripts/lynx/upgrade_coordinator.py#L29

This script fails on the last step:

deployer.finalize(deployments=deployments)

After a little investigation, the problem seems that the returned deployment coordinator doesn't contain the transaction hash. See https://github.com/vzotova/nucypher-contracts/blob/free-fee-model/deployment/registry.py#L63.

Error trace:

Traceback (most recent call last):
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/bin/ape", line 8, in <module>
    sys.exit(cli())
             ^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/ape/_cli.py", line 104, in invoke
    return super().invoke(ctx)
           ^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/ape_run/_cli.py", line 74, in invoke
    return super().invoke(ctx)
           ^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/ape/cli/commands.py", line 98, in invoke
    return self._invoke(ctx, provider=provider)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/ape/cli/commands.py", line 135, in _invoke
    return ctx.invoke(self.callback or (lambda: None), **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/ape_run/_cli.py", line 151, in call
    main_ns["main"]()  # Execute the script
    ^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/scripts/lynx/upgrade_coordinator.py", line 29, in main
    deployer.finalize(deployments=deployments)
  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/deployment/params.py", line 647, in finalize
    registry_from_ape_deployments(
  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/deployment/registry.py", line 200, in registry_from_ape_deployments
    entries = _get_entries(contract_instances=deployments, registry_names=registry_names)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/deployment/registry.py", line 82, in _get_entries
    entry = _get_entry(contract_instance=contract_instance, registry_names=registry_names)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/deployment/registry.py", line 63, in _get_entry
    receipt = chain.get_receipt(contract_instance.txn_hash)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/ape/managers/chain.py", line 1724, in get_receipt
    receipt = self.chain_manager.history[transaction_hash]
              ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/lib/python3.11/functools.py", line 946, in _method
    return method.__get__(obj, cls)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/.pyenv/versions/3.11.6/envs/nucypher-contracts/lib/python3.11/site-packages/ape/managers/chain.py", line 517, in __getitem__
    raise NotImplementedError(f"Cannot use type of {type(key)} as Index")
NotImplementedError: Cannot use type of <class 'NoneType'> as Index

Note: this line was changed from receipt = contract_instance.receipt to receipt = chain.get_receipt(contract_instance.txn_hash) because when we updated the ape dependencies, this line failed with the following error:

  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/scripts/lynx/deploy_coordinator.py", line 22, in main
    deployer.finalize(deployments=deployments)
  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/deployment/params.py", line 647, in finalize
    registry_from_ape_deployments(
  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/deployment/registry.py", line 200, in registry_from_ape_deployments
    entries = _get_entries(contract_instances=deployments, registry_names=registry_names)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/deployment/registry.py", line 82, in _get_entries
    entry = _get_entry(contract_instance=contract_instance, registry_names=registry_names)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/manumonti/Projects/nucypher/nucypher-contracts/deployment/registry.py", line 63, in _get_entry
    receipt = contract_instance.receipt
              ^^^^^^^^^^^^^^^^^^^^^^^^^

ERROR: (ApeAttributeError) 'Coordinator' has no attribute 'receipt'.
derekpierre commented 4 months ago

Right. For a proxy upgrade there is no tx_hash on the proxy contract instance.

We may have to go through the ChainManager differently.

Perhaps...

creation = chain.get_creation_metadata(contract_instance.address)
receipt = creation.receipt
manumonti commented 4 months ago

Update: this fails for every script that upgrades a proxy contract instance as derek mentioned.

So this script also fails with mainnet/deploy_bqeth.py script.

A workaround is to modify _get_entry() function in deployment/registry.py so a receipt object is always created:

def _get_entry(
    contract_instance: ContractInstance, registry_names: Dict[ContractName, ContractName]
) -> RegistryEntry:
    contract_abi = _get_abi(contract_instance)
    contract_name = _get_name(contract_instance=contract_instance, registry_names=registry_names)

    class Object(object):
        pass

    receipt = Object()
    receipt.transaction = Object()
    receipt.transaction.chain_id = 137
    receipt.transaction.sender = "0x00000"
    receipt.txn_hash = "0x00000000000"
    receipt.block_number = 0
    receipt.deployer = "0x0000000"

    if(contract_instance.txn_hash is not None):
        receipt = chain.get_receipt(contract_instance.txn_hash)

    entry = RegistryEntry(
        name=contract_name,
        address=to_checksum_address(contract_instance.address),
        abi=contract_abi,
        chain_id=receipt.transaction.chain_id,
        tx_hash=receipt.txn_hash,
        block_number=receipt.block_number,
        deployer=receipt.transaction.sender,
    )
    return entry