Skip to content

Commit

Permalink
feat: deploy account contract + execute at address utils (kkrt-labs#550)
Browse files Browse the repository at this point in the history
<!--- Please provide a general summary of your changes in the title
above -->
This PR provides python utilities in order to easily deploy a contract
on Kakarot and execute calldata on deployed contracts.

<!-- Give an estimate of the time you spent on this PR in terms of work
days. Did you spend 0.5 days on this PR or rather 2 days? -->

Time spent on this PR: 1 day

## Pull request type

<!-- Please try to limit your pull request to one type, submit multiple
pull requests if needed. -->

Please check the type of change your PR introduces:

- [ ] Bugfix
- [x] Feature
- [ ] Code style update (formatting, renaming)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] Documentation content changes
- [ ] Other (please describe):

## What is the current behavior?

<!-- Please describe the current behavior that you are modifying, or
link to a relevant issue. -->
No script available to deploy a contract account on Kakarot or execute
calldata on a deployed contract.

Resolves N/A

## What is the new behavior?

<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Provide a script to deploy a contract account or execute calldata on a
deployed contract.
  • Loading branch information
greged93 authored Apr 5, 2023
1 parent 7e36d60 commit f31d7eb
Show file tree
Hide file tree
Showing 7 changed files with 421 additions and 69 deletions.
14 changes: 10 additions & 4 deletions .env_example
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# Github configuration
GITHUB_TOKEN=

# Network configuration
STARKNET_NETWORK=testnet

# All addresses are hex strings
MAINNET_ACCOUNT_ADDRESS=
MAINNET_PRIVATE_KEY=
Expand All @@ -8,12 +14,12 @@ TESTNET_PRIVATE_KEY=
TESTNET2_ACCOUNT_ADDRESS=
TESTNET2_PRIVATE_KEY=

DEVNET_ACCOUNT_ADDRESS=0x7e00d496e324876bbc8531f2d9a82bf154d1a04a50218ee74cdd372f75a551a
DEVNET_PRIVATE_KEY=0xe3e70682c2094cac629f6fbed82c07cd
DEVNET_ACCOUNT_ADDRESS=
DEVNET_PRIVATE_KEY=

# These will be used if above variables are not set for the given network
ACCOUNT_ADDRESS=
PRIVATE_KEY=

# A default evm address to deploy an eoa for
EVM_ADDRESS=
# The private key to the eoa to deploy
EVM_PRIVATE_KEY=
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ deploy: build

format:
poetry run cairo-format -i ${cairo_files}
poetry run black tests/.
poetry run isort tests/.
poetry run black tests/. scripts/.
poetry run isort tests/. scripts/.
poetry run autoflake . -r

format-check:
Expand Down
78 changes: 78 additions & 0 deletions scripts/artifacts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Imports
import io
import logging
import os
import zipfile
from pathlib import Path

import pandas as pd
import requests
from dotenv import load_dotenv

load_dotenv()
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


def get_resources(
coverage_dir: Path = Path("coverage"), base_branch_name: str = "main"
):
# Pull latest main artifacts
response = requests.get(
"https://api.github.com/repos/sayajin-labs/kakarot/actions/artifacts"
)
artifacts = (
pd.DataFrame(
[
{**artifact["workflow_run"], **artifact}
for artifact in response.json()["artifacts"]
]
)
.loc[lambda df: df.name == "coverage"]
.reindex(["head_branch", "updated_at", "archive_download_url"], axis=1)
.sort_values(["head_branch", "updated_at"], ascending=False)
.drop_duplicates(["head_branch"])
)
if base_branch_name not in artifacts.head_branch.tolist():
logger.info(
f"No artifacts found for base branch '{base_branch_name}'. Found\n{artifacts.head_branch.tolist()}"
)

for artifact in artifacts.to_dict("records"):
response = requests.get(
artifact["archive_download_url"],
headers={"Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}"},
)

z = zipfile.ZipFile(io.BytesIO(response.content))
z.extractall(coverage_dir / artifact["head_branch"])

return artifacts


def get_deployments(path: str = "deployments"):
response = requests.get(
"https://api.github.com/repos/sayajin-labs/kakarot/actions/artifacts"
)
artifacts = (
pd.DataFrame(
[
{**artifact["workflow_run"], **artifact}
for artifact in response.json()["artifacts"]
]
)
.loc[lambda df: df["head_branch"] == "main"]
.loc[lambda df: df["name"] == "deployments"]
.sort_values(["updated_at"], ascending=False)
.archive_download_url
)

if artifacts.empty:
raise ValueError(f"No deployment artifacts found for base branch main")

response = requests.get(
artifacts.tolist()[0],
headers={"Authorization": f"Bearer {os.getenv('GITHUB_TOKEN')}"},
)
z = zipfile.ZipFile(io.BytesIO(response.content))
z.extractall(path)
47 changes: 7 additions & 40 deletions scripts/check_resources.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
#%% Imports
import io
# Imports
import logging
import os
import zipfile
from pathlib import Path

import pandas as pd
import requests
from dotenv import load_dotenv

load_dotenv()
from scripts.artifacts import get_resources

pd.set_option("display.max_rows", 500)
pd.set_option("display.max_columns", 10)
pd.set_option("display.width", 1000)
Expand All @@ -18,44 +14,15 @@
logger = logging.getLogger(__name__)


#%% main
def main():
#%% Script constants
# Script constants
coverage_dir = Path("coverage")
base_branch_name = "main"
current_name = "local"

#%% Pull latest main artifacts
response = requests.get(
"https://api.github.com/repos/sayajin-labs/kakarot/actions/artifacts"
)
artifacts = (
pd.DataFrame(
[
{**artifact["workflow_run"], **artifact}
for artifact in response.json()["artifacts"]
]
)
.loc[lambda df: df.name == "coverage"]
.reindex(["head_branch", "updated_at", "archive_download_url"], axis=1)
.sort_values(["head_branch", "updated_at"], ascending=False)
.drop_duplicates(["head_branch"])
)
if base_branch_name not in artifacts.head_branch.tolist():
logger.info(
f"No artifacts found for base branch '{base_branch_name}'. Found\n{artifacts.head_branch.tolist()}"
)

for artifact in artifacts.to_dict("records"):
response = requests.get(
artifact["archive_download_url"],
headers={"Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}"},
)

z = zipfile.ZipFile(io.BytesIO(response.content))
z.extractall(coverage_dir / artifact["head_branch"])
artifacts = get_resources(coverage_dir, base_branch_name)

#%% Build aggregated stat for checking resources evolution
# Build aggregated stat for checking resources evolution
resources = [
(
pd.read_csv(
Expand Down Expand Up @@ -101,7 +68,7 @@ def main():
)
logger.info(f"Resources summary:\n{resources_summary}")

#%% Compare local test run with base branch
# Compare local test run with base branch
if ({current_name, base_branch_name}).issubset(set(all_resources.head_branch)):
tests_with_diff = (
all_resources.loc[
Expand Down
25 changes: 20 additions & 5 deletions scripts/constants.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import json
import os
import re
from enum import Enum
from pathlib import Path

from dotenv import load_dotenv
from eth_keys import keys
from starknet_py.net.gateway_client import GatewayClient

from scripts.artifacts import get_deployments

load_dotenv()

ETH_TOKEN_ADDRESS = 0x49D36570D4E46F48E99674BD3FCC84644DDD6B96F7C741B1562B82F9E004DC7
EVM_ADDRESS = os.getenv("EVM_ADDRESS")
EVM_PRIVATE_KEY = os.getenv("EVM_PRIVATE_KEY")
EVM_ADDRESS = keys.PrivateKey(
bytes.fromhex(EVM_PRIVATE_KEY[2:])
).public_key.to_checksum_address()
NETWORK = os.getenv("STARKNET_NETWORK", "starknet-devnet")
NETWORK = (
"testnet"
Expand All @@ -21,7 +28,7 @@
else "mainnet"
)
GATEWAY_URLS = {
"mainnet": "alpha-mainnet",
"mainnet": "https://alpha-mainnet.starknet.io",
"testnet": "https://alpha4.starknet.io",
"testnet2": "https://alpha4-2.starknet.io",
"devnet": "http://127.0.0.1:5050",
Expand Down Expand Up @@ -50,17 +57,25 @@ class ChainId(Enum):
devnet = int.from_bytes(b"SN_GOERLI", "big")


CHAIN_ID = getattr(ChainId, NETWORK)

DEPLOYMENTS_DIR = Path("deployments") / NETWORK
BUILD_DIR = Path("build")
BUILD_DIR.mkdir(exist_ok=True, parents=True)
SOURCE_DIR = Path("src")
CONTRACTS = {p.stem: p for p in list(SOURCE_DIR.glob("**/*.cairo"))}


ACCOUNT_ADDRESS = (
os.environ.get(f"{NETWORK.upper()}_ACCOUNT_ADDRESS")
or os.environ["ACCOUNT_ADDRESS"]
)
PRIVATE_KEY = (
os.environ.get(f"{NETWORK.upper()}_PRIVATE_KEY") or os.environ["PRIVATE_KEY"]
)

get_deployments(Path("deployments"))
DEPLOYMENTS_DIR = Path("deployments") / NETWORK
DEPLOYMENTS_DIR.mkdir(exist_ok=True, parents=True)
deployments = json.load(open(DEPLOYMENTS_DIR / "deployments.json", "r"))

CHAIN_ID = getattr(ChainId, NETWORK)
KAKAROT_CHAIN_ID = 1263227476 # KKRT (0x4b4b5254) in ASCII
KAKAROT_ADDRESS = deployments["kakarot"]["address"]
Loading

0 comments on commit f31d7eb

Please sign in to comment.