Skip to content

Commit

Permalink
Script and test updates
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielSchiavini committed Nov 27, 2023
1 parent ffba985 commit 7f78b30
Show file tree
Hide file tree
Showing 11 changed files with 392 additions and 152 deletions.
69 changes: 29 additions & 40 deletions scripts/change_registry_handler.py
Original file line number Diff line number Diff line change
@@ -1,62 +1,51 @@
import sys

from brownie import (
AddressProvider,
CryptoRegistry,
MetaRegistry,
ProxyAdmin,
accounts,
network,
)
from brownie.network.gas.strategies import GasNowScalingStrategy
import boa
from rich.console import Console as RichConsole

from scripts.deployment_utils import setup_environment
from tests.utils import ZERO_ADDRESS, get_deployed_contract

RICH_CONSOLE = RichConsole(file=sys.stdout)
ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383"
CRYPTO_REGISTRY_HANDLER = "0x5f493fEE8D67D3AE3bA730827B34126CFcA0ae94"
CRYPTO_REGISTRY_HANDLER_ID = 2
OLD_CRYPTO_REGISTRY_HANDLER = "0x22ceb131d3170f9f2FeA6b4b1dE1B45fcfC86E56"
CRYPTO_REGISTRY = "0x9a32aF1A11D9c937aEa61A3790C2983257eA8Bc0"
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"

METAREGISTRY = "0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC"

if network.show_active() == "mainnet":
RICH_CONSOLE.log("Writing on mainnet")
accounts.load("babe")
txparams = {"from": accounts[0], "required_confs": 5}
try:
network.gas_price(GasNowScalingStrategy("slow", "fast"))
except ConnectionError:
pass

else:
RICH_CONSOLE.log("Simulation Mode. Writing to mainnet-fork.")
txparams = {
"from": accounts.at(
"0xbabe61887f1de2713c6f97e567623453d3C79f67", force=True
)
}
def setup():
"""
Sets up the environment for deployment scripts.
:return: txparams for deployment.
"""
if setup_environment(RICH_CONSOLE):
return {"from": "0xbabe61887f1de2713c6f97e567623453d3C79f67"}
return {"from": boa.env.eoa, "required_confs": 5}


def main():
def main(txparams) -> None:
"""
Change the registry handler of the metaregistry to the new crypto registry handler.
:param txparams: txparams argument for the proxy admin.
"""
# admin only: only admin of ADDRESSPROVIDER's proxy admin can do the following:
address_provider = AddressProvider.at(ADDRESS_PROVIDER)
address_provider_admin = address_provider.admin()
proxy_admin = ProxyAdmin.at(address_provider_admin)

metaregistry = MetaRegistry.at(
"0xF98B45FA17DE75FB1aD0e7aFD971b0ca00e379fC"
address_provider = get_deployed_contract(
"AddressProvider", ADDRESS_PROVIDER
)
address_provider_admin = address_provider.admin()
proxy_admin = get_deployed_contract("ProxyAdmin", address_provider_admin)
metaregistry = get_deployed_contract("MetaRegistry", METAREGISTRY)

assert (
metaregistry.get_registry(CRYPTO_REGISTRY_HANDLER_ID)
== OLD_CRYPTO_REGISTRY_HANDLER
)
num_pools = metaregistry.pool_count()
num_registries = metaregistry.registry_length()
num_pools_in_crypto_registry = CryptoRegistry.at(
CRYPTO_REGISTRY
).pool_count()
crypto_registry = get_deployed_contract("CryptoRegistry", CRYPTO_REGISTRY)
num_pools_in_crypto_registry = crypto_registry.pool_count()

call_data = metaregistry.update_registry_handler.encode_input(
CRYPTO_REGISTRY_HANDLER_ID,
Expand All @@ -68,11 +57,11 @@ def main():
metaregistry.pool_count() == num_pools + num_pools_in_crypto_registry
)
assert metaregistry.registry_length() == num_registries
assert (
metaregistry.get_gauge("0xD51a44d3FaE010294C616388b506AcdA1bfAAE46")
!= ZERO_ADDRESS
gauge = metaregistry.get_gauge(
"0xD51a44d3FaE010294C616388b506AcdA1bfAAE46"
)
assert gauge != ZERO_ADDRESS


if __name__ == "__main__":
main()
main(setup())
119 changes: 119 additions & 0 deletions scripts/class_diagram.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"""
Generates a mermaid class diagram with the contract selectors and
the dependencies between contracts.
Usage:
python scripts/class_diagram.py [glob_pattern] (--internal) (--members)
"""
import sys
from base64 import b64encode
from dataclasses import dataclass
from glob import glob
from pathlib import Path

import boa
from vyper import ast


@dataclass
class ContractDependencies:
"""
Describes the information extracted from each vyper contract in order to generate
the class diagram.
"""

# the name of the contract (file)
contract: str
# a dict of the interface name to a list of the selectors where it's used
interfaces: dict[str, set[str]]
functions: list[str]
variables: list[str]


def get_function_descriptor(node: ast.FunctionDef) -> str:
"""Returns a string describing the function signature."""
args_descriptor = ", ".join(a.node_source_code for a in node.args.args)
return f"({node.returns} {node.name} {args_descriptor})"


def parse_contract(filename: str) -> ContractDependencies:
"""
The interfaces used in a contract and a list of the slots where it's used.
:param filename: The path to the Vyper source code.
:return: a list of the interface names used in the contract
"""
module = boa.load_partial(filename).compiler_data.vyper_module
interfaces = module.get_children(ast.InterfaceDef)
return ContractDependencies(
contract=Path(filename).stem,
interfaces={
i.name: {
node.get_ancestor(ast.FunctionDef).name
for node in module.get_descendants(ast.Call)
if getattr(node.func, "id", None) == i.name
}
for i in interfaces
},
functions=sorted(
{
get_function_descriptor(node)
for node in module.get_children(ast.FunctionDef)
}
),
variables=sorted(
{
node.node_source_code.replace("(", " ").replace(")", "")
for node in module.get_children(ast.VariableDecl)
}
),
)


def main(pattern: str, internal=True, members=True) -> None:
"""
Generates a mermaid graph of the dependencies between contracts.
Prints the graph and a link to the image via the Mermaid Live Editor.
:param pattern: a glob pattern to match the contracts
:param internal: whether to include internal dependencies
:param members: whether to include the members of each contract
"""
contracts = [
parse_contract(filename) for filename in glob(pattern, recursive=True)
]
names = {c.contract for c in contracts}

classes = (
[
line
for contract in contracts
for line in [f" class {contract.contract} {{"]
+ contract.variables
+ contract.functions
+ [" }"]
]
if members
else []
)

connections = [
f" {contract.contract} --> {interface}: "
f"{', '.join(selectors) if 0 < len(selectors) < 3 else f'{len(selectors)} selectors'}"
for contract in contracts
for interface, selectors in contract.interfaces.items()
if not internal or interface in names
]

graph = "\n".join(["classDiagram"] + classes + connections)

print(graph)
print(
f"https://mermaid.ink/img/{b64encode(graph.encode()).decode('ascii')}"
)


if __name__ == "__main__":
args = sys.argv[1:]
main(
pattern=args[0] if args else "contracts/**/*.vy",
internal="--internal" in args,
members="--members" in args,
)
83 changes: 55 additions & 28 deletions scripts/deploy.py
Original file line number Diff line number Diff line change
@@ -1,83 +1,110 @@
import click
from ape import project
from ape.cli import NetworkBoundCommand, account_option, network_option
"""
Deploy the contracts to the network.
Usage for fork mode:
scripts/deploy.py
requires the RPC_ETHEREUM environment variable to be set
Usage for prod mode:
scripts/deploy.py --prod
requires the URL and ACCOUNT environment variables to be set
"""
import boa
from eth_abi import encode
from rich import Console as RichConsole

from scripts.deployment_utils import setup_environment

ADDRESS_PROVIDER = "0x0000000022D53366457F9d5E68Ec105046FC4383"
STABLE_REGISTRY_ADDRESS = "0x90E00ACe148ca3b23Ac1bC8C240C2a7Dd9c2d7f5"
STABLE_FACTORY_ADDRESS = "0xB9fC157394Af804a3578134A6585C0dc9cc990d4"
CRYPTO_REGISTRY_ADDRESS = "" # left blank because a new one gets deployed
CRYPTO_FACTORY_ADDRESS = "0xF18056Bbd320E96A48e3Fbf8bC061322531aac99"


@click.group(short_help="Deploy the project")
def cli():
pass

def main():
"""
Deploy the contracts to the network.
It does the following:
1. deploys the base pool registry
2. deploys the crypto registry
3. deploys the stable registry handler
4. deploys the stable factory handler
5. deploys the crypto registry handler
6. deploys the crypto factory handler
7. deploys the metaregistry
"""
console = RichConsole()
setup_environment(console)

@cli.command(cls=NetworkBoundCommand)
@network_option()
@account_option()
def main(network, account):
# deploy basepool registry:
base_pool_registry = account.deploy(project.BasePoolRegistry)
base_pool_registry = boa.load(
"contracts/mainnet/registries/BasePoolRegistry.vy"
)

# deploy crypto registry:
print(
console.log(
"Crypto Registry constructor arguments: ",
encode(["address", "address"], [ADDRESS_PROVIDER, base_pool_registry]),
)
crypto_registry = account.deploy(
project.CryptoRegistryV1,
crypto_registry = boa.load(
"contracts/mainnet/registries/CryptoRegistryV1.vy",
ADDRESS_PROVIDER,
base_pool_registry,
)

# deploy stable registry handler:
print(
console.log(
"Stable Registry Handler constructor arguments: ",
encode(["address"], [STABLE_REGISTRY_ADDRESS]).hex(),
)
account.deploy(project.StableRegistryHandler, STABLE_REGISTRY_ADDRESS)
boa.load(
"contracts/mainnet/registry_handlers/StableRegistryHandler.vy",
STABLE_REGISTRY_ADDRESS,
)

# deploy stable factory handler:
print(
console.log(
"Stable Factory Handler constructor arguments: ",
encode(
["address", "address"],
[STABLE_FACTORY_ADDRESS, base_pool_registry],
).hex(),
)
account.deploy(
project.StableFactoryHandler,
boa.load(
"contracts/mainnet/registry_handlers/StableFactoryHandler.vy",
STABLE_FACTORY_ADDRESS,
base_pool_registry,
)

# deploy crypto registry handler:
print(
console.log(
"Crypto Registry Handler constructor arguments: ",
encode(["address"], [crypto_registry]).hex(),
)
account.deploy(project.CryptoRegistryHandler, crypto_registry)
boa.load(
"contracts/mainnet/registry_handlers/CryptoRegistryHandler.vy",
crypto_registry,
)

# deploy crypto factory handler:
print(
console.log(
"Crypto Factory Handler constructor arguments: ",
encode(
["address", "address"],
[CRYPTO_FACTORY_ADDRESS, base_pool_registry],
).hex(),
)
account.deploy(
project.CryptoFactoryHandler,
boa.load(
"contracts/mainnet/registry_handlers/CryptoFactoryHandler.vy",
CRYPTO_FACTORY_ADDRESS,
base_pool_registry,
)

# deploy metaregistry:
print(
console.log(
"MetaRegistry constructor arguments: ",
encode(["address"], [ADDRESS_PROVIDER]).hex(),
)
account.deploy(project.MetaRegistry, ADDRESS_PROVIDER)
boa.load("contracts/mainnet/MetaRegistry.vy", ADDRESS_PROVIDER)


if __name__ == "__main__":
main()
Loading

0 comments on commit 7f78b30

Please sign in to comment.