Skip to content

Commit

Permalink
Process invalid answers (#333)
Browse files Browse the repository at this point in the history
  • Loading branch information
kongzii authored Aug 5, 2024
1 parent 97c4a09 commit 69ec60e
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
OMEN_TRUE_OUTCOME = "Yes"
OMEN_FALSE_OUTCOME = "No"
INVALID_ANSWER = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
INVALID_ANSWER_HEX_BYTES = HexBytes(INVALID_ANSWER)
OMEN_BASE_URL = "https://aiomen.eth.limo"
PRESAGIO_BASE_URL = "https://presagio.pages.dev"

Expand Down
56 changes: 47 additions & 9 deletions prediction_market_agent_tooling/markets/omen/omen_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
wei_type,
xdai_type,
)
from prediction_market_agent_tooling.markets.omen.data_models import (
INVALID_ANSWER_HEX_BYTES,
)
from prediction_market_agent_tooling.tools.contract import (
ContractDepositableWrapperERC20OnGnosisChain,
ContractERC20OnGnosisChain,
Expand Down Expand Up @@ -562,8 +565,7 @@ def submitAnswer(
self,
api_keys: APIKeys,
question_id: HexBytes,
answer: str,
outcomes: list[str],
answer: HexBytes,
bond: Wei,
max_previous: Wei | None = None,
web3: Web3 | None = None,
Expand All @@ -573,24 +575,60 @@ def submitAnswer(
# same as on Omen website: https://github.com/protofire/omen-exchange/blob/763d9c9d05ebf9edacbc1dbaa561aa5d08813c0f/app/src/services/realitio.ts#L363.
max_previous = Wei(0)

# Normalise the answer to lowercase, to match Enum values as [YES, NO] against outcomes as ["Yes", "No"].
answer = answer.lower()
outcomes = [o.lower() for o in outcomes]

return self.send_with_value(
api_keys=api_keys,
function_name="submitAnswer",
function_params=dict(
question_id=question_id,
answer=int_to_hexbytes(
outcomes.index(answer)
), # Contract's method expects answer index in bytes.
answer=answer,
max_previous=max_previous,
),
amount_wei=bond,
web3=web3,
)

def submit_answer(
self,
api_keys: APIKeys,
question_id: HexBytes,
answer: str,
outcomes: list[str],
bond: Wei,
max_previous: Wei | None = None,
web3: Web3 | None = None,
) -> TxReceipt:
# Normalise the answer to lowercase, to match Enum values as [YES, NO] against outcomes as ["Yes", "No"].
answer = answer.lower()
outcomes = [o.lower() for o in outcomes]

return self.submitAnswer(
api_keys=api_keys,
question_id=question_id,
answer=int_to_hexbytes(
outcomes.index(answer)
), # Contract's method expects answer index in bytes.
bond=bond,
max_previous=max_previous,
web3=web3,
)

def submit_answer_invalid(
self,
api_keys: APIKeys,
question_id: HexBytes,
bond: Wei,
max_previous: Wei | None = None,
web3: Web3 | None = None,
) -> TxReceipt:
return self.submitAnswer(
api_keys=api_keys,
question_id=question_id,
answer=INVALID_ANSWER_HEX_BYTES,
bond=bond,
max_previous=max_previous,
web3=web3,
)

def claimWinnings(
self,
api_keys: APIKeys,
Expand Down
51 changes: 48 additions & 3 deletions prediction_market_agent_tooling/markets/omen/omen_resolving.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import datetime

from web3 import Web3

from prediction_market_agent_tooling.config import APIKeys
Expand Down Expand Up @@ -140,6 +142,7 @@ def claim_bonds_on_realitio_question(
def finalize_markets(
api_keys: APIKeys,
markets_with_resolutions: list[tuple[OmenMarket, Resolution | None]],
wait_n_days_before_invalid: int = 30,
web3: Web3 | None = None,
) -> list[HexAddress]:
finalized_markets: list[HexAddress] = []
Expand All @@ -148,9 +151,24 @@ def finalize_markets(
logger.info(
f"[{idx+1} / {len(markets_with_resolutions)}] Looking into {market.url=} {market.question_title=}"
)
closed_before_days = (datetime.now() - market.close_time).days

if resolution is None:
logger.warning(f"No resolution provided for {market.url=}")
if closed_before_days > wait_n_days_before_invalid:
logger.warning(
f"Finalizing as invalid, market closed before {closed_before_days} days: {market.url=}"
)
omen_submit_invalid_answer_market_tx(
api_keys,
market,
OMEN_DEFAULT_REALITIO_BOND_VALUE,
web3=web3,
)

else:
logger.warning(
f"Skipping, no resolution provided, market closed before {closed_before_days} days: {market.url=}"
)

elif resolution in (Resolution.YES, Resolution.NO):
logger.info(f"Found resolution {resolution.value=} for {market.url=}")
Expand All @@ -165,7 +183,15 @@ def finalize_markets(
logger.info(f"Finalized {market.url=}")

else:
logger.error(f"Invalid resolution found, {resolution=}, for {market.url=}")
logger.warning(
f"Invalid resolution found, {resolution=}, for {market.url=}, finalizing as invalid."
)
omen_submit_invalid_answer_market_tx(
api_keys,
market,
OMEN_DEFAULT_REALITIO_BOND_VALUE,
web3=web3,
)

return finalized_markets

Expand Down Expand Up @@ -199,7 +225,7 @@ def omen_submit_answer_market_tx(
And after the period is over, you need to resolve the market using `omen_resolve_market_tx`.
"""
realitio_contract = OmenRealitioContract()
realitio_contract.submitAnswer(
realitio_contract.submit_answer(
api_keys=api_keys,
question_id=market.question.id,
answer=resolution.value,
Expand All @@ -209,6 +235,25 @@ def omen_submit_answer_market_tx(
)


def omen_submit_invalid_answer_market_tx(
api_keys: APIKeys,
market: OmenMarket,
bond: xDai,
web3: Web3 | None = None,
) -> None:
"""
After the answer is submitted, there is 24h waiting period where the answer can be challenged by others.
And after the period is over, you need to resolve the market using `omen_resolve_market_tx`.
"""
realitio_contract = OmenRealitioContract()
realitio_contract.submit_answer_invalid(
api_keys=api_keys,
question_id=market.question.id,
bond=xdai_to_wei(bond),
web3=web3,
)


def omen_resolve_market_tx(
api_keys: APIKeys,
market: OmenMarket,
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "prediction-market-agent-tooling"
version = "0.45.1"
version = "0.46.0"
description = "Tools to benchmark, deploy and monitor prediction market agents."
authors = ["Gnosis"]
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion tests_integration/markets/omen/test_omen.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def test_create_bet_withdraw_resolve_market(
# Submit the answer and verify it was successfully submitted.
logger.debug(f"Submitting the answer to {market.question.id=}.")

OmenRealitioContract().submitAnswer(
OmenRealitioContract().submit_answer(
api_keys=test_keys,
question_id=market.question.id,
answer=OMEN_FALSE_OUTCOME,
Expand Down

0 comments on commit 69ec60e

Please sign in to comment.