-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
improve(SpokePool): _depositV3 interprets exclusivityParameter
as an offset, or a timestamp
#670
Conversation
Signed-off-by: Matt Rice <[email protected]>
Signed-off-by: Matt Rice <[email protected]>
Signed-off-by: Matt Rice <[email protected]>
The new relative exclusivity check has not been propagated to fillV3RelayWithUpdatedDeposit(). Identified via test case failures in the relayer. Signed-off-by: Paul <[email protected]>
…, an offset, or a timestamp There should be a way for the deposit transaction to remove chain re-org risk affecting the block.timestamp by allowing the caller to set a fixed `exclusivityDeadline` value. This supports the existing behavior where the `exclusivityDeadline` is always emitted as its passed in. The new behavior is that if the `exclusivityParameter`, which replaces the `exclusivityDeadlineOffset` parameter, is 0 or greater than 1 year in seconds, then the `exclusivityDeadline` is equal to this parameter. Otherwise, its interpreted by `_depositV3()` as an offset. The offset would be useful in cases where the origin chain will not re-org, for example.
// One year in seconds. If `exclusivityParameter` is set to a value less than this, then the emitted | ||
// exclusivityDeadline in a deposit event will be set to the current time plus this value. | ||
uint32 public constant MAX_EXCLUSIVITY_PERIOD_SECONDS = 31_536_000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we instead infer the upper limit for a relative exclusivity period based on the fillDeadlineBuffer? It otherwise doesn't make sense to permit relative exclusivity > fillDeadlineBuffer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with this since no relayer can make a fill on an expired deposit regardless of exclusivity.
On the other hand - having a defined upper limit for whether the exclusivityParameter
is an offset or timestamp is convenient.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that seems like it would add complexity where we don't need it. If the caller sets the exclusivity period larger than fill deadline, then the full period is exclusive. Is this a bug? Not really IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's OK to permit a larger relative exclusivityDeadline, I just don't know of any use cases for a fixed exclusivityDeadline - that's generally unreliable due to the unknown transaction submission & confirmation delay, and the logic to derive whether it's 0, relative or fixed is relatively more complicated as a result (also RE #670 (comment)).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think there are ways to build an exclusive quoting API with fixed timestamps:
- API gives depositors fixed timestamps to set. Let's say this is some time 15 seconds from now.
- Depositors form deposit and then sign over message and hand off to filler to submit on origin chain
- API rewards the designated exclusive filler if they fill on the destination chain within 5 seconds of the deposit time
- API penalizes fillers who do not fill in time unless the deposit took too long to be mined on chain. In this example let's say the deposit gets 10 seconds to be brought on chain. This means the filler gets 5 seconds of exclusivity in their worst case.
- Therefore the API needs to parameterize:
- A buffer period for the deposit to be mined, in this example it is 10 seconds,
depositBufferPeriod
. The filler gets this amount of protection against deposits taking longer to mine. - A target fill time, in this example it is 5 seconds,
longestFillPeriod
. The filler must fill within this time of the deposit being mined.
- A buffer period for the deposit to be mined, in this example it is 10 seconds,
- And the API must keep track of:
- The time
quoteTime
that the quote was given - The time
depositTime
that the deposit was mined - The time
fillTime
that the fill was mined
- The time
- And the API will reward fillers who:
- Have a fill response time of
fillTime - depositTime <= longestFillPeriod
if thedepositTime - quoteTime <= depositBufferPeriod
- Have a fill response time of
IMO this use case is the only realistic way to support exclusivity without exposing fillers to block.timestamp-related re-org risk and without changing the V3RelayData
struct.
Another way to build the API is to offer relative offset exclusivity if the origin chain has very little re org risk. This protects fillers a bit more from late deposits. For these chains, the API would no longer need to keep track of quoteTime
or depositBufferPeriod
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nicholaspai Have we ruled out pulling exclusivityDeadline
out of the relayData
definition?
If we did this then there's no marginal re-org risk as a result of this feature. It does permit someone else to make a fill for a relay that they didn't have exclusivity for, but the user is still OK in that context, and we can easily post-process to filter those out when evaluating relayer performance.
I guess one issue is that well- behaved relayers can still get rekt by bad actors who deliberately intend to disrupt :\
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think removing exclusivity deadline from the relay hash is off the table since it means anyone can "steal" exclusivity and it prevents the depositor from offering exclusivity. If we were open to changing the relay hash then I would instead propose adding an initiateDeadline parameter that ensures that deposits don't delay getting mined.
However changing the relay hash would be highly disruptive so I strongly want to avoid.
// 3. Otherwise, interpret this parameter as a timestamp and emit it as the exclusivity deadline. This means | ||
// that the filler of this deposit will not assume re-org risk related to the block.timestamp of this | ||
// event changing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have a concrete use case for this? It only seems useful for relatively long-duration (i.e. fillDeadlineBuffer > exclusivity > ~300 seconds). But that in itself seems quite bespoke since it can still be achieved with relative duration.
tldr, as the exclusivity period increases in duration, origin chain reorg risk fades to 0, so the relative timestamp actually seems like a better fit there anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO there isn't a strong reason to use a fixed timestamp over a large exclusivity offset but there are probably some cases where you want to fill pretty quickly (i.e. take on some re-org risk) and also have exclusivity over the full deposit. Why not support it since it's easy to write the code for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It only seems useful for relatively long-duration
I don't think this is necessarily true. You could imagine employing "optimistic" exclusivity where you give 15-30 seconds seconds of exclusivity and if someone takes too long to send their transaction, they just lose exclusivity.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also want to backtrack this statement a bit as I think fixed timestamps can be useful when building an exclusive quoting API as I describe here
IMO there isn't a strong reason to use a fixed timestamp over a large exclusivity offset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessarily true. You could imagine employing "optimistic" exclusivity where you give 15-30 seconds seconds of exclusivity and if someone takes too long to send their transaction, they just lose exclusivity.
I'm probably missing something, but I'm struggling to see how this is useful vs. an offset for short-duration exclusivity. Considering the three chains where we currently see reorgs (mainnet, Scroll, Polygon):
For mainnet, in my view 15 - 30 seconds in an absolute timestamp isn't enough because confirmation time is probably 6 - 12 seconds, and any relayer probably wants more than 1 deposit confirmation on top before filling. In that case I think a relative offset of 30 seconds is probably OK, since the relayer has 2 confirmation blocks, after which they can be reasonably confident that they won't see a subsequent re-org (based on historical re-org depths, at least).
For Scroll, where we are now seeing reorgs at ~2 blocks, a relative offset of 15 seconds is probably fine and you don't need to revert to a fixed timestamp.
I'm not sure how I see it on Polygon...their re-orgs are still fairly frequent and I see 2 at 13 & 14 blocks respectively in the last week, which amounts to ~30 seconds, and they can run much more deeply (20 - 30 blocks). So I'm unsure whether we'd be looking to apply a 30 second exclusivity there anyway.
The example of 30 seconds might just be an off-the-cuff suggestion so maybe there are other examples that fit better. But I think my gut feel could be summarised as:
Fixed timestamps are mostly useful over the short term to minimise invalid fills in cases where a re-org occurs without deposit reordering, assuming the initial deposit submission & confirmation delay is very short. In order to account for those delays, we may need to pad exclusivity to a duration where the origin chain re-org risk can instead be managed by the relayer by waiting for their standard finality constraints to elapse, and then filling before the residual exclusivity expires. This is the relayer's responsibility, and I think the relayers that have been burned by origin chain re-orgs have actually been discarding their finality constraints in order to prioritise filling ASAP, which IMO is long-term unsustainable because they will get burned by other re-org issues (deposit renumbering or inputAmount changes due to pre-deposit swaps).
Another challenge with offering fixed timestamps is that it will play poorly with suggested-fees caching. We currently cache the fees for 10s, so a depositor might actually be approving a quote that's already 10 seconds old. We can drop this of course (and we may not see any performance impact from that, tbf), but we may alternatively need to look at other mitigations if not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand your suggestion here. So I'll propose how I think we can use fixed timestamps to support exclusivity on deposits from origin chains that re-org:
- Let's say for mainnet we want to give the relayer 30 seconds to fill following the deposit mining time. Let's assume confirmation time is worst case 24 seconds. The quoting API should therefore suggest that depositors set their exclusiveDeadline to 60 seconds from now. The quoting API should reward fillers for fills on deposits where the deposit was mined within 24+6=30 seconds of teh quote and when the fill was sent within the exclusivity period.
What's wrong with this strawman implementation? Fillers are incentivized via off-chain mechanisms to fill quickly, and are not penalized if the depositor takes too long to mine
Another challenge with offering fixed timestamps is that it will play poorly with suggested-fees caching. We currently cache the fees for 10s, so a depositor might actually be approving a quote that's already 10 seconds old. We can drop this of course (and we may not see any performance impact from that, tbf), but we may alternatively need to look at other mitigations if not.
This is a good critique. We may have to turn off caching for quotes on origin chains that can-reorg or turn the caching time down from 10 seconds to 2 seconds, for example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Let's say for mainnet we want to give the relayer 30 seconds to fill following the deposit mining time. Let's assume confirmation time is worst case 24 seconds. The quoting API should therefore suggest that depositors set their exclusiveDeadline to 60 seconds from now. The quoting API should reward fillers for fills on deposits where the deposit was mined within 24+6=30 seconds of teh quote and when the fill was sent within the exclusivity period.
What's wrong with this strawman implementation? Fillers are incentivized via off-chain mechanisms to fill quickly, and are not penalized if the depositor takes too long to mine
If exclusivityDeadline is set to quote time + 60 seconds as an absolute timestamp and the relayer doesn't turn up then there's an somewhat-nasty delay that the depositor suffers. Alternatively, I think you can actually get something close to 30 seconds with a relative timestamp because this implies 2 deposit confirmations + x blocks to fill on an L2 (2 - 3 blocks on OP stack chains, more on Arbitrum, 1 - 2 blocks on Linea or Scroll).
So my thinking is that the utility of an absolute exclusivityDeadline is greatest when it is closer to the quote time, but this means that the uncertain time for deposit submission + confirmation "eats" most of it and reduces its utility.
To me, the fact that relayers were impacted by this whilst skipping their usual finality constraints seems significant. The fact that relative timestamps also broke deterministic deposit IDs was also significant, though that is addressed by permitting the depositor to specify exclusivityDeadline 0 and have that passed through to the resulting event.
(also to clarify, this might technically be a redundant point to debate because there's no obligation to use absolute timestamps. The deposit originator can choose whichever. The only impact of supporting them is a minor gas increase implied by having to check for them)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation is OK for me, though with two comments to consider.
Co-authored-by: Paul <[email protected]>
Summary
There should be a way for the deposit transaction to remove chain re-org risk affecting the block.timestamp by allowing the caller to set a fixed
exclusivityDeadline
value. This supports the existing behavior where theexclusivityDeadline
is always emitted as its passed in.The new behavior is that if the
exclusivityParameter
, which replaces theexclusivityDeadlineOffset
parameter, is 0 or greater than 1 year in seconds, then theexclusivityDeadline
is equal to this parameter. Otherwise, its interpreted by_depositV3()
as an offset. The offset would be useful in cases where the origin chain will not re-org, for example.Details
Unintended introduction of re-org risk when specifying exclusivity as an offset
We discovered that there is an issue with specifying the exclusivity deadline parameter in
depositV3
as an offset instead of a fixed timestamp, which was a change originally proposed here.The motivation for specifying exclusivity as an offset was to improve UX, so that depositors could say that they wanted to give fillers exclusivity for some period following the time that their deposit transaction is mined, which makes sense since deposit mining times are variable and out of the depositor’s control. We implemented this by emitting the
exclusivityDeadlineTimestamp
in theV3FundsDeposited
event as the offset plus the mined block’s block.timestamp.However, this inherently makes all such
V3FundsDeposited
events fragile because the block.timestamp can change if the deposit gets re-orged. This means all deposits where the caller specifies the exclusivity as an offset instead of a fixed timestamp are inherently not re-org resistant.Negating benefits of deterministic relay hash
Separately, we wanted to add a method to allow depositors to create re-org resistant deposits which we implemented here. All deposits have re-org risk today because the
depositId
can always be changed in a re-org because its dependent on contract state outside of the depositor’s control. In the linked PR, we added a method unsafeDepositV3 where the depositor could specify an exact depositId, which could be used to give relayers a chance to know ahead of time the deposit’s full relay hash without concern for reorg risk. However, if unsafeDepositV3 forces depositors to specify exclusivity as an offset, then we unintentionally re-introduced re-org risk.This PR is our attempt at fixing the issue by allowing all depositors to either specify a fixed exclusivity timestamp or an offset, which means it is up to depositors to choose how much re-org risk they want to embed in their deposits. We envision certain use cases choosing to use fixed timestamps, while others choose offsets. We imagine that deposits on certain origin chains that don’t re-org (e.g. Arbitrum, ZkSync) can continue to use offsets while those with high re-org risk (e.g. Ethereum, Polygon) opt to use a fixed timestamp.