Skip to content

Commit

Permalink
fix: Blockscout compiler version
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielSchiavini committed Oct 15, 2024
1 parent 034c0ae commit f502998
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 19 deletions.
53 changes: 39 additions & 14 deletions boa/verifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from typing import Optional

import requests
from cached_property import cached_property

from boa.util.abi import Address
from boa.util.open_ctx import Open
Expand Down Expand Up @@ -56,28 +57,44 @@ def verify(

url = f"{self.uri}/api/v2/smart-contracts/{address}/"
url += f"verification/via/vyper-standard-input?apikey={api_key}"
data = {
"compiler_version": solc_json["compiler_version"],
"license_type": license_type,
}
files = {
"files[0]": (
contract_name,
json.dumps(solc_json).encode("utf-8"),
"application/json",
)
}

response = requests.post(url, data=data, files=files)

version = self._get_compiler_version(solc_json["compiler_version"])
solc_json = {**solc_json, "compiler_version": version}
data = {"compiler_version": version, "license_type": license_type}
file = (contract_name, json.dumps(solc_json), "application/json")

response = requests.post(url, data=data, files={"files[0]": file})
response.raise_for_status()
print(response.json().get("message")) # usually verification started
# print(f"Sent {data} to {url} with {file}")

if not wait:
return VerificationResult(address, self)

self.wait_for_verification(address)
return None

def _get_compiler_version(self, compiler_version) -> str:
"""
Runs a partial match based on the compiler version.
Blockscout only accepts exact matches, but vyper can have a different
commit hash length depending on the version and installation method.
Raises a ValueError if no match is found or if multiple matches are found.
"""
supported = self.supported_versions
match [v for v in supported if compiler_version in v]:
case [version]:
return version
case []:
err = "Could not find a matching compiler version on Blockscout. "
err += f"Given: {compiler_version}, supported: {supported}."
raise Exception(err)
case multiple:
err = "Ambiguous compiler version for Blockscout verification. "
err += f"Given: {compiler_version}, found: {multiple}."
raise Exception(err)

def wait_for_verification(self, address: Address) -> None:
"""
Waits for the contract to be verified on Blockscout.
Expand All @@ -94,7 +111,7 @@ def wait_for_verification(self, address: Address) -> None:
time.sleep(wait_time.total_seconds())
wait_time *= self.backoff_factor

raise TimeoutError("Timeout waiting for verification to complete")
raise TimeoutError(f"Timeout waiting for verification of {address}")

def is_verified(self, address: Address) -> bool:
api_key = self.api_key or ""
Expand All @@ -106,6 +123,14 @@ def is_verified(self, address: Address) -> bool:
response.raise_for_status()
return response.json().get("is_verified", False)

@cached_property
def supported_versions(self) -> list[str]:
response = requests.get(
"https://http.sc-verifier.services.blockscout.com/api/v2/verifier/vyper/versions"
)
response.raise_for_status()
return response.json()["compilerVersions"]


_verifier = Blockscout()

Expand Down
22 changes: 17 additions & 5 deletions tests/integration/network/sepolia/test_sepolia_env.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import os
from random import randint, sample
from string import ascii_lowercase

import pytest

Expand Down Expand Up @@ -38,13 +40,23 @@ def simple_contract():
return boa.loads(code, STARTING_SUPPLY)


def test_verify(simple_contract):
def test_verify():
# generate a random contract so the verification will actually be done again
name = "".join(sample(ascii_lowercase, 10))
contract = boa.loads(
f"""
@external
def {name}() -> uint256:
return {randint(0, 2**256 - 1)}
""",
name=name,
)

api_key = os.getenv("BLOCKSCOUT_API_KEY")
blockscout = Blockscout("https://eth-sepolia.blockscout.com", api_key)
with boa.set_verifier(blockscout):
result = boa.verify(simple_contract)
result.wait_for_verification()
assert result.is_verified()
result = boa.verify(contract, blockscout)
result.wait_for_verification()
assert result.is_verified()


def test_env_type():
Expand Down

0 comments on commit f502998

Please sign in to comment.