Skip to content

Commit

Permalink
feat: deployment script, dev_multisig
Browse files Browse the repository at this point in the history
  • Loading branch information
heswithme committed Oct 15, 2024
1 parent 577c575 commit 8d8cd7f
Show file tree
Hide file tree
Showing 15 changed files with 1,266 additions and 98 deletions.
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
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
24 changes: 13 additions & 11 deletions tests/integration/curve_pools/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def alice():


@pytest.fixture()
def dev_address():
def dev_deployer():
return boa.env.generate_address()


Expand Down Expand Up @@ -51,7 +51,7 @@ def pool_tokens(paired_tokens, vault):


@pytest.fixture()
def stableswap_pool(stableswap_factory, vault, dev_address, pool_tokens):
def stableswap_pool(stableswap_factory, vault, dev_deployer, pool_tokens):
# Retrieve token addresses and asset types from request.param
coins = [token["address"] for token in pool_tokens]
asset_types = [token.get("asset_type") for token in pool_tokens]
Expand All @@ -63,7 +63,7 @@ def stableswap_pool(stableswap_factory, vault, dev_address, pool_tokens):
oracles = ["0x0000000000000000000000000000000000000000"] * pool_size
offpeg_fee_mp = 20000000000
# deploy pool
with boa.env.prank(dev_address):
with boa.env.prank(dev_deployer):
pool_address = stableswap_factory.deploy_plain_pool(
"pool_name",
"POOL",
Expand All @@ -84,27 +84,29 @@ def stableswap_pool(stableswap_factory, vault, dev_address, pool_tokens):
dev_balances = []
for token in pool_tokens:
if token["asset_type"] == 0:
boa.deal(token["contract"], dev_address, AMOUNT_STABLE * 10 ** token["decimals"])
boa.deal(token["contract"], dev_deployer, AMOUNT_STABLE * 10 ** token["decimals"])
elif token["asset_type"] == 3:
underlying_token = token["contract"].asset()
underlying_contract = boa.from_etherscan(underlying_token, "token")
decimals = underlying_contract.decimals()
boa.deal(
underlying_contract,
dev_address,
dev_deployer,
AMOUNT_STABLE * 10**decimals
+ underlying_contract.balanceOf(
dev_address
dev_deployer
), # in case of dai + sdai deal would overwrite, so we add the previous balance
)
underlying_contract.approve(
token["contract"],
AMOUNT_STABLE * 10**decimals,
sender=dev_address,
sender=dev_deployer,
)
token["contract"].deposit(
AMOUNT_STABLE * 10**decimals, dev_deployer, sender=dev_deployer
)
token["contract"].deposit(AMOUNT_STABLE * 10**decimals, dev_address, sender=dev_address)
# Approve pool to spend vault tokens
token["contract"].approve(pool, 2**256 - 1, sender=dev_address)
dev_balances.append(token["contract"].balanceOf(dev_address))
pool.add_liquidity(dev_balances, 0, dev_address, sender=dev_address)
token["contract"].approve(pool, 2**256 - 1, sender=dev_deployer)
dev_balances.append(token["contract"].balanceOf(dev_deployer))
pool.add_liquidity(dev_balances, 0, dev_deployer, sender=dev_deployer)
return pool
24 changes: 12 additions & 12 deletions tests/integration/curve_pools/test_stableswap.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
import address_book as ab


N_COMBINATIONS = 40 # num of combinations in stableswap tests (>=36 => all combinations)
N_COMBINATIONS = 5 # num of combinations in stableswap tests (>=36 => all combinations)

# produce tokens for stableswap to pair against crvusd
paired_token_combinations = generate_list_combinations(ab.all_stables, [1, 2], randomize=False)
paired_token_combinations = generate_list_combinations(ab.all_stables, [1, 2], randomize=True)
tokens_subset = paired_token_combinations[0:N_COMBINATIONS]


def test_accrue_value(alice, dev_address, vault, crvusd, crvusd_init_balance):
def test_accrue_value(alice, dev_deployer, vault, crvusd, crvusd_init_balance):
# fund alice
assert crvusd.balanceOf(alice) == 0
boa.deal(crvusd, alice, crvusd_init_balance)
Expand All @@ -23,8 +23,8 @@ def test_accrue_value(alice, dev_address, vault, crvusd, crvusd_init_balance):
alice_value_0 = vault.convertToAssets(vault.balanceOf(alice))

# deposit crvusd rewards into vault & time travel
boa.deal(crvusd, dev_address, crvusd_init_balance)
crvusd.transfer(vault, crvusd_init_balance, sender=dev_address)
boa.deal(crvusd, dev_deployer, crvusd_init_balance)
crvusd.transfer(vault, crvusd_init_balance, sender=dev_deployer)
vault.process_report(vault, sender=ab.dao_agent)
boa.env.time_travel(seconds=86_400 * 7)

Expand All @@ -45,7 +45,7 @@ def test_stableswap_pool_liquidity(
paired_tokens,
vault,
alice,
dev_address,
dev_deployer,
crvusd_init_balance,
crvusd,
):
Expand All @@ -69,8 +69,8 @@ def test_stableswap_pool_liquidity(

# now increase shares value by 5%
amt_reward = int(vault.totalAssets() * 0.05)
boa.deal(crvusd, dev_address, amt_reward)
crvusd.transfer(vault, amt_reward, sender=dev_address)
boa.deal(crvusd, dev_deployer, amt_reward)
crvusd.transfer(vault, amt_reward, sender=dev_deployer)
vault.process_report(vault, sender=ab.dao_agent)
boa.env.time_travel(seconds=86_400 * 7)

Expand All @@ -94,7 +94,7 @@ def test_stableswap_pool_liquidity(
ids=[f"scrvusd+{'+'.join([token['name'] for token in tokens])}" for tokens in tokens_subset],
)
def test_stableswap_pool_prices_with_vault_growth(
stableswap_pool, pool_tokens, vault, dev_address, crvusd, paired_tokens
stableswap_pool, pool_tokens, vault, dev_deployer, crvusd, paired_tokens
):
"""
Test where vault shares grow (rewards airdropped), and we expect that pool prices change accordingly.
Expand All @@ -117,11 +117,11 @@ def test_stableswap_pool_prices_with_vault_growth(

# Step 2: Dev removes 5% of liquidity in a balanced way
stableswap_pool.remove_liquidity(
stableswap_pool.balanceOf(dev_address) // 20,
stableswap_pool.balanceOf(dev_deployer) // 20,
[0] * n_coins,
dev_address,
dev_deployer,
True,
sender=dev_address,
sender=dev_deployer,
)
# Check pool prices after each iteration
cur_dy = [stableswap_pool.get_dy(0, i, 10 ** decimals[0]) for i in range(1, n_coins)]
Expand Down
23 changes: 14 additions & 9 deletions tests/unitary/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ def curve_dao():


@pytest.fixture()
def dev_address():
def dev_deployer():
return boa.env.generate_address()


@pytest.fixture()
def dev_multisig():
return boa.env.generate_address()


Expand All @@ -31,10 +36,10 @@ def vault_init_deposit_cap():


@pytest.fixture()
def deposit_limit_module(dev_address, crvusd, vault, vault_init_deposit_cap):
def deposit_limit_module(dev_deployer, crvusd, vault, vault_init_deposit_cap, dev_multisig):
contract_deployer = boa.load_partial("contracts/DepositLimitModule.vy")
with boa.env.prank(dev_address):
contract = contract_deployer(vault, vault_init_deposit_cap)
with boa.env.prank(dev_deployer):
contract = contract_deployer(vault, vault_init_deposit_cap, dev_multisig)
return contract


Expand Down Expand Up @@ -64,10 +69,10 @@ def role_manager():


@pytest.fixture()
def vault(vault_factory, crvusd, role_manager, dev_address):
def vault(vault_factory, crvusd, role_manager, dev_deployer):
vault_deployer = boa.load_partial("contracts/yearn/VaultV3.vy")

with boa.env.prank(dev_address):
with boa.env.prank(dev_deployer):
address = vault_factory.deploy_new_vault(
crvusd, "Savings crvUSD", "scrvUSD", role_manager, 0
)
Expand Down Expand Up @@ -133,14 +138,14 @@ def rewards_handler(
scaling_factor,
mock_controller_factory,
curve_dao,
dev_address,
dev_deployer,
):
rewards_handler_deployer = boa.load_partial("contracts/RewardsHandler.vy")
with boa.env.prank(dev_address):
with boa.env.prank(dev_deployer):
rh = rewards_handler_deployer(
crvusd, vault, minimum_weight, scaling_factor, mock_controller_factory, curve_dao
)

vault.set_role(rh, 2**11 | 2**5 | 2**0, sender=role_manager)
vault.set_role(rh, 2**11 | 2**5, sender=role_manager)

return rh
38 changes: 25 additions & 13 deletions tests/unitary/deposit_limit_module/test_available_deposit_limit.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import boa


def test_available_deposit_limit_paused(deposit_limit_module, security_agent, dev_address):
def test_available_deposit_limit_paused(deposit_limit_module, security_agent, dev_multisig):
"""
Tests that the available deposit limit returns 0 when deposits are paused.
"""
# Set security_agent status for security_agent using dev_address privileges
with boa.env.prank(dev_address):
# Set security_agent status for security_agent using dev_multisig privileges
with boa.env.prank(dev_multisig):
deposit_limit_module.set_security_agent(security_agent, True)

# Pause deposits
Expand All @@ -18,7 +18,13 @@ def test_available_deposit_limit_paused(deposit_limit_module, security_agent, de


def test_available_deposit_limit_below_max(
deposit_limit_module, dev_address, crvusd, vault, vault_init_deposit_cap, vault_god
deposit_limit_module,
dev_deployer,
crvusd,
vault,
vault_init_deposit_cap,
vault_god,
dev_multisig,
):
"""
Tests the available deposit limit when the vault balance is below the max deposit limit.
Expand All @@ -28,13 +34,13 @@ def test_available_deposit_limit_below_max(
vault.set_deposit_limit(2**256 - 1, sender=vault_god)
# Set the mock vault and stablecoin balances
deal_balance = int(0.7 * vault_init_deposit_cap)
boa.deal(crvusd, dev_address, deal_balance)
crvusd.approve(vault.address, deal_balance, sender=dev_address)
vault.deposit(deal_balance, dev_address, sender=dev_address)
boa.deal(crvusd, dev_deployer, deal_balance)
crvusd.approve(vault.address, deal_balance, sender=dev_deployer)
vault.deposit(deal_balance, dev_deployer, sender=dev_deployer)

# Set the max deposit limit higher than the vault balance
limit_balance = vault_init_deposit_cap
with boa.env.prank(dev_address):
with boa.env.prank(dev_multisig):
deposit_limit_module.set_deposit_limit(limit_balance)

# Check that the available deposit limit is the difference between max limit and vault balance
Expand All @@ -45,7 +51,13 @@ def test_available_deposit_limit_below_max(


def test_available_deposit_limit_above_max(
deposit_limit_module, dev_address, crvusd, vault, vault_init_deposit_cap, vault_god
deposit_limit_module,
dev_deployer,
crvusd,
vault,
vault_init_deposit_cap,
vault_god,
dev_multisig,
):
"""
Tests the available limit when the vault balance is equal to or above the max deposit cap.
Expand All @@ -55,12 +67,12 @@ def test_available_deposit_limit_above_max(
vault.set_deposit_limit(2**256 - 1, sender=vault_god)
# Set the vault balance to be above the max deposit limit
deal_balance = int(1.2 * vault_init_deposit_cap)
boa.deal(crvusd, dev_address, deal_balance)
crvusd.approve(vault.address, deal_balance, sender=dev_address)
vault.deposit(deal_balance, dev_address, sender=dev_address)
boa.deal(crvusd, dev_deployer, deal_balance)
crvusd.approve(vault.address, deal_balance, sender=dev_deployer)
vault.deposit(deal_balance, dev_deployer, sender=dev_deployer)

# Set the max deposit limit lower than the vault balance
with boa.env.prank(dev_address):
with boa.env.prank(dev_multisig):
deposit_limit_module.set_deposit_limit(vault_init_deposit_cap)

# Check that the available limit is 0 when the vault balance is above the max deposit cap
Expand Down
13 changes: 8 additions & 5 deletions tests/unitary/deposit_limit_module/test_set_admin.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import boa


def test_default_behavior(deposit_limit_module, dev_address, curve_dao):
def test_default_behavior(deposit_limit_module, dev_deployer, curve_dao, dev_multisig):
# Verify that dev_deployer is not an admin
assert not deposit_limit_module.is_admin(dev_deployer)

# Call function to set admin status
with boa.env.prank(dev_address):
with boa.env.prank(dev_multisig):
deposit_limit_module.set_admin(curve_dao, True)

# Verify that curve_dao is now an admin
assert deposit_limit_module.is_admin(curve_dao)

# Revoke admin role
with boa.env.prank(curve_dao):
deposit_limit_module.set_admin(dev_address, False)
deposit_limit_module.set_admin(dev_multisig, False)

# Verify that dev_address is no longer an admin
assert not deposit_limit_module.is_admin(dev_address)
# Verify that dev_deployer is no longer an admin
assert not deposit_limit_module.is_admin(dev_multisig)


def test_set_admin_unauthorized(deposit_limit_module, curve_dao, security_agent):
Expand Down
13 changes: 8 additions & 5 deletions tests/unitary/deposit_limit_module/test_set_controller.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import boa


def test_default_behavior(deposit_limit_module, dev_address, security_agent):
def test_default_behavior(deposit_limit_module, security_agent, dev_multisig):
# Verify initialization
assert deposit_limit_module.is_security_agent(dev_multisig)

# Verify that security_agent is not yet a security_agent
assert not deposit_limit_module.is_security_agent(security_agent)

# Set security_agent status using dev_address privileges
with boa.env.prank(dev_address):
# Set security_agent status using dev_multisig privileges
with boa.env.prank(dev_multisig):
deposit_limit_module.set_security_agent(security_agent, True)

# Verify that security_agent is now a security_agent
assert deposit_limit_module.is_security_agent(security_agent)

# Revoke security_agent role using dev_address privileges
with boa.env.prank(dev_address):
# Revoke security_agent role using dev_multisig privileges
with boa.env.prank(dev_multisig):
deposit_limit_module.set_security_agent(security_agent, False)

# Verify that security_agent is no longer a security_agent
Expand Down
Loading

0 comments on commit 8d8cd7f

Please sign in to comment.