Skip to content

Contract verification is a difficult step on ZKsync and forces to import lib with absolute path #251

@s3bc40

Description

@s3bc40

Blockscout (and Etherscan closely)

[networks.zksync-sepolia]
is_zksync = true
url = "$ZKSYNC_SEPOLIA_RPC_ALCHEMY"
chain_id = 300
default_account_name = "$DEFAULT_ACCOUNT_NAME_ZKSYNC"
explorer_uri = "https://zksync-sepolia.blockscout.com"
explorer_type = "blockscout"
prompt_live = true
save_to_db = true
live_or_staging = true
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/moccasin/commands/run.py", line 81, in run_script
    result = module.moccasin_main()
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/script/deploy_fund_me.py", line 28, in moccasin_main
    return deploy()
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/script/deploy_fund_me.py", line 18, in deploy
    result = active_network.moccasin_verify(fund_me_contract)
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/moccasin/config.py", line 226, in moccasin_verify
    return boa_zksync.verify(contract, verifier_instance)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/boa_zksync/__init__.py", line 43, in verify
    return verifier.verify(
           ~~~~~~~~~~~~~~~^
        address=contract.address,
        ^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<3 lines>...
        **kwargs,
        ^^^^^^^^^
    )
    ^
TypeError: Blockscout.verify() missing 1 required positional argument: 'chain_id'

Adding chain_id in config.py:

  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/boa/verifiers.py", line 116, in verify
    response.raise_for_status()
    ~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/requests/models.py", line 1024, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://zksync-sepolia.blockscout.com/api/v2/smart-contracts/0xc81D559Cd0160E12A01aB588431252978ACb7479/verification/via/vyper-standard-input?apikey=

Changing to zksyncexplorer in toml:

  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/boa_zksync/__init__.py", line 43, in verify
    return verifier.verify(
           ~~~~~~~~~~~~~~~^
        address=contract.address,
        ^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<3 lines>...
        **kwargs,
        ^^^^^^^^^
    )
    ^
TypeError: ZksyncExplorer.verify() got an unexpected keyword argument 'chain_id'

Removing chain_id in config.py:

  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/requests/models.py", line 1024, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://zksync-sepolia.blockscout.com/contract_verification

Which seems logical, and even if I change the contract_verification to contract-verification, it will return the HTML text so that's not how we want it work, even though in the boa-zksync class ZksyncExplorer:

def verify(
        self,
        address: Address,
        contract_name: str,
        solc_json: dict,
        constructor_calldata: bytes = b"",
        wait: bool = False,
    ) -> Optional["VerificationResult"]:
        """
        Verify the Vyper contract on Blockscout.
        :param address: The address of the contract.
        :param contract_name: The name of the contract.
        :param solc_json: The solc_json output of the Vyper compiler.
        :param constructor_calldata: The calldata for the constructor.
        :param wait: Whether to return a VerificationResult immediately
                     or wait for verification to complete. Defaults to False
        """
        url = f"{self.uri}/contract_verification"

ZKsync explorer

[networks.zksync-sepolia]
is_zksync = true
url = "$ZKSYNC_SEPOLIA_RPC_ALCHEMY"
chain_id = 300
default_account_name = "$DEFAULT_ACCOUNT_NAME_ZKSYNC"
explorer_uri = "https://explorer.sepolia.era.zksync.dev"
explorer_type = "zksyncexplorer"
prompt_live = true
save_to_db = true
live_or_staging = true
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/moccasin/commands/run.py", line 81, in run_script
    result = module.moccasin_main()
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/script/deploy_fund_me.py", line 28, in moccasin_main
    return deploy()
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/script/deploy_fund_me.py", line 19, in deploy
    result.wait_for_verification()
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/boa/verifiers.py", line 160, in wait_for_verification
    self.verifier.wait_for_verification(self.identifier)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/boa_zksync/verifiers.py", line 96, in wait_for_verification
    if self.is_verified(verification_id):
       ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/home/s3bc40/perso-projects/web3-portfolio/moccasin/.venv/lib/python3.13/site-packages/boa_zksync/verifiers.py", line 115, in is_verified
    raise ValueError(f"Verification failed: {json['error']}")
ValueError: Verification failed: zkvyper error: /tmp/.tmprsCDeo/etc/vyper-bin/0.4.1/vyper error: vyper.exceptions.ModuleNotFound: snekmate.auth.ownable

  contract "tmp/.tmpWvLub3/fund_me.vy:13", line 13:0 
       12 # @dev Import the ownable module for ownership functionality.
  ---> 13 from snekmate.auth import ownable
  --------^
       14

[PYI-3330:ERROR] Failed to execute script 'vyper_compile' due to unhandled exception!

Problem with external lib, idk if it is something already known as an issue. It seems to be a temp subprocess which maybe break moccasin dependencies.

BUT

Changing into from lib.pypi.snekmate.auth import ownable:

The transactions run on this will actually be broadcast/transmitted, spending gas associated with your account. Are you sure you wish to continue?Type 'y' or 'Y' and hit 'ENTER' or 'RETURN' to continue:y
Enter your password for keystore zksepolia_fundme: 
tx broadcasted: 0x36ff5bd5220440939e24ca5ba5d305bd395871a7c6461eed4ec638ac258b940b
0x36ff5bd5220440939e24ca5ba5d305bd395871a7c6461eed4ec638ac258b940b mined in block 0x76af4598fcefd482aa199a270f52d7abaea80066efc0180dbb2a577c4fead2a9!
Contract deployed at 0x44a0D5f0C23B39199470364659D6Fdf33304fC1D
ERROR: Could not add contract_name to database for contract zktoken.
tx broadcasted: 0x8de504c6744261568488ca1f529c437103d1aba20929d5c7dfcf05542922e2a1
0x8de504c6744261568488ca1f529c437103d1aba20929d5c7dfcf05542922e2a1 mined in block 0xe45acc119d1c715851faa5c3a805df1ff78b44f16ddd1eb962f5a8746ac3d68e!
Contract deployed at 0xa1E4C493C6c99224e9aB1eC6F90522505EAff401
Contract verified!

So maybe we need to take check how to make this work without requiring the user to change the lib import before each verification 🤔

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions