fix: detect managed oov2 in monitors#4940
Conversation
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 501f329620
ℹ️ 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".
| if (this.currentImplementationPromise === null) { | ||
| this.currentImplementationPromise = this.web3.eth.getStorageAt( | ||
| this.optimisticOracleContract.options.address, | ||
| EIP1967_IMPLEMENTATION_SLOT | ||
| ); |
There was a problem hiding this comment.
Reset cached implementation after storage-read failure
_getCurrentImplementation caches the raw promise from getStorageAt, so a transient RPC error on the first call stores a rejected promise permanently. After that, every _isManagedOOV2() call reuses the same rejection and always falls back to Optimistic+Oracle+V2, so managed OOv2 links stay incorrect for the lifetime of the monitor process even if the node recovers. Clearing/retrying the cache on rejection would avoid this sticky failure mode.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in a759001dd.
_getCurrentImplementation() now clears currentImplementationPromise on rejection before rethrowing, so a transient getStorageAt failure no longer poisons managed OOv2 detection for the lifetime of the monitor process.
Added a regression test that exercises the fail-then-succeed path:
- first
_generateUILink()call falls back toOptimistic+Oracle+V2 - second
_generateUILink()call retries the storage read and returnsManaged+Optimistic+Oracle+V2 - storage-read call count is
2
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
| } | ||
|
|
||
| _getCurrentImplementation() { | ||
| if (this.currentImplementationPromise === null) { |
There was a problem hiding this comment.
Small concern: currentImplementationPromise stays cached after the first successful read, so a long-running monitor may miss a later proxy upgrade. Simplest fix may be to skip permanent caching here, or refresh it per poll or with a short TTL.
There was a problem hiding this comment.
Addressed in 6e7deb2f2.
I kept the managed-vs-regular OOv2 detection cached, but split upgrade detection off that cache.
_isManagedOOV2() still uses the cached/retryable current-slot read because that is just acting as a type discriminator for the monitored OOv2 address. _detectManagedOOV2Upgraded() now reads the current implementation fresh on each proposal poll and compares it against a cached pre-upgrade implementation read at managedOOV2PreUpgradeBlock.
That keeps the Cloud Run case cheap, but also lets a long-running monitor observe a later proxy upgrade without restart.
Added regression coverage for the long-running path as well: two successive upgrade checks now re-read the current slot, reuse the cached pre-upgrade slot, and flip from false to true when the mocked current implementation changes.
| break; | ||
| case OptimisticOracleType.OptimisticOracleV2: | ||
| oracleType = "Optimistic+Oracle+V2"; | ||
| oracleType = (await this._isManagedOOV2()) ? "Managed+Optimistic+Oracle+V2" : "Optimistic+Oracle+V2"; |
There was a problem hiding this comment.
Nice addition. One thing to watch: this reads the current proxy implementation when choosing the OOv2 UI type, so historical events can flip to the managed route after an upgrade or backfill. Could we resolve the implementation at the event block here instead?
There was a problem hiding this comment.
I don’t think event-block resolution is the right behavior here.
This check is not trying to reconstruct the historical implementation for a given event. It’s only being used to distinguish ManagedOptimisticOracleV2 from regular OptimisticOracleV2, since both share the same oracleType in the monitor config and ABI. The UUPS implementation slot is acting as a type discriminator for the ManagedOptimisticOracleV2 (as it is upgradeable), not as historical event-state lookup.
Signed-off-by: Reinis Martinsons <reinis@umaproject.org>
Motivation
Managed Optimistic Oracle V2 requests currently generate the standard OOv2 Oracle UI link in monitor alerts. That points reviewers to the wrong UI variant.
This PR fixes the link generation inside the monitor so managed OOv2 requests resolve to
oracleType=Managed+Optimistic+Oracle+V2.Summary
This PR updates
OptimisticOracleContractMonitorto detect managed OOv2 contracts by reading the current EIP-1967 implementation slot.If the configured oracle type is
OptimisticOracleV2and the contract is a UUPS proxy,_generateUILinknow emits the managed UI link. The upgraded-managed dispute-window detection keeps its existing semantics, but now uses a fresh current-slot read on each proposal poll so long-running monitor processes can observe a later proxy upgrade without restart.Details
_generateUILinkis now async and all monitor alert paths await it before logging request, proposal, dispute, and settlement messages.Managed OOv2 UI-link detection is local to
packages/monitors/src/OptimisticOracleContractMonitor.js. It treats an OOv2 contract as managed when the current EIP-1967 implementation slot is non-empty.For managed detection, the current-slot read is still cached per monitor instance, and rejected reads clear the cache before rethrowing. That preserves single-flight behavior on success while allowing managed detection to retry after transient RPC/storage failures instead of getting stuck on a permanently rejected promise.
_detectManagedOOV2Upgradedstill requiresmanagedOOV2PreUpgradeBlockand compares the current implementation to the pre-upgrade implementation. To support long-running processes, it now reads the current implementation fresh on each proposal poll, while caching the historical pre-upgrade-slot read.Testing
Added coverage for:
Executed:
Observed result:
23 passing (1m)for the monitor suiteIssue(s)
Fixes: https://linear.app/uma/issue/FE-520/moov2-proposal-links-in-oo-live-feed-use-incorrect-oracletype