We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vyper 0.3.10 and titanoboa @ git+https://github.com/vyperlang/titanoboa@a06e134b25c8206cb4d6d76521e6705111e92c68
In the unit test, test_allocate_balance_adapter_tx, the types that get returned back shift around unnaturally.
Also mypy complains about titanoboa.
$ mypy tests_boa/test_yield_bearing_asset_funds_allocator.py tests_boa/test_yield_bearing_asset_funds_allocator.py:3: error: Skipping analyzing "boa": module is installed, but missing library stubs or py.typed marker [import-untyped] tests_boa/test_yield_bearing_asset_funds_allocator.py:4: error: Skipping analyzing "boa.util.abi": module is installed, but missing library stubs or py.typed marker [import-untyped] tests_boa/test_yield_bearing_asset_funds_allocator.py:4: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports Found 2 errors in 1 file (checked 1 source file) (AdapterBoa) scherrey@squire:~/projects/adapter-fi/AdapterVault $
test_yield_bearing_asset_funds_allocator.py
import pytest import boa from boa.util.abi import Address as Address from decimal import Decimal from dataclasses import dataclass, field # ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" # MAX_ADAPTERS = 5 # Must match the value from AdapterVault.vy @pytest.fixture def deployer(): acc = boa.env.generate_address(alias="deployer") boa.env.set_balance(acc, 1000*10**18) return acc # @pytest.fixture # def trader(): # acc = boa.env.generate_address(alias="trader") # boa.env.set_balance(acc, 1000*10**18) # return acc # @pytest.fixture # def dai(deployer, trader): # with boa.env.prank(deployer): # erc = boa.load("contracts/test_helpers/ERC20.vy", "DAI Token", "DAI", 18, 1000*10**18, deployer) # erc.mint(deployer, 100000) # erc.mint(trader, 100000) # return erc # @pytest.fixture # def erc20(deployer, trader): # with boa.env.prank(deployer): # erc = boa.load("contracts/test_helpers/ERC20.vy", "ERC20", "Coin", 18, 1000*10**18, deployer) # erc.mint(deployer, 100000) # erc.mint(trader, 100000) # return erc @pytest.fixture def funds_alloc(deployer): with boa.env.prank(deployer): f = boa.load("contracts/YieldBearingAssetFundsAllocator.vy") return f def test_is_full_rebalance(funds_alloc): assert funds_alloc.internal._is_full_rebalance() == False max_uint256 = 2**256 - 1 max_int256 = 2**255 - 1 min_uint256 = 0 min_int256 = -2**255 neutral_max_deposit = max_int256 - 42 @dataclass class BalanceAdapter: adapter: Address current: int = field(default=0) last_value: int = field(default=0) max_deposit: int = field(default=max_int256) max_withdraw: int = field(default=min_int256) ratio: int = field(default=0) target: int = field(default=0) delta: int = field(default=0) @classmethod def from_dict(cls, data: dict): return cls(**data) def to_tuple(self): return ( self.adapter, self.current, self.last_value, self.max_deposit, self.max_withdraw, self.ratio, self.target, self.delta ) def from_tuple(self, t): self.adapter = Address(t[0]), self.current = t[1], self.last_value = t[2], self.max_deposit = t[3], self.max_withdraw = t[4], self.ratio = t[5], self.target = t[6], self.delta = t[7] balance_adapters_data = [ ({ 'adapter': Address('0x0000000000000000000000000000000000000001'), 'current': 1000, 'last_value': 900, 'ratio': 10 }, {'exception': None, 'ratio_value': 100, 'target':1000, 'delta':0, 'leftovers':0, 'block': False, 'neutral': False}), #({ 'adapter': Address('0x0000000000000000000000000000000000000002'), 'current': 1500, 'last_value': 1500, 'max_deposit': 1000, 'ratio': 20 }, # {'exception': None, 'ratio_value': 100, 'target':2000, 'delta':500, 'leftovers':0, 'block': False, 'neutral': False}), ] def test_allocate_balance_adapter_tx(funds_alloc): for adapter_data in balance_adapters_data: adapter = BalanceAdapter.from_dict(adapter_data[0]) print("adapter = %s" % adapter) target_result = adapter_data[1] adapter_tuple = adapter.to_tuple() # result = funds_alloc.internal._allocate_balance_adapter_tx(100, adapter_tuple) # This fails with boa now. allocated_adapter, leftovers, block_adapter, neutral_adapter = funds_alloc.allocate_balance_adapter_tx(target_result['ratio_value'], adapter_tuple) print("allocated_adapter[0] = %s" % allocated_adapter[0]) print("allocated_adapter[1] = %s" % allocated_adapter[1]) print("type(allocated_adapter[0]) = %s" % type(allocated_adapter[0])) print("before type(adapter.adapter) = %s" % type(adapter.adapter)) adapter.from_tuple(allocated_adapter) print("after type(adapter.adapter) = %s" % type(adapter.adapter)) print("adapter.adapter = %s" % Address(adapter.adapter[0])) print("adapter_data[0]['adapter'] = %s" % adapter_data[0]['adapter']) print("type(adapter.adapter) = %s" % type(adapter.adapter)) print("type(adapter_data[0]['adapter']) = %s" % type(adapter_data[0]['adapter'])) print("adapter.adapter == adapter_data[0]['adapter'] = %s" % adapter.adapter == adapter_data[0]['adapter']) assert Address(adapter.adapter[0]) == adapter_data[0]['adapter'] # BDM WTF?!?!? Why is adapter.adapter becoming a tuple???? assert adapter.current == adapter_data[0]['current'] adapter.target = target_result['target'] # 100 * adapter.ratio adapter.delta = target_result['delta'] # adapter.target - adapter.current #assert result == (adapter.to_tuple(), target_result['leftovers'], target_result['block'], target_result['neutral'])
YieldBearingAssetFundsAllocator.vy
#pragma evm-version cancun """ @title Adapter Fund Allocation Logic @license Copyright 2023, 2024 Biggest Lab Co Ltd, Benjamin Scherrey, Sajal Kayan, and Eike Caldeweyher @author BiggestLab (https://biggestlab.io) Benjamin Scherrey """ ## ## Must match AdapterVault.vy ## MAX_ADAPTERS : constant(uint256) = 5 ADAPTER_BREAKS_LOSS_POINT : constant(decimal) = 0.05 # This structure must match definition in AdapterVault.vy struct BalanceTX: qty: int256 adapter: address # This structure must match definition in AdapterVault.vy struct BalanceAdapter: adapter: address current: uint256 last_value: uint256 max_deposit: int256 max_withdraw: int256 # represented as a negative number ratio: uint256 target: uint256 delta: int256 @external @view def getBalanceTxs(_vault_balance: uint256, _target_asset_balance: uint256, _min_proposer_payout: uint256, _total_assets: uint256, _total_ratios: uint256, _adapter_states: BalanceAdapter[MAX_ADAPTERS], _withdraw_only : bool = False) -> (BalanceTX[MAX_ADAPTERS], address[MAX_ADAPTERS]): return self._getBalanceTxs(_vault_balance, _target_asset_balance, _min_proposer_payout, _total_assets, _total_ratios, _adapter_states, _withdraw_only ) @internal @pure def _getBalanceTxs(_vault_balance: uint256, _target_asset_balance: uint256, _min_proposer_payout: uint256, _total_assets: uint256, _total_ratios: uint256, _adapter_states: BalanceAdapter[MAX_ADAPTERS], _withdraw_only : bool = False) -> (BalanceTX[MAX_ADAPTERS], address[MAX_ADAPTERS]): # _BDM TODO : max_txs is ignored for now. adapter_txs : BalanceTX[MAX_ADAPTERS] = empty(BalanceTX[MAX_ADAPTERS]) blocked_adapters : address[MAX_ADAPTERS] = empty(address[MAX_ADAPTERS]) adapter_states: BalanceAdapter[MAX_ADAPTERS] = empty(BalanceAdapter[MAX_ADAPTERS]) d4626_delta : int256 = 0 tx_count : uint256 = 0 #d4626_delta, tx_count, adapter_states, blocked_adapters = self._getTargetBalances(_vault_balance, _target_asset_balance, _total_assets, _total_ratios, _adapter_states, _min_proposer_payout, _withdraw_only) pos : uint256 = 0 for tx_bal in adapter_states: adapter_txs[pos] = BalanceTX({qty: tx_bal.delta, adapter: tx_bal.adapter}) pos += 1 return adapter_txs, blocked_adapters @internal @view def _is_full_rebalance() -> bool: return False NEUTRAL_ADAPTER_MAX_DEPOSIT : constant(int256) = max_value(int256) - 42 @internal @pure def _allocate_balance_adapter_tx(_ratio_value : uint256, _balance_adapter : BalanceAdapter) -> (BalanceAdapter, int256, bool, bool): """ Given a value per strategy ratio and an un-allocated BalanceAdapter, return the newly allocated BalanceAdapter constrained by min & max limits and also identify if this adapter should be blocked due to unexpected losses, plus identify whether or not this is our "neutral adapter". """ is_neutral_adapter : bool = _balance_adapter.max_deposit == NEUTRAL_ADAPTER_MAX_DEPOSIT # Have funds been lost? should_we_block_adapter : bool = False if _balance_adapter.current < _balance_adapter.last_value: # There's an unexpected loss of value. Let's try to empty this adapter and stop # further allocations to it by setting the ratio to 0 going forward. # This will not necessarily result in any "leftovers" unless withdrawing the full # balance of the adapter is limited by max_withdraw limits below. _balance_adapter.ratio = 0 should_we_block_adapter = True target : uint256 = _ratio_value * _balance_adapter.ratio delta : int256 = convert(_balance_adapter.current, int256) - convert(target, int256) leftovers : int256 = 0 # Limit deposits to max_deposit if delta > _balance_adapter.max_deposit: leftovers = _balance_adapter.max_deposit - delta delta = _balance_adapter.max_deposit # Limit withdraws to max_withdraw elif delta < _balance_adapter.max_withdraw: leftovers = delta - _balance_adapter.max_withdraw delta = _balance_adapter.max_withdraw _balance_adapter.delta = delta _balance_adapter.target = target # We are not adjusting the optimium target for now. return _balance_adapter, leftovers, should_we_block_adapter, is_neutral_adapter @external @pure def allocate_balance_adapter_tx(_ratio_value : uint256, _balance_adapter : BalanceAdapter) -> (BalanceAdapter, int256, bool, bool): return self._allocate_balance_adapter_tx(_ratio_value, _balance_adapter)
Execution of test run:
$ make test tests_boa/test_yield_bearing_asset_funds_allocator.py pytest tests_boa/ --ignore tests_boa/test_transient.py tests_boa/test_yield_bearing_asset_funds_allocator.py ============================================================================== test session starts =============================================================================== platform linux -- Python 3.11.2, pytest-8.2.1, pluggy-1.5.0 rootdir: /home/scherrey/projects/adapter-fi/AdapterVault plugins: hypothesis-6.103.0, cov-5.0.0, titanoboa-0.1.10b1, web3-6.11.0 collected 2 items tests_boa/test_yield_bearing_asset_funds_allocator.py .F [100%] ==================================================================================== FAILURES ==================================================================================== ________________________________________________________________________ test_allocate_balance_adapter_tx ________________________________________________________________________ funds_alloc = <contracts/YieldBearingAssetFundsAllocator.vy at 0x8A369A3a3a60866B01ABB5b30D3Cce00F06b98F2, compiled with vyper-0.3.10+9136169> def test_allocate_balance_adapter_tx(funds_alloc): for adapter_data in balance_adapters_data: adapter = BalanceAdapter.from_dict(adapter_data[0]) print("adapter = %s" % adapter) target_result = adapter_data[1] adapter_tuple = adapter.to_tuple() # result = funds_alloc.internal._allocate_balance_adapter_tx(100, adapter_tuple) # This fails with boa now. allocated_adapter, leftovers, block_adapter, neutral_adapter = funds_alloc.allocate_balance_adapter_tx(target_result['ratio_value'], adapter_tuple) print("allocated_adapter[0] = %s" % allocated_adapter[0]) print("allocated_adapter[1] = %s" % allocated_adapter[1]) print("type(allocated_adapter[0]) = %s" % type(allocated_adapter[0])) print("before type(adapter.adapter) = %s" % type(adapter.adapter)) adapter.from_tuple(allocated_adapter) print("after type(adapter.adapter) = %s" % type(adapter.adapter)) print("adapter.adapter = %s" % Address(adapter.adapter[0])) print("adapter_data[0]['adapter'] = %s" % adapter_data[0]['adapter']) print("type(adapter.adapter) = %s" % type(adapter.adapter)) print("type(adapter_data[0]['adapter']) = %s" % type(adapter_data[0]['adapter'])) print("adapter.adapter == adapter_data[0]['adapter'] = %s" % adapter.adapter == adapter_data[0]['adapter']) assert Address(adapter.adapter[0]) == adapter_data[0]['adapter'] # BDM WTF?!?!? Why is adapter.adapter becoming a tuple???? > assert adapter.current == adapter_data[0]['current'] E AssertionError: assert (1000,) == 1000 E + where (1000,) = BalanceAdapter(adapter=(Address('0x0000000000000000000000000000000000000001'),), current=(1000,), last_value=(900,), m...-57896044618658097711785492504343953926634992332820282019728792003956564819968,), ratio=(10,), target=(1000,), delta=0).current tests_boa/test_yield_bearing_asset_funds_allocator.py:121: AssertionError ------------------------------------------------------------------------------ Captured stdout call ------------------------------------------------------------------------------ adapter = BalanceAdapter(adapter=Address('0x0000000000000000000000000000000000000001'), current=1000, last_value=900, max_deposit=57896044618658097711785492504343953926634992332820282019728792003956564819967, max_withdraw=-57896044618658097711785492504343953926634992332820282019728792003956564819968, ratio=10, target=0, delta=0) allocated_adapter[0] = 0x0000000000000000000000000000000000000001 allocated_adapter[1] = 1000 type(allocated_adapter[0]) = <class 'boa.util.abi.Address'> before type(adapter.adapter) = <class 'boa.util.abi.Address'> after type(adapter.adapter) = <class 'tuple'> adapter.adapter = 0x0000000000000000000000000000000000000001 adapter_data[0]['adapter'] = 0x0000000000000000000000000000000000000001 type(adapter.adapter) = <class 'tuple'> type(adapter_data[0]['adapter']) = <class 'boa.util.abi.Address'> False ============================================================================ short test summary info ============================================================================= FAILED tests_boa/test_yield_bearing_asset_funds_allocator.py::test_allocate_balance_adapter_tx - AssertionError: assert (1000,) == 1000 ========================================================================== 1 failed, 1 passed in 0.31s =========================================================================== make: *** [Makefile:41: test] Error 1 (AdapterBoa) scherrey@squire:~/projects/adapter-fi/AdapterVault $
The text was updated successfully, but these errors were encountered:
Opened up issue vyperlang/titanoboa#262
d7fbf6b
i think maybe the bug is in your implementation of BalanceAdapter.from_tuple()? adapter-fi/AdapterVault@d7fbf6b#diff-a9b84898eba76eb6d9fb13497ebefe93ee7ab2d201f54741dba470f64a257fa5R84 looks like it has a trailing comma which might be unintentional
BalanceAdapter.from_tuple()
self.adapter = Address(t[0]), # <- trailing comma
Sorry, something went wrong.
No branches or pull requests
Vyper 0.3.10 and titanoboa @ git+https://github.com/vyperlang/titanoboa@a06e134b25c8206cb4d6d76521e6705111e92c68
In the unit test, test_allocate_balance_adapter_tx, the types that get returned back shift around unnaturally.
Also mypy complains about titanoboa.
test_yield_bearing_asset_funds_allocator.py
YieldBearingAssetFundsAllocator.vy
Execution of test run:
The text was updated successfully, but these errors were encountered: