Skip to content

Commit

Permalink
Working on Lagoon settlement
Browse files Browse the repository at this point in the history
  • Loading branch information
miohtama committed Dec 3, 2024
1 parent 7fc01c2 commit a628875
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 7 deletions.
27 changes: 27 additions & 0 deletions eth_defi/lagoon/vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,21 @@ def fetch_info(self) -> LagoonVaultInfo:
del safe_info_dict["address"] # Key conflict
return vault_info | safe_info_dict

def fetch_nav(self) -> Decimal:
"""Fetch the most recent onchain NAV value.
- In the case of Lagoon, this is the last value written in the contract with
`updateNewTotalAssets()` and ` settleDeposit()`
- TODO: `updateNewTotalAssets()` there is no way to read pending asset update on chain
:return:
Vault NAV, denominated in :py:meth:`denomination_token`
"""
token = self.denomination_token
raw_amount = self.vault_contract.functions.totalAssets().call()
return token.convert_to_decimals(raw_amount)

@property
def address(self) -> HexAddress:
"""Get the vault smart contract address."""
Expand Down Expand Up @@ -262,6 +277,18 @@ def post_new_valuation(
bound_func = self.vault_contract.functions.updateNewTotalAssets(raw_amount)
return bound_func

def settle(self) -> ContractFunction:
"""Settle the new valuation and deposits.
- settleDeposit will also settle the redeems request if possible
- if there is nothing to settle: no deposit and redeem requests you can still call settleDeposit/settleRedeem to validate the new nav
"""
logger.info("Settling vault %s valuation", )
bound_func = self.vault_contract.functions.settleDeposit()
return bound_func





Expand Down
1 change: 0 additions & 1 deletion eth_defi/vault/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ def fetch_nav(self) -> Decimal:
Vault NAV, denominated in :py:meth:`denomination_token`
"""


@cached_property
def denomination_token(self) -> TokenDetails:
return self.fetch_denomination_token()
Expand Down
23 changes: 22 additions & 1 deletion tests/lagoon/conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
"""Base mainnet fork based tests for Lagoon.
Explore the static deployment which we fork from the Base mainnet:
- Vault UI: https://trading-stategy-users-frontend.vercel.app/vault/8453/0xab4ac28d10a4bc279ad073b1d74bfa0e385c010c
- Vault contract: https://basescan.org/address/0xab4ac28d10a4bc279ad073b1d74bfa0e385c010c#readProxyContract
- Safe UI: https://app.safe.global/home?safe=base:0x20415f3Ec0FEA974548184bdD6e67575D128953F
- Contract: https://basescan.org/address/0x20415f3Ec0FEA974548184bdD6e67575D128953F#readProxyContract
- Safe contract: https://basescan.org/address/0x20415f3Ec0FEA974548184bdD6e67575D128953F#readProxyContract
- Roles: https://app.safe.global/apps/open?safe=base:0x20415f3Ec0FEA974548184bdD6e67575D128953F&appUrl=https%3A%2F%2Fzodiac.gnosisguild.org%2F
"""
import os
Expand Down Expand Up @@ -45,6 +48,12 @@ def valuation_manager() -> HexAddress:
return "0x8358bBFb4Afc9B1eBe4e8C93Db8bF0586BD8331a"


@pytest.fixture()
def safe_address() -> HexAddress:
"""Unlockable Safe multisig as spoofed Anvil account."""
return "0x20415f3Ec0FEA974548184bdD6e67575D128953F"


@pytest.fixture()
def anvil_base_fork(request, vault_owner, usdc_holder, asset_manager, valuation_manager) -> AnvilLaunch:
"""Create a testable fork of live BNB chain.
Expand Down Expand Up @@ -183,6 +192,18 @@ def topped_up_valuation_manager(web3, valuation_manager):
return valuation_manager


@pytest.fixture()
def spoofed_safe(web3, safe_address):
# Topped up with some ETH
tx_hash = web3.eth.send_transaction({
"to": safe_address,
"from": web3.eth.accounts[0],
"value": 9 * 10**18,
})
assert_transaction_success_with_explanation(web3, tx_hash)
return safe_address


# Some addresses for the roles set:
"""
Expand Down
14 changes: 9 additions & 5 deletions tests/lagoon/test_lagoon_valuation.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ def test_lagoon_diagnose_routes(
assert routes.loc["DINO -> USDC"]["Value"] == "-"


@pytest.mark.skip(reason="Unfinished")
def test_lagoon_post_valuation(
web3: Web3,
lagoon_vault: LagoonVault,
Expand All @@ -208,6 +209,7 @@ def test_lagoon_post_valuation(
base_dino: TokenDetails,
uniswap_v2: UniswapV2Deployment,
topped_up_valuation_manager: HexAddress,
spoofed_safe: HexAddress,
):
"""Update vault NAV."""

Expand All @@ -216,7 +218,7 @@ def test_lagoon_post_valuation(

# Check value before update
nav = vault.fetch_nav()
assert nav == pytest.approx(Decimal(0.1))
assert nav == pytest.approx(Decimal(0)) # settle() never called for this vault

universe = TradingUniverse(
spot_token_addresses={
Expand All @@ -241,15 +243,17 @@ def test_lagoon_post_valuation(

portfolio_valuation = nav_calculator.calculate_market_sell_nav(portfolio)

# First post the new valuation as valuation manager
total_value = portfolio_valuation.get_total_equity()
bound_func = vault.post_new_valuation(total_value)
tx_hash = bound_func.transact({"from": valuation_manager}) # Unlocked by anvil
assert_transaction_success_with_explanation(web3, tx_hash)

# Unlocked by anvil
tx_hash = bound_func.transact({"from": valuation_manager})
# Then settle the valuation as the vault owner
bound_func = vault.settle()
tx_hash = bound_func.transact({"from": spoofed_safe})
assert_transaction_success_with_explanation(web3, tx_hash)

# Check value after update
nav = vault.fetch_nav()
assert nav == pytest.approx(Decimal(0.1))


0 comments on commit a628875

Please sign in to comment.