Closed evangriffiths closed 5 months ago
Writing down some notes for when we get to this issue:
-> When we first load an OmenAgentMarket
, the property outcome_token_amounts
comes from the subgraph. If we trade against that market on the fork (local_web3
) or inside an RPC from Tenderly, the subgraph doesn't pick that up, hence the reserves are not affected. The proper way to fetch an updated value is by reading data directly from the contract, using the web3 provider from the test.
-> Let's say Bob wants to sell 10 Yes outcome tokens to market A. The functon to be called is market_contract.sell
, with args (from function sell(uint returnAmount, uint outcomeIndex, uint maxOutcomeTokensToSell) external {):
function sell(uint returnAmount, uint outcomeIndex, uint maxOutcomeTokensToSell) external {
-> maxOutcomeTokensToSell
is trivial and can be set as equal the number of outcome tokens the user has (via market.get_token_balance(
)
-> The tricky part is returnAmount
, which is the current value in xDAI of maxOutcomeTokensToSell
(or whichever amount of outcome_tokens
the user wants to sell). What we need here is the inverse of calcSellAmount
, which is used in the smart contract as per below:
uint outcomeTokensToSell = calcSellAmount(returnAmount, outcomeIndex);
There is already an implementation for this function (calculate_sell_amount_in_collateral
- link) - however it delivers results that have a small discrepancy (~ 1e-3 xDAI) from the correct value. This results in a non-zero position even though the user tries to sell his entire outcome_tokens
position (see test).
-> When we first load an OmenAgentMarket, the property outcome_token_amounts comes from the subgraph. If we trade against that market on the fork (local_web3) or inside an RPC from Tenderly, the subgraph doesn't pick that up, hence the reserves are not affected. The proper way to fetch an updated value is by reading data directly from the contract, using the web3 provider from the test.
This is the issue!!
The test was doing:
market = get_market() # market.outcome_token_amounts is fixed now
market.buy_tokens(amount_xdai) # the pool balance changes, but market.outcome_token_amounts doesn't!
market.sell_tokens(amount_tokens) # the calculation uses incorrect pool balance amounts!!
The reason why the microchain didn't see this problem is because it always does get_market
before buying and selling, so the outcome_token_amounts are always up to date with the subgraph. I've fixed it now (here https://github.com/gnosis/prediction-market-agent-tooling/pull/272) to get the pool balance via the smart contract just before calculating the sell colateral.
The CI test appears to be flaky. It passed originally!, but appears to fail depending on:
Understand why there is this discrepancy, and fix.