Skip to content

Commit 620bfe4

Browse files
Handle more test errors
1 parent 8883c78 commit 620bfe4

10 files changed

+110
-64
lines changed

.pre-commit-config.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,3 @@ repos:
2121
hooks:
2222
- id: isort
2323
args: ["--profile", "black", --line-length=79]
24-
25-
default_language_version:
26-
python: python3.11

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Mainnet:
88

99
1. Curve Stable Registry: A registry of custom pool implementations deployed by Curve Core.
1010
2. Curve Stable Factory: A permissionless [StableSwap](https://curve.fi/files/stableswap-paper.pdf) pool factory, which also acts as a registry for pools that its users create.
11-
3. Curve Crypto Registry: A registry of custom CryptoSwap pool implementaions deployed by Curve Core.
11+
3. Curve Crypto Registry: A registry of custom CryptoSwap pool implementations deployed by Curve Core.
1212
4. Curve Crypto Factory: A permissionless [CryptoSwap](https://curve.fi/files/crypto-pools-paper.pdf) pool factory, which also acts as a registry for pools that its users create.
1313

1414
Each of the child registries are accompanied by a RegistryHandler, which is a contract that wraps around the child registry and enforces the abi implemented in the MetaRegistry. These registry handlers are then added to the MetaRegistry using the `MetaRegistry.add_registry_handler` method.
@@ -67,9 +67,9 @@ Out[1]: '3pool'
6767

6868
#### `MetaRegistry.is_meta`
6969

70-
Metapools are pools that pair a coin to a base pool comprising of multiple coins.
70+
Meta-pools are pools that pair a coin to a base pool comprising multiple coins.
7171

72-
An example is the [`LUSD-3CRV`](https://etherscan.io/address/0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca) pool which pairs [Liquity's](https://www.liquity.org/) [`LUSD`](https://etherscan.io/address/0x5f98805a4e8be255a32880fdec7f6728c6568ba0) against [`3CRV`](https://etherscan.io/address/0x6c3f90f043a72fa612cbac8115ee7e52bde6e490), where `3CRV` is a liquidity pool token that represents a share of a pool containing `DAI`, `USDC` and `USDT`:
72+
An example is the [`LUSD-3CRV`](https://etherscan.io/address/0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca) pool which pairs [Liquidity's](https://www.liquity.org/) [`LUSD`](https://etherscan.io/address/0x5f98805a4e8be255a32880fdec7f6728c6568ba0) against [`3CRV`](https://etherscan.io/address/0x6c3f90f043a72fa612cbac8115ee7e52bde6e490), where `3CRV` is a liquidity pool token that represents a share of a pool containing `DAI`, `USDC` and `USDT`:
7373

7474
```
7575
In [1]: metaregistry.is_meta("0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca")
@@ -294,7 +294,7 @@ For CryptoSwap, the getter returns:
294294
4. Allowed extra profit
295295
5. Fee gamma
296296
6. Adjustment step
297-
7. MA (moving average) half time
297+
7. MA (moving average) half-time
298298

299299
```
300300
@@ -338,7 +338,7 @@ Out[1]: '0xc4AD29ba4B3c580e6D59105FFf484999997675Ff'
338338

339339
#### `MetaRegistry.get_pool_asset_type`
340340

341-
Gets the asset type of a pool. `0` = `USD`, `1` = `ETH`, `2` = `BTC`, `3` = Other, `4` = CryptoPool token. The asset type is a property of StableSwaps, and is not enforced in CryptoSwap pools (which always return `4`).
341+
Gets the asset type of pool. `0` = `USD`, `1` = `ETH`, `2` = `BTC`, `3` = Other, `4` = CryptoPool token. The asset type is a property of StableSwaps, and is not enforced in CryptoSwap pools (which always return `4`).
342342

343343
StableSwap pool example for `LUSD-3CRV` pool which is a `USD` stablecoin pool:
344344

scripts/change_registry_handler.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
import boa
44
from rich.console import Console as RichConsole
55

6-
from scripts.deployment_utils import setup_environment, ZERO_ADDRESS, get_deployed_contract
6+
from scripts.deployment_utils import (
7+
ADDRESS_PROVIDER,
8+
ZERO_ADDRESS,
9+
get_deployed_contract,
10+
setup_environment,
11+
)
712

813
RICH_CONSOLE = RichConsole(file=sys.stdout)
914
CRYPTO_REGISTRY_HANDLER = "0x5f493fEE8D67D3AE3bA730827B34126CFcA0ae94"

scripts/deployment_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def setup_environment(console: RichConsole):
3636
boa.env.eoa = FIDDY_DEPLOYER
3737
return False
3838

39+
3940
def get_deployed_contract(contract_name: str, address: str) -> VyperContract:
4041
"""
4142
Loads a contract and retrieves a deployed instance of it with the given address.

scripts/setup_metaregistry.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
import boa
1414
from rich.console import Console as RichConsole
1515

16-
from scripts.deployment_utils import ZERO_ADDRESS, get_deployed_contract, setup_environment
16+
from scripts.deployment_utils import (
17+
ZERO_ADDRESS,
18+
get_deployed_contract,
19+
setup_environment,
20+
)
1721

1822
RICH_CONSOLE = RichConsole(file=sys.stdout)
1923

tests/mainnet/metaregistry/api/test_find_pool_for_coins.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import itertools
1+
from itertools import combinations
2+
from os import environ
3+
4+
import pytest
25

36
from tests.utils import ZERO_ADDRESS
47

@@ -11,10 +14,14 @@ def _get_all_combinations(metaregistry, pool):
1114
pool_coins = [
1215
coin for coin in metaregistry.get_coins(pool) if coin != ZERO_ADDRESS
1316
]
14-
all_combinations = list(itertools.combinations(pool_coins, 2))
17+
all_combinations = list(combinations(pool_coins, 2))
1518
first_coin = pool_coins[0]
1619

17-
if metaregistry.is_meta(pool):
20+
# there exist some pools with an LP token as the first coin, that's incorrect
21+
# example: 0xf5d5305790c1af08e9df44b30a1afe56ccda72df
22+
is_first_coin_lp_token = metaregistry.get_pool_from_lp_token(first_coin)
23+
24+
if metaregistry.is_meta(pool) and not is_first_coin_lp_token:
1825
underlying_coins = [
1926
coin
2027
for coin in metaregistry.get_underlying_coins(pool)
@@ -29,16 +36,18 @@ def _get_all_combinations(metaregistry, pool):
2936
return all_combinations
3037

3138

39+
@pytest.mark.skipif(
40+
condition=environ.get("TEST_ALL") == "False",
41+
reason="This test is too slow, don't run it locally every time.",
42+
)
3243
def test_all(populated_metaregistry, pool):
33-
combinations = _get_all_combinations(populated_metaregistry, pool)
34-
for combination in combinations:
44+
all_combinations = _get_all_combinations(populated_metaregistry, pool)
45+
for coin1, coin2 in all_combinations:
3546
pools_containing_pair = populated_metaregistry.find_pools_for_coins(
36-
*combination
47+
coin1, coin2
3748
)
3849
assert pool in pools_containing_pair
3950

4051
for i, found_pool in enumerate(pools_containing_pair):
41-
assert (
42-
populated_metaregistry.find_pool_for_coins(*combination, i)
43-
== found_pool
44-
)
52+
pool = populated_metaregistry.find_pool_for_coins(coin1, coin2, i)
53+
assert pool == found_pool

tests/mainnet/metaregistry/api/test_get_admin_balances.py

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
from boa import BoaError
44
from eth.codecs.abi.exceptions import DecodeError as ABIDecodeError
55

6-
from tests.utils import ZERO_ADDRESS, get_deployed_token_contract
6+
from tests.utils import (
7+
assert_negative_coin_balance,
8+
check_decode_error,
9+
get_deployed_token_contract,
10+
)
711

812

913
def pre_test_checks(metaregistry, pool):
@@ -29,31 +33,12 @@ def pre_test_checks(metaregistry, pool):
2933
if contract.totalSupply() == 0:
3034
return pytest.skip("LP token supply is zero")
3135
except ABIDecodeError as e:
32-
assert e.msg == "Value length is not the expected size of 32 bytes"
33-
assert len(e.value) == 4096
36+
check_decode_error(e)
3437
return pytest.skip(
3538
f"Pool {pool} cannot decode the total supply of its LP token {lp_token}"
3639
)
3740

3841

39-
def assert_negative_coin_balance(metaregistry, pool):
40-
"""
41-
The implementation of get_balance calculates (balance - admin_balance) but sometimes the coin
42-
balance might be lower than the admin balance, resulting in an uint underflow.
43-
"""
44-
coins = [
45-
coin for coin in metaregistry.get_coins(pool) if coin != ZERO_ADDRESS
46-
]
47-
coin_balances = [
48-
get_deployed_token_contract(coin).balanceOf(pool) for coin in coins
49-
]
50-
admin_balances = metaregistry.get_admin_balances(pool)
51-
assert any(
52-
coin_balance < admin_balance
53-
for coin_balance, admin_balance in zip(coin_balances, admin_balances)
54-
)
55-
56-
5742
def test_stable_registry_pools(
5843
populated_metaregistry, stable_registry_pool, stable_registry
5944
):

tests/mainnet/metaregistry/api/test_get_underlying_decimals.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
def _test_underlying_decimals_getter(metaregistry, registry, pool):
1919
metaregistry_output = metaregistry.get_underlying_decimals(pool)
20-
assert metaregistry_output[1] != 0 # there has to be a second coin!
2120

2221
pool_is_metapool = metaregistry.is_meta(pool)
2322
if pool in EXCEPTIONS:

tests/mainnet/metaregistry/api/test_get_virtual_price.py

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@
33
import boa
44
import pytest
55
from boa import BoaError
6+
from eth.codecs.abi.exceptions import DecodeError as ABIDecodeError
67

7-
from tests.utils import ZERO_ADDRESS, get_deployed_token_contract
8+
from tests.utils import (
9+
ZERO_ADDRESS,
10+
assert_negative_coin_balance,
11+
check_decode_error,
12+
get_deployed_token_contract,
13+
)
814

915
# ---- sanity checks since vprice getters can revert for specific pools states ----
1016

@@ -36,18 +42,21 @@ def _check_skem_tokens_with_weird_decimals(
3642

3743
pool_balances_float.append(pool_balances[i] / 10 ** coin_decimals[i])
3844

39-
if (
40-
coin_decimals[i] == 0
41-
and get_deployed_token_contract(
42-
metaregistry.get_coins(pool)[0]
43-
).decimals()
44-
== 0
45-
):
46-
with boa.reverts():
45+
first_coin = metaregistry.get_coins(pool)[0]
46+
coin_contract = get_deployed_token_contract(first_coin)
47+
if coin_decimals[i] == 0 and coin_contract.decimals() == 0:
48+
try:
49+
virtual_price = metaregistry.get_virtual_price_from_lp_token(
50+
lp_token
51+
)
52+
warnings.warn(
53+
f"Pool {pool} virtual price {virtual_price}. continuing test"
54+
)
55+
except BoaError:
4756
metaregistry.get_virtual_price_from_lp_token(lp_token)
48-
pytest.skip(
49-
f"skem token {coins[i]} in pool {pool} with zero decimals"
50-
)
57+
pytest.skip(
58+
f"Skem token {coins[i]} in pool {pool} with zero decimals"
59+
)
5160

5261
return pool_balances_float
5362

@@ -69,23 +78,26 @@ def _check_pool_is_depegged(
6978
and min(pool_balances_float) < 1
7079
):
7180
try:
72-
with boa.reverts():
73-
metaregistry.get_virtual_price_from_lp_token(lp_token)
74-
81+
virtual_price = metaregistry.get_virtual_price_from_lp_token(
82+
lp_token
83+
)
84+
warnings.warn(
85+
f"Pool {pool} virtual price {virtual_price}. continuing test"
86+
)
87+
except BoaError:
7588
pytest.skip(
7689
f"skewed pool: {pool} as num coins (decimals divided) at index {i} is "
7790
f"{pool_balances[i] / 10 ** coin_decimals[i]}"
7891
)
79-
except (
80-
AssertionError
81-
): # ok to catch this assertion error since we continue testing
82-
warnings.warn(
83-
"pool virtual price getter did not revert. continuing test"
84-
)
8592

8693

8794
def pre_test_checks(metaregistry, pool):
88-
pool_balances = metaregistry.get_balances(pool)
95+
try:
96+
pool_balances = metaregistry.get_balances(pool)
97+
except BoaError:
98+
assert_negative_coin_balance(metaregistry, pool)
99+
return pytest.skip(f"Pool {pool} has coin balances lower than admin")
100+
89101
lp_token = metaregistry.get_lp_token(pool)
90102

91103
_check_pool_has_no_liquidity(metaregistry, pool, pool_balances, lp_token)
@@ -139,6 +151,11 @@ def test_stable_factory_pools(
139151
except BoaError:
140152
with boa.reverts():
141153
populated_metaregistry.get_virtual_price_from_lp_token(lp_token)
154+
except ABIDecodeError as e:
155+
check_decode_error(e)
156+
return pytest.skip(
157+
f"Pool {stable_factory_pool} cannot decode the virtual price"
158+
)
142159

143160

144161
def test_crypto_registry_pools(

tests/utils.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import boa
66
from boa.vyper.contract import VyperContract
7+
from eth.codecs.abi.exceptions import DecodeError as ABIDecodeError
78
from eth_account.signers.local import LocalAccount
89

910
ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"
@@ -98,3 +99,31 @@ def get_deployed_token_contract(address: str) -> VyperContract:
9899
]
99100
)
100101
return boa.loads_abi(abi).at(address)
102+
103+
104+
def check_decode_error(e: ABIDecodeError):
105+
"""
106+
Checks that the error message is the expected decode error.
107+
This seems to be happening in some pools, but it's not clear if it's a boa or contract issue.
108+
:param e: The error to check.
109+
"""
110+
assert e.msg == "Value length is not the expected size of 32 bytes"
111+
assert len(e.value) == 4096
112+
113+
114+
def assert_negative_coin_balance(metaregistry, pool):
115+
"""
116+
The implementation of get_balance calculates (balance - admin_balance) but sometimes the coin
117+
balance might be lower than the admin balance, resulting in an uint underflow.
118+
"""
119+
coins = [
120+
coin for coin in metaregistry.get_coins(pool) if coin != ZERO_ADDRESS
121+
]
122+
coin_balances = [
123+
get_deployed_token_contract(coin).balanceOf(pool) for coin in coins
124+
]
125+
admin_balances = metaregistry.get_admin_balances(pool)
126+
assert any(
127+
coin_balance < admin_balance
128+
for coin_balance, admin_balance in zip(coin_balances, admin_balances)
129+
)

0 commit comments

Comments
 (0)