Skip to content

Commit

Permalink
Merge branch 'main' into liav/unit-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
liav-certora committed Dec 18, 2024
2 parents e5d6a68 + 28283fe commit 914ec12
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 88 deletions.
8 changes: 0 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@ jobs:

env:
ETHSCAN_API_KEY: ${{ secrets.ETHSCAN_API_KEY }}
POLYSCAN_API_KEY: ${{ secrets.POLYSCAN_API_KEY }}
OPTSCAN_API_KEY: ${{ secrets.OPTSCAN_API_KEY }}
ARBSCAN_API_KEY: ${{ secrets.ARBSCAN_API_KEY }}
BASESCAN_API_KEY: ${{ secrets.BASESCAN_API_KEY }}
GNOSCAN_API_KEY: ${{ secrets.GNOSCAN_API_KEY }}
SCRSCAN_API_KEY: ${{ secrets.SCRSCAN_API_KEY }}
BSCSCAN_API_KEY: ${{ secrets.BSCSCAN_API_KEY }}
ZKSCAN_API_KEY: ${{ secrets.ZKSCAN_API_KEY }}
QUORUM_PATH: "."
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

Expand Down
84 changes: 32 additions & 52 deletions Quorum/apis/block_explorers/chains_api.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from dataclasses import dataclass
import requests
from typing import Callable, Any
import os
import requests
from typing import Any
import json

from eth_abi import encode
Expand All @@ -10,20 +9,6 @@
from Quorum.utils.chain_enum import Chain
from Quorum.apis.block_explorers.source_code import SourceCode


@dataclass
class APIinfo:
"""
Data class for storing API base URL and a function to retrieve the API key.
Attributes:
base_url (str): The base URL of the blockchain explorer API.
api_key (Callable[[], str]): A function to retrieve the API key for the explorer.
"""
base_url: str
api_key: Callable[[], str]


class ChainAPI:
"""
A class to interact with blockchain explorer APIs for fetching contract ABIs,
Expand All @@ -33,32 +18,22 @@ class ChainAPI:
chain_mapping (dict): Maps Chain enum to APIinfo containing base URL and API key function.
"""

# Maps Chain enums to their corresponding API base URL and API key retrieval function.
chain_mapping = {
Chain.ETH: APIinfo(base_url="https://api.etherscan.io/api",
api_key=lambda: os.getenv('ETHSCAN_API_KEY')),
Chain.ARB: APIinfo(base_url="https://api.arbiscan.io/api",
api_key=lambda: os.getenv('ARBSCAN_API_KEY')),
Chain.AVAX: APIinfo(base_url="https://api.routescan.io/v2/network/mainnet/evm/43114/etherscan/api",
api_key=lambda: os.getenv('AVAXSCAN_API_KEY', "FREE")),
Chain.BASE: APIinfo(base_url="https://api.basescan.org/api",
api_key=lambda: os.getenv('BASESCAN_API_KEY')),
Chain.BSC: APIinfo(base_url="https://api.bscscan.com/api",
api_key=lambda: os.getenv('BSCSCAN_API_KEY')),
Chain.GNO: APIinfo(base_url="https://api.gnosisscan.io/api",
api_key=lambda: os.getenv('GNOSCAN_API_KEY')),
Chain.MET: APIinfo(base_url="https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan/api",
api_key=lambda: os.getenv('METSCAN_API_KEY', "FREE")),
Chain.OPT: APIinfo(base_url="https://api-optimistic.etherscan.io/api",
api_key=lambda: os.getenv('OPTSCAN_API_KEY')),
Chain.POLY: APIinfo(base_url="https://api.polygonscan.com/api",
api_key=lambda: os.getenv('POLYSCAN_API_KEY')),
Chain.SCR: APIinfo(base_url="https://api.scrollscan.com/api",
api_key=lambda: os.getenv('SCRSCAN_API_KEY')),
Chain.ZK: APIinfo(base_url="https://api-era.zksync.network/api",
api_key=lambda: os.getenv('ZKSCAN_API_KEY'))
# Mapping between Chain enum members and their corresponding Chain IDs
CHAIN_ID_MAP = {
Chain.ETH: 1,
Chain.ARB: 42161,
Chain.AVAX: 43114,
Chain.BASE: 8453,
Chain.BSC: 56,
Chain.GNO: 100,
Chain.OPT: 10,
Chain.POLY: 137,
Chain.SCR: 534352,
Chain.ZK: 324
}

BASE_URL = "https://api.etherscan.io/v2/api?chainid={chain_id}&apikey={api_key}"

def __init__(self, chain: Chain) -> None:
"""
Initializes the ChainAPI with the appropriate blockchain network's base URL and API key.
Expand All @@ -69,15 +44,20 @@ def __init__(self, chain: Chain) -> None:
Raises:
ValueError: If the selected chain is unsupported or the API key is not set.
"""
if chain not in self.chain_mapping:
raise ValueError(f"Unsupported chain: {chain}. Available chains: {', '.join([c.name for c in self.chain_mapping.keys()])}")

api_info = self.chain_mapping[chain]
self.api_key = api_info.api_key()
if not self.api_key:
raise ValueError(f"{chain}SCAN_API_KEY environment variable is not set.")
if chain not in self.CHAIN_ID_MAP and chain != Chain.MET:
raise ValueError(f"Unsupported chain: {chain}. Available chains: {', '.join([c.name for c in self.CHAIN_ID_MAP.keys()])}")
# MET is not supported via ETHScan API
if chain == Chain.MET:
self.base_url = "https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan/api"
else:
chain_id = self.CHAIN_ID_MAP[chain]
api_key = os.getenv("ETHSCAN_API_KEY")
if not api_key:
raise ValueError(f"{chain}SCAN_API_KEY environment variable is not set.")

self.base_url = self.BASE_URL.format(chain_id=chain_id, api_key=api_key)

self.base_url = f"{api_info.base_url}?apikey={self.api_key}"
self.session = requests.Session()

def get_source_code(self, proposal_address: str) -> list[SourceCode]:
"""
Expand All @@ -93,7 +73,7 @@ def get_source_code(self, proposal_address: str) -> list[SourceCode]:
ValueError: If the API request fails or the source code could not be retrieved.
"""
url = f"{self.base_url}&module=contract&action=getsourcecode&address={proposal_address}"
response = requests.get(url)
response = self.session.get(url)
response.raise_for_status()
data = response.json()

Expand Down Expand Up @@ -128,7 +108,7 @@ def get_contract_abi(self, contract_address: str) -> list[dict]:
ValueError: If the API request fails or the ABI could not be retrieved.
"""
url = f"{self.base_url}&module=contract&action=getabi&address={contract_address}"
response = requests.get(url)
response = self.session.get(url)
response.raise_for_status()
data = response.json()

Expand Down Expand Up @@ -169,7 +149,7 @@ def call_contract_function(self, contract_address: str, function_name: str, argu

# Step 5: Make the request to the blockchain explorer eth_call endpoint
url = f"{self.base_url}&module=proxy&action=eth_call&to={contract_address}&data={data}&tag=latest"
response = requests.get(url)
response = self.session.get(url)
response.raise_for_status()

# Step 6: Handle the response
Expand Down
4 changes: 1 addition & 3 deletions Quorum/execution.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{
"Aave": {
"AVAX": {
"Proposals": [
"0x96cecD5D7A4b740f6a8eF2787fe88E0Bd480d79f"
]
"Proposals": []
},
"ETH": {
"Proposals": [
Expand Down
32 changes: 8 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,37 +34,20 @@ As part of tool process, the tool will use solcx to parse the contract code to A

## Environment Variables

Before using Quorum, you need to configure the following environment variables for API keys corresponding to each blockchain. These keys are necessary to access the respective blockchain explorers:

- **ETHSCAN_API_KEY:** API key for Etherscan (Ethereum).
- **ARBSCAN_API_KEY:** API key for Arbiscan (Arbitrum).
- **AVAXSCAN_API_KEY:** API key for AvaScan (Avalanche). Defaults to "FREE" if not set.
- **BASESCAN_API_KEY:** API key for BaseScan (Base).
- **BSCSCAN_API_KEY:** API key for BscScan (Binance Smart Chain).
- **GNOSCAN_API_KEY:** API key for GnoScan (Gnosis Chain).
- **METSCAN_API_KEY:** API key for MetScan (Meter). Defaults to "FREE" if not set.
- **OPTSCAN_API_KEY:** API key for OptScan (Optimism).
- **POLYSCAN_API_KEY:** API key for PolygonScan (Polygon).
- **SCRSCAN_API_KEY:** API key for ScrollScan (Scroll).
- **ZKSCAN_API_KEY:** API key for ZKScan (ZKsync).
Before using Quorum, you need to configure the following environment variable for the Etherscan API key. This key is necessary to access the respective blockchain explorers:

- **ETHSCAN_API_KEY:** API key for Etherscan.

And for the new advanced new listing first deposit check, you need to configure the ANTHROPIC_API_KEY This key is necessary to access the Antropic API.

You can set these environment variables in your shell:

```sh
export ETHSCAN_API_KEY="your_etherscan_api_key"
export ARBSCAN_API_KEY="your_arbiscan_api_key"
export AVAXSCAN_API_KEY="your_avaxscan_api_key"
export BASESCAN_API_KEY="your_basescan_api_key"
export BSCSCAN_API_KEY="your_bscscan_api_key"
export GNOSCAN_API_KEY="your_gnoscan_api_key"
export METSCAN_API_KEY="your_metscan_api_key"
export OPTSCAN_API_KEY="your_optscan_api_key"
export POLYSCAN_API_KEY="your_polyscan_api_key"
export SCRSCAN_API_KEY="your_scrscan_api_key"
export ZKSCAN_API_KEY="your_zkscan_api_key"
export ANTHROPIC_API_KEY="your_anthropic_api_key"
```

Replace `your_etherscan_api_key`, `your_arbiscan_api_key`, etc., with the actual API keys provided by the respective blockchain explorers.
Replace `your_etherscan_api_key`, `your_anthropic_api_key` with your actual API keys.

Additionally, set the `QUORUM_PATH` environment variable to specify where the repositories and diffs will be saved:

Expand Down Expand Up @@ -177,6 +160,7 @@ This configuration is used by the tool to manage the ground truth information fo
current supported price feed providers are:
- Chainlink
- Chronicle
- Coingecko

## Artifacts Structure

Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20241218.083641.938892
20241218.131651.794671

0 comments on commit 914ec12

Please sign in to comment.