Skip to content

pm-v2-oo-reporter: add automatic re-request controls - #38

Merged
chrismaree merged 3 commits into
unaudited-pm-v2-oo-reporterfrom
chrismaree/oo-reporter-auto-rerequest
Jun 23, 2026
Merged

chrismaree merged 3 commits into
unaudited-pm-v2-oo-reporterfrom
chrismaree/oo-reporter-auto-rerequest

Conversation

@chrismaree

@chrismaree chrismaree commented Jun 23, 2026 •

Copy link
Copy Markdown
Member

What Changed

  • Added automatic replacement-request support to OOReporter.
  • Added a global owner-controlled automaticRerequestsEnabled switch, enabled by default at initialization.
  • Added per-request automaticDisputeRerequestUsed state so each registered request gets at most one automatic dispute re-request.
  • Changed manual rerequest(requestId, reward, proposalBond, liveness) to be owner-only and to spend the renamed manualRerequestsRemaining budget.
  • Allowed manual re-requests to update the active replacement request reward, proposal bond, and liveness.
  • Kept automatic re-requests on the active stored reward, proposal bond, and liveness.
  • Added RerequestType to RequestRerequested so indexers can distinguish Manual, AutomaticDispute, and AutomaticInvalidSettlement replacement requests.
  • Updated tests and README lifecycle docs for automatic dispute/P4 behavior, owner-only manual re-requests, dynamic manual settings, and manual budget semantics.

Why

  • The reporter should automatically create one replacement request on the first dispute without consuming manual budget.
  • Later disputes should require explicit owner/admin action through the manual re-request path.
  • DVM P4 settlements should independently create a replacement request when automation is enabled, regardless of whether the first-dispute automatic re-request was already used.
  • Operators need a simple global kill switch that falls back to the manual re-request gate.
  • Operators also need to adjust reward, bond, and liveness on later manual re-requests as market conditions change.

Impact

  • This is an ABI/event/storage-shape change for the unaudited PM v2 reporter branch.
  • Automatic re-requests reuse the active request reward, bond, liveness, identifier, and rules.
  • Manual re-requests can update reward, proposal bond, and liveness for the replacement request.
  • If a manual re-request updates bond or liveness, later automatic P4 replacement requests reuse those latest stored settings.
  • Automatic re-requests do not consume manual budget.
  • Manual re-requests are owner-only and consume manualRerequestsRemaining.
  • If automatic re-requests are disabled, disputes and P4 settlements open the manual gate using RequestRerequestAllowed.

High risk Sections to review with detail

  • pm-v2-oo-reporter/src/OOReporter.sol: callback paths now create replacement OO requests directly from priceDisputed and P4 priceSettled.
  • pm-v2-oo-reporter/src/OOReporter.sol: manual rerequest now validates and stores caller-supplied proposalBond and liveness before creating the replacement request.
  • pm-v2-oo-reporter/src/interfaces/IOOReporter.sol: ABI changes for RequestData, RequestRerequested, the automatic toggle, manual budget naming, and the expanded manual rerequest signature.
  • pm-v2-oo-reporter/test/OOReporter.t.sol: state-machine expectations for first dispute, later disputes, P4 automation, disabled automation, owner-only manual re-requests, and dynamic manual bond/liveness updates.
  • Automatic replacement requests use the active reward, bond, and liveness; callback transactions can revert if the reporter is not funded for a nonzero automatic replacement reward.

Validation

  • Ran git diff --check.
  • Did not run builds or tests per instruction.

@chrismaree

Copy link
Copy Markdown
Member Author

Security audit notes:

  1. Potential first-dispute semantic gap in priceDisputed: automaticDisputeRerequestUsed is only set when automation is enabled and the automatic re-request actually runs. If automation is disabled for the first dispute, the callback opens the manual gate but leaves automaticDisputeRerequestUsed == false; after a manual replacement and re-enabling automation, a later dispute can still auto re-request. That does not match the documented "first dispute auto, later disputes manual" model. If the intended behavior is first-dispute-only globally, mark the flag on the first active dispute regardless of whether automation is currently enabled, then either auto re-request or open the manual gate based on the toggle. Add a regression test for disabled first dispute -> manual re-request -> re-enable -> later dispute.

  2. Storage-layout caveat: RequestData now inserts automaticDisputeRerequestUsed before the address fields. Because this struct is stored in the requests mapping behind a UUPS implementation, that shifts the storage packing for all later fields in existing stored requests. This is acceptable only if no live OOReporter proxy state must be preserved. If this can upgrade an initialized/deployed reporter, the new bool needs to be appended in a storage-compatible location instead, or the upgrade needs an explicit migration plan.

Additional note: manual liveness validation looks correct. rerequest(..., liveness) calls _requireValidRequestLiveness, and automatic re-requests reuse stored liveness values that came from initialization or a prior validated manual re-request. I did not run tests or builds per repo instruction.


Sent from Chris Codex Agent 🤖

@chrismaree

Copy link
Copy Markdown
Member Author

Follow-up after discussing intended toggle semantics:

  • The intended model is that automaticRerequestsEnabled is evaluated when the future callback arrives, not frozen when the request was initialized or last re-requested.
  • Under that model, the current contract behavior is correct: a disabled first dispute opens the manual gate without consuming the future automatic-dispute slot; if automation is later re-enabled, a later eligible dispute can auto re-request. P4 settlement likewise follows the current setting when the DVM result comes back.
  • I pushed a7d367f with regression coverage for disabled-first-dispute -> manual re-request -> re-enabled later dispute, plus enabled request -> disabled before P4 settlement.
  • The storage-layout caveat from my earlier comment is not relevant here because there is no live OOReporter proxy state to preserve.

I did not run builds or tests per repo instruction; I did run git diff --check.


Sent from Chris Codex Agent 🤖

@chrismaree
chrismaree marked this pull request as ready for review June 23, 2026 16:18
@chrismaree
chrismaree merged commit bd5582b into unaudited-pm-v2-oo-reporter Jun 23, 2026
4 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a7d367fead

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +21 to +22
/// @notice Whether this request has used its one automatic dispute re-request.
bool automaticDisputeRerequestUsed;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve RequestData storage layout

When this implementation upgrades an existing proxy with registered requests, inserting automaticDisputeRerequestUsed here corrupts every stored RequestData: the old layout packed uint64 liveness + 4 bools + address requester into one full slot, so adding another bool pushes requester and all later fields into the next slots. Existing requests will then read the old oracleInitializer as requester, old priceIdentifier as oracleInitializer, etc., breaking authorization, callback lookup state, and resolution data. Add new per-request state without shifting the existing struct layout.

Useful? React with 👍 / 👎.

Comment on lines +510 to +511
uint256 previousRequestTimestamp =
_executeRerequest(request, request.reward, request.proposalBond, request.liveness, address(this));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid auto-rerequesting before deferred refunds are available

For a rewarded request whose OO dispute refund is deferred instead of transferred immediately, this automatic path reuses request.reward before the reporter has those tokens back. _requestPrice then reverts with InsufficientRewardBalance, which rolls back the first dispute callback rather than letting the deferred payout be claimed and the request proceed. This is a regression from the previous callback behavior, which only opened the gate and did not require the refund to have arrived during the dispute transaction.

Useful? React with 👍 / 👎.

Comment on lines +340 to +342
if (automaticRerequestsEnabled() && !request.automaticDisputeRerequestUsed) {
request.automaticDisputeRerequestUsed = true;
_executeAutomaticRerequest(requestId, request, RerequestType.AutomaticDispute);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fall back when same-block disputes cannot advance time

If a newly initialized or re-requested OO request is proposed and disputed in the same block, block.timestamp is still equal to the active requestTimestamp; this automatic dispute path calls _executeRerequest, which requires the replacement timestamp to be strictly greater and reverts. Because the revert happens inside priceDisputed, the whole OO dispute fails instead of opening the manual gate, even though the OO allows proposal/dispute before liveness expires.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant