Skip to content
New issue

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

bug: handling token boundaries + invariant #439

Open
Autoparallel opened this issue Sep 1, 2023 · 1 comment
Open

bug: handling token boundaries + invariant #439

Autoparallel opened this issue Sep 1, 2023 · 1 comment

Comments

@Autoparallel
Copy link
Contributor

Autoparallel commented Sep 1, 2023

Issue

I'll do my best to explain here, but what I've found in the the portfolio_simulations shows that we have a massive spike in the invariant as the tokens approach their boundary values. We first see it in the WARN level logs that Portfolio is rejecting the output amount and we loop to reduce the output size by enough:

[2023-09-01T17:52:25Z WARN  portfolio_simulation::strategies] Swap failed due to revert: Portfolio_InvalidInvariant(Portfolio_InvalidInvariant { prev: 6162663215956134642, next: 6157807202322611536 })
[2023-09-01T17:52:25Z WARN  portfolio_simulation::strategies] Shrinking order output size by 0.01%
[2023-09-01T17:52:25Z WARN  portfolio_simulation::strategies] Swap failed due to revert: Portfolio_InvalidInvariant(Portfolio_InvalidInvariant { prev: 6162663215956134642, next: 6161556751258908410 })
[2023-09-01T17:52:25Z WARN  portfolio_simulation::strategies] Shrinking order output size by 0.01%
[2023-09-01T17:52:25Z WARN  arbiter_core::manager] Stopped running environment labeled portfolio

Notice the large previous invariant value.

Background

All of this can be achieved running at commit a696d82eac41abff875c55bdd47135b09932e5ca
In the simulation, we can set the config.toml as so:

[environment_parameters]
label = "portfolio" 
block_rate = 10.0
seed = 0

[price_process_parameters]
# The following constants are used to configure the Ornstein-Uhlenbeck process
# The initial price of the asset.
initial_price = 1.0
# The mean (price) of the process.
mean = 1.0
# The standard deviation of the process.
std_dev = 0.001
# The theta parameter of the process.
# This describes how strongly the process will revert to the mean.
theta = 3.0
# The start time of the process.
t_0 = 0.0
# The end time of the process.
t_n = 1000
# t_n = 1
# The number of steps in the process.
num_steps = 25000
# Seed for the price processes
seed = 1

# We will need two tokens for the simulation.
# One will be the "asset", the other will be the "quote"

[asset_token_parameters]
name = "Arbiter Token X"
symbol = "ARBX"
decimals = 18

[quote_token_parameters]
name = "Arbiter Token Y"
symbol = "ARBY"
decimals = 18


# We need to set the parameters for the Portfolio pool
[portfolio_pool_parameters]
volatility_basis_points = 10
strike_price = 1.0
time_remaining_years = 1
is_perpetual = true
fee_basis_points = 5
priority_fee_basis_points = 0

# LP PARAMETRER
liquidity_mantissa = 1
liquidity_exponent = 20
initial_price = 1.0


# Simulation Parameters
[simulation_parameters]
number_of_paths = 1

Note that the liquidity given here represents 1E20 in wad units, so the maximum we expect either reserves (due to a strike price of 1) to be is X in [0,100] and Y in [0,100+k] where k is the invariant.

The seeding ensures perfect replayability. Taking this now, we can graph out some of these details:
combined_plot_single_0

If we zoom in to where we first see this happen, we can see some interesting phenomenon:
combined_plot_single_1
Notice that at 18533 to 18534 we see the invariant jump massively. Specifically, we have:

invariant_18533 == 214289665497284135 ==  0.214289665497284135
invariant_18534 == 4633509197977427441 == 4.633509197977427441 wad

Also at this point, the arbitrageur massively overshoots the price correction and gains a profit in a single step that amounts to more than the profit up until that point. After this, the arbitrageur starts losing massively, presumably due to the disconnect between its understanding of the pool pricing and swap behavior and the behavior of the contract.

Let's move a bit further down and zoom in:
combined_plot_single_2

From the top down, we can see the portfolio price tracking the external exchange up to price change index 18565. At this point, the price remains constant and no more swaps occur until the 18574 mark.

Some things to note, from 18540 onward, we see behavior that is somewhat unexpected. The Y (quote) reserves remained tied to their boundary, while the X (asset) reserves are still undergoing change. Note that price of this strategy depends implicitly only on the (virtual) reserves of X, hence why price did continue to track.

From 18574 to 18575 we see that the Y reserves jump massively and jump beyond what we would expect the maximum reserves to be. Specifically:

y_reserves_18574 == 99990769527159934700 == 99.990769527159934700 wad
y_reserves_18575 == 484252902085083286100 == 484.252902085083286100 wad

Recall again that Y is bounded by [0,100+k] where k is the invariant (and given we have 100*1E18 liquidity), so the large jump in the invariant allows for this to occur.

@Alexangelj
Copy link
Contributor

Solved by the linked commit, however, introduces a new issue described in #442

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants