Skip to content

Commit

Permalink
Added declare tests, simplify handler logic
Browse files Browse the repository at this point in the history
  • Loading branch information
OxideDall committed Jan 29, 2025
1 parent fddf57f commit 7fa0808
Show file tree
Hide file tree
Showing 7 changed files with 375 additions and 164 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,4 @@ This project is licensed under the MIT License. See [LICENSE](./LICENSE) for det

- [ ] Docker containerization
- [ ] Extend testing
- [ ] Add epoches management in case of close, declare
15 changes: 10 additions & 5 deletions contracts/MockInfraMarket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.20;

import "../contracts/IInfraMarket.sol";
import "forge-std/console.sol";

contract MockInfraMarket is IInfraMarket {
struct EpochDetails {
Expand Down Expand Up @@ -159,8 +160,6 @@ contract MockInfraMarket is IInfraMarket {
return (InfraMarketState.Sweeping, 0);
}

// [Additional helper functions and mock-specific overrides would follow]

function curOutcomeVestedArb(
address trading,
bytes8 outcome
Expand Down Expand Up @@ -313,22 +312,26 @@ contract MockInfraMarket is IInfraMarket {
return true;
}

// ... existing code ...

function call(
address tradingAddr,
bytes8 winner0,
address incentiveRecipient
) external override returns (uint256) {
console.log("call");
console.log("now", block.timestamp);
console.log("begins", campaign_call_begins[tradingAddr]);
console.log("ends", campaign_call_deadline[tradingAddr]);

require(enabled, "Not enabled");
require(campaign_call_deadline[tradingAddr] != 0, "Not registered");
require(
block.timestamp > campaign_call_begins[tradingAddr],
"Not inside calling period"
);

require(
block.timestamp < campaign_call_deadline[tradingAddr],
"Past calling deadline"
"Past deadline"
);
require(winner0 != 0, "Bad winner");

Expand Down Expand Up @@ -433,5 +436,7 @@ contract MockInfraMarket is IInfraMarket {
require(commit != 0, "Zero commit");

e.commitments[msg.sender] = commit;

emit Committed(tradingAddr, msg.sender, commit);
}
}
5 changes: 3 additions & 2 deletions service/const.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const INFRA_MARKET_BIRDTHBLOCK_TEST = 31563;
export const INFRA_MARKET_BIRDTHBLOCK_MAINNET = 98847;
export const INFRA_MARKET_BIRTHBLOCK_TESTNET = 31563;
export const INFRA_MARKET_BIRTHBLOCK_MAINNET = 98847;
export const SET_TIMEOUT_THRESHOLD = 2000;
export const POOLING_INTERVAL = 1000;
160 changes: 89 additions & 71 deletions service/infra-market-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { TxQueue } from "./tx-queue";
import { Logger } from "./logger";
import { sleep } from "./utils";
import { Config } from "../types/config";
import { SET_TIMEOUT_THRESHOLD } from "./const";
import { POOLING_INTERVAL, SET_TIMEOUT_THRESHOLD } from "./const";

export class InfraMarketHandler extends Logger {
#activeMarkets: ActiveMarkets = {};
Expand All @@ -38,7 +38,7 @@ export class InfraMarketHandler extends Logger {
}

public init = async () => {
this.#initEventLUT();
await this.#initEventLUT();
await this.#filterMarkets();
};

Expand Down Expand Up @@ -79,10 +79,6 @@ export class InfraMarketHandler extends Logger {

const { state, remaining } = status;

if (state !== InfraMarketState.Closed) {
this.#activeMarkets[market.args.tradingAddr] ??= { outcomes: [] };
}

switch (state) {
case InfraMarketState.Callable:
if (remaining === 0) {
Expand All @@ -96,17 +92,21 @@ export class InfraMarketHandler extends Logger {
this.#scheduleClose(market.args.tradingAddr);
break;

case InfraMarketState.Declarable:
this.#ifDeclare(market.args.tradingAddr);
break;

case InfraMarketState.Closable:
// TODO: closable and close are the same, check that campaign not closed here
// TODO: closable and close are the same, check that campaign not closed based on epoches management
this.#close(market.args.tradingAddr);
break;

case InfraMarketState.Revealing:
this.#scheduleDeclare(market.args.tradingAddr);
break;

case InfraMarketState.Declarable:
await this.#declare(market.args.tradingAddr);
break;

case InfraMarketState.Sweeping:
this.#ifSweep(market.args.tradingAddr);
this.#sweep(market.args.tradingAddr);
break;
}
}
Expand All @@ -118,35 +118,33 @@ export class InfraMarketHandler extends Logger {
this.#activeEventLUT[topics] = handler;
}

this.wssProvider.on({ address: this.infraMarket.target }, (log: Log) => {
if (this.#activeEventLUT[log.topics[0]]) {
return this.#activeEventLUT[log.topics[0]]!(log);
await this.wssProvider.on(
{ address: this.infraMarket.target },
(log: Log) => {
if (this.#activeEventLUT[log.topics[0]]) {
return this.#activeEventLUT[log.topics[0]]!(log);
}
}
});
);
};

parseLog = (log: Log) =>
this.infraMarket.interface.parseLog(
log
)! as TypedLogDescription<TypedContractEvent>;

#onCreate = (log: Log) => {
#onCreate = async (log: Log) => {
const createdEvt: MarketCreated2Event.LogDescription = this.parseLog(log);
this.#activeMarkets[createdEvt.args.tradingAddr] = { outcomes: [] };

const status = await this.#marketStatus(createdEvt.args.tradingAddr);

if (status) {
this.#scheduleEscape(createdEvt.args.tradingAddr, status.remaining);
}
};

#onCall = (log: Log) => {
const callEvt: CallMadeEvent.LogDescription = this.parseLog(log);
if (!this.#activeMarkets[callEvt.args.tradingAddr]) {
this.#activeMarkets[callEvt.args.tradingAddr] = {
outcomes: [callEvt.args.winner],
};
} else {
this.#activeMarkets[callEvt.args.tradingAddr].outcomes.push(
callEvt.args.winner
);
}
clearTimeout(this.#activeMarkets[callEvt.args.tradingAddr]?.escapeTimer);

this.#scheduleClose(callEvt.args.tradingAddr);
};
Expand All @@ -160,66 +158,46 @@ export class InfraMarketHandler extends Logger {
const revealEvt: CommitmentRevealedEvent.LogDescription =
this.parseLog(log);

const tradingAddr = revealEvt.args.trading;
const committerAddr = revealEvt.args.revealer;
const revealedOutcome = revealEvt.args.outcome;

if (!this.#activeMarkets[tradingAddr]) {
this.#activeMarkets[tradingAddr] = { outcomes: [] };
}
this.#activeMarkets[tradingAddr].outcomes.push(revealedOutcome);

if (!this.#activeMarkets[tradingAddr].reveals) {
this.#activeMarkets[tradingAddr].reveals = {};
}
this.#activeMarkets[tradingAddr].reveals![committerAddr] = revealedOutcome;

this.#ifDeclare(tradingAddr);
this.#scheduleDeclare(revealEvt.args.trading);
};

#ifDeclare = async (tradingAddr: string) => {
if (this.#activeMarkets[tradingAddr].declared) return;
#declare = async (tradingAddr: string) => {
const outcomes = await this.infraMarket
.queryFilter(this.infraMarket.filters.CommitmentRevealed(tradingAddr))
.then((logs) => logs.map((l) => l.args.outcome));

const s = await this.#marketStatus(tradingAddr);

if (s?.state === InfraMarketState.Declarable) {
this.#declare(tradingAddr);
}

await this.#ifSweep(tradingAddr);
};

#declare = (tradingAddr: string) => {
const outcomes = this.#activeMarkets[tradingAddr].outcomes;
this.txQueue.push(
this.infraMarket.declare,
tradingAddr,
outcomes,
this.txQueue.actor.address
);
this.#activeMarkets[tradingAddr].declared = true;

this.#scheduleSweep(tradingAddr);
};

#close = (tradingAddr: string) =>
#close = (tradingAddr: string) => {
this.txQueue.push(
this.infraMarket.close,
tradingAddr,
this.txQueue.actor.address
);
};

#sweep = async (tradingAddr: string) => {
const declaredWinner = await this.infraMarket.winner(tradingAddr);

const reveals = this.#activeMarkets[tradingAddr].reveals || {};
const victims = Object.keys(reveals).filter(
(committerAddr) => reveals[committerAddr] !== declaredWinner
const reveals = await this.infraMarket
.queryFilter(this.infraMarket.filters.CommitmentRevealed(tradingAddr))
.then((logs) => logs.map((l) => l.args));

const victims = reveals.filter(
(reveal) => reveal.outcome !== declaredWinner
);

const epochNo = await this.infraMarket.epochNumber(tradingAddr);

const victimsAddresses = victims.map(
(committerAddr) => reveals[committerAddr]
);
const victimsAddresses = victims.map((victim) => victim.revealer);

this.txQueue.push(
this.batchSweeper.sweepBatch,
Expand All @@ -235,7 +213,44 @@ export class InfraMarketHandler extends Logger {
this.txQueue.push(this.infraMarket.escape, tradingAddr);
};

#scheduleSweep = async (tradingAddr: string) => {
while (true) {
const s = await this.#marketStatus(tradingAddr);

if (s?.state === InfraMarketState.Sweeping) {
await this.#sweep(tradingAddr);
break;
}

await sleep(POOLING_INTERVAL);
}
};

#scheduleDeclare = async (tradingAddr: string) => {
if (!this.#activeMarkets[tradingAddr]) {
this.#activeMarkets[tradingAddr] = {};
}

clearTimeout(this.#activeMarkets[tradingAddr]?.closeTimer);

const s = await this.#marketStatus(tradingAddr);

if (s?.state === InfraMarketState.Revealing) {
clearTimeout(this.#activeMarkets[tradingAddr]?.declareTimer);
this.#activeMarkets[tradingAddr].declareTimer = setTimeout(
() => this.#declare(tradingAddr),
s.remaining * 1000 + SET_TIMEOUT_THRESHOLD
);
}
};

#scheduleClose = async (tradingAddr: string) => {
if (!this.#activeMarkets[tradingAddr]) {
this.#activeMarkets[tradingAddr] = {};
}

clearTimeout(this.#activeMarkets[tradingAddr]?.escapeTimer);

const s = await this.#marketStatus(tradingAddr);

if (s?.state === InfraMarketState.Whinging) {
Expand All @@ -250,14 +265,11 @@ export class InfraMarketHandler extends Logger {
}
};

#ifSweep = async (tradingAddr: string) => {
const s = await this.#marketStatus(tradingAddr);
if (s?.state === InfraMarketState.Sweeping) {
await this.#sweep(tradingAddr);
#scheduleEscape = (tradingAddr: string, remaining: number) => {
if (!this.#activeMarkets[tradingAddr]) {
this.#activeMarkets[tradingAddr] = {};
}
};

#scheduleEscape = (tradingAddr: string, remaining: number) => {
clearTimeout(this.#activeMarkets[tradingAddr]?.escapeTimer);
this.#activeMarkets[tradingAddr].escapeTimer = setTimeout(
() => this.#escape(tradingAddr),
Expand All @@ -273,5 +285,11 @@ export class InfraMarketHandler extends Logger {
[this.infraMarket.filters.CommitmentRevealed(), this.#onReveal],
];

destroy = () => this.wssProvider.destroy();
destroy = () => {
this.wssProvider.destroy();
for (const market of Object.keys(this.#activeMarkets)) {
clearTimeout(this.#activeMarkets[market]?.escapeTimer);
clearTimeout(this.#activeMarkets[market]?.closeTimer);
}
};
}
Loading

0 comments on commit 7fa0808

Please sign in to comment.