Skip to content

Commit

Permalink
feat: deploy scripts (#35)
Browse files Browse the repository at this point in the history
* refactor: staking -> saving

* ci: remove parallel pytest to avoid hitting rate limits

* feat: we can now cache in boa if we reject n=auto

* chore: comments cleanup

* feat: deployment script, dev_multisig

* feat: deploy script

* ci: notebooks cleanup on commit
  • Loading branch information
heswithme authored Oct 16, 2024
1 parent 494e3eb commit 309e317
Show file tree
Hide file tree
Showing 17 changed files with 1,561 additions and 98 deletions.
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ repos:
- id: check-ast
- id: detect-private-key

- repo: https://github.com/kynan/nbstripout
rev: 0.7.1
hooks:
- id: nbstripout

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.9
hooks:
Expand Down
5 changes: 3 additions & 2 deletions contracts/DepositLimitModule.vy
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ vault: public(immutable(IVault))
def __init__(
_vault: IVault,
max_deposit_limit: uint256,
admin: address,
):
"""
@notice Initializes the contract by assigning the deployer as the initial admin and security_agent.
"""
self._set_admin(msg.sender, True)
self._set_security_agent(msg.sender, True)
self._set_admin(admin, True)
self._set_security_agent(admin, True)
self._set_deposits_paused(False) # explicit non-paused at init
self._set_deposit_limit(max_deposit_limit)

Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ dev-dependencies = [
"pre-commit==3.8.0",
"ruff==0.6.9",
"pytest==8.2.2",
"pytest-xdist==3.6.1",
"plyvel-ci==1.5.1",
"curve-dao>=1.0.0",
"jupyter>=1.0.0",
"python-dotenv>=1.0.1"
]

[tool.ruff]
Expand Down
290 changes: 290 additions & 0 deletions scripts/deploy_scrvusd.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "0",
"metadata": {},
"source": [
"# s-crvUSD deployment\n",
"This script deploys the scrvUSD vault contract to the Ethereum network. Additionally, RewardsHandler contract periphery is deployed to integrate the scrvUSD into the flow of crvUSD lending fees."
]
},
{
"cell_type": "markdown",
"id": "1",
"metadata": {},
"source": [
"## Setup"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"# importing scripting dependencies\n",
"import boa\n",
"from eth_account import Account\n",
"from boa import NetworkEnv, Env"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3",
"metadata": {},
"outputs": [],
"source": [
"# use address book for relevant addresses\n",
"import sys\n",
"\n",
"if os.getcwd()[-7:] == \"scripts\":\n",
" sys.path.append(\"..\") # to enable import from parent directory\n",
"import tests.integration.address_book as ab\n",
"\n",
"from dotenv import load_dotenv\n",
"\n",
"load_dotenv()\n",
"\n",
"# get env vars\n",
"ETHERSCAN_API_KEY = os.getenv(\"ETHERSCAN_API_KEY\")\n",
"PINATA_API_KEY = os.getenv(\"PINATA_API_KEY\")\n",
"RPC_URL = os.environ.get(\"ETH_RPC_URL\")\n",
"PRIVATE_KEY = os.environ.get(\"PRIVATE_KEY\")"
]
},
{
"cell_type": "markdown",
"id": "4",
"metadata": {},
"source": [
"## Select mode\n",
"Production mode cell is intentionally executed first to avoid deploying things by accident. If one runs all the cells sequentially things will be executed in forking mode.\n",
"\n",
"To deploy in production mode, manually skip the execution of the fork mode cell."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5",
"metadata": {},
"outputs": [],
"source": [
"# production mode (to deploy on ethereum)\n",
"deployer = Account.from_key(PRIVATE_KEY)\n",
"eth_env = NetworkEnv(RPC_URL)\n",
"boa.set_env(eth_env)\n",
"\n",
"# this automatically sets the eoa as the deployer\n",
"boa.env.add_account(deployer)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6",
"metadata": {},
"outputs": [],
"source": [
"# fork mode (for testing)\n",
"# we impersonate convex since they definitely have enough to push a vote\n",
"CONVEX_VOTERPROXY = \"0x989aeb4d175e16225e39e87d0d97a3360524ad80\"\n",
"\n",
"forked_env = Env()\n",
"boa.set_env(forked_env)\n",
"\n",
"boa.env.fork(RPC_URL, cache_file=None) # no cache because kernel locks access to the file\n",
"boa.env.eoa = CONVEX_VOTERPROXY"
]
},
{
"cell_type": "markdown",
"id": "7",
"metadata": {},
"source": [
"# I. Deployment"
]
},
{
"cell_type": "markdown",
"id": "8",
"metadata": {},
"source": [
"### 1. Vault"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9",
"metadata": {},
"outputs": [],
"source": [
"# I. First deploy the Vault\n",
"vault_factory = boa.from_etherscan(\n",
" ab.yearn_vault_factory, \"vault_factory\", api_key=ETHERSCAN_API_KEY\n",
")\n",
"\n",
"deployer_address = boa.env.eoa\n",
"vault_address = vault_factory.deploy_new_vault(\n",
" ab.crvusd, # underlying token\n",
" \"Savings crvUSD\", # vault name\n",
" \"scrvUSD\", # vault symbol\n",
" deployer_address, # initial role manager = deployer\n",
" 86_400 * 7, # unlock time for rewards\n",
")\n",
"\n",
"print(f\"Vault deployed at {vault_address}\")"
]
},
{
"cell_type": "markdown",
"id": "10",
"metadata": {},
"source": [
"### 2. DepositLimitModule"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "11",
"metadata": {},
"outputs": [],
"source": [
"# II. Then deploy the DepositLimitModule\n",
"DepositLimit_deployer = boa.load_partial(\"../contracts/DepositLimitModule.vy\")\n",
"\n",
"deposit_limit = DepositLimit_deployer(\n",
" vault_address, # vault\n",
" 5_000_000 * 10**18, # cap deposits to 5M crvUSD\n",
" ab.dev_multisig, # admin\n",
")\n",
"\n",
"print(f\"Deposit limit module deployed at {deposit_limit.address}\")"
]
},
{
"cell_type": "markdown",
"id": "12",
"metadata": {},
"source": [
"### 3. RewardsHandler"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "13",
"metadata": {},
"outputs": [],
"source": [
"# III. Finally deploy the RewardsHandler\n",
"RewardsHandler_deployer = boa.load_partial(\"../contracts/RewardsHandler.vy\")\n",
"\n",
"rewards_handler = RewardsHandler_deployer(\n",
" ab.crvusd, # stablecoin\n",
" vault_address, # vault\n",
" 500, # minimum weight (5%)\n",
" 10_000, # scaling factor (over MAX_BPS)\n",
" ab.crvusd_controller_factory, # controller factory\n",
" ab.dao_agent, # WE CERTAIN ABOUT THIS CONTRACT? [TODO]\n",
")\n",
"\n",
"print(f\"Rewards handler deployed at {rewards_handler.address}\")"
]
},
{
"cell_type": "markdown",
"id": "14",
"metadata": {},
"source": [
"# II. Post-deployment setup"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "15",
"metadata": {},
"outputs": [],
"source": [
"# I. Set the vault\n",
"vault = boa.load_partial(\"../contracts/yearn/VaultV3.vy\").at(vault_address)\n",
"# a. set the rewards handler roles in the vault\n",
"vault.set_role(\n",
" rewards_handler.address, 2**11 | 2**5\n",
") # set RH as REPORTING_MANAGER and PROFIT_UNLOCK_MANAGER\n",
"# b. set the deposit limit module in the vault\n",
"vault.set_role(ab.dev_multisig, int(\"11111111111111\", 2)) # set dev_multisig megarole\n",
"vault.transfer_role_manager(ab.dao_agent)\n",
"\n",
"# with boa.env.prank(ab.dev_multisig): ### TODO call from dev_multisig\n",
"# vault.set_deposit_limit_module(deposit_limit.address, True)\n",
"# c. relinquish the role manager role to DAO ### TODO propose acceptance of role by dao\n",
"\n",
"# II. Set the deposit limit module\n",
"# use dev_multisig as admin at deploy time, then manually set the security agent to fuzzland (to avoid extra txns from deployer)\n",
"# deposit_limit_address.set_security_agent(ab.fuzzland_address, True) # TODO dev_multisig txn\n",
"\n",
"# III. Finally set the rewards handler parameters\n",
"# rewards_handler_contract = boa.load_partial(\"../contracts/RewardsHandler.vy\").at(rewards_handler_address)\n",
"# here distribution_time must be set to match the vault's value, but why does RH have distribution_time at all? TODO: discuss"
]
},
{
"cell_type": "markdown",
"id": "16",
"metadata": {},
"source": [
"## 3. Vote in the DAO"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "17",
"metadata": {},
"outputs": [],
"source": [
"# ACTIONS = [(ab.controller_factory, \"set_fee_receiver\", fs)]\n",
"# DESCRIPTION = \"Set the fee receiver to the fee splitter, to lay the foundation for autobribe, st-crvUSD and rebalancing donations. This vote **is not** about changing the fee distribution (100% of revenues will still go to veCRV holders).\"\n",
"# curve_dao.create_vote(ab.dao, ACTIONS, DESCRIPTION, ETHERSCAN_API_KEY, PINATA_API_KEY)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "18",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
6 changes: 5 additions & 1 deletion tests/integration/address_book.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
# yearn vaults 3.0.3 factory
yearn_vault_factory = "0x5577EdcB8A856582297CdBbB07055E6a6E38eb5f"
vault_original = "0xcA78AF7443f3F8FA0148b746Cb18FF67383CDF3f"

crvusd = "0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E"
crvusd_controller_factory = "0xC9332fdCB1C491Dcc683bAe86Fe3cb70360738BC"
crvusd_fee_collector = "0xa2Bcd1a4Efbd04B63cd03f5aFf2561106ebCCE00"
fee_splitter = "0x22556558419eed2d0a1af2e7fd60e63f3199aca3"
dao_agent = "0x40907540d8a6C65c637785e8f8B742ae6b0b9968"
vault_original = "0xcA78AF7443f3F8FA0148b746Cb18FF67383CDF3f"

dev_multisig = "0xe286b81d16FC7e87eD9dc2a80dd93b1816F4Dcf2"
fuzzland_address = "0xaE4A2FFeeD8eEDA4698bBf4A36F01d1f86602973"

# curve factories
factory_stableswap_ng = "0x6A8cbed756804B16E05E741eDaBd5cB544AE21bf"
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def rewards_handler(vault, minimum_weight):
ab.crvusd_controller_factory,
ab.dao_agent,
)
vault.set_role(rh, 2**11 | 2**5 | 2**0, sender=ab.dao_agent)
vault.set_role(rh, 2**11 | 2**5, sender=ab.dao_agent)

# TODO how to enforce this in prod?
time = vault.profitMaxUnlockTime()
Expand Down
Loading

0 comments on commit 309e317

Please sign in to comment.