Skip to content
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

feat: OptimismPortal wd invalidation mitigation #77

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

smartcontracts
Copy link
Contributor

Introduces a proposal that would prevent user withdrawals in the OptimismPortal from being invalidated any time that the fallback is utilized.

Introduces a proposal that would prevent user withdrawals in the
OptimismPortal from being invalidated any time that the fallback
is utilized.
Copy link
Contributor

@ajsutton ajsutton left a comment

Choose a reason for hiding this comment

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

I'm in favour of this change. The validity checks are still really simple and it gives the guardian significantly more flexibility. The concern about user impact affects the guardian decision making process even if the actual impact winds up being small so providing better tools to simplify the decision making process seems well worth it to me.

protocol/proofs/withdrawal-invalidation-mitigation.md Outdated Show resolved Hide resolved

We propose removing the requirement that withdrawals must be finalized against a dispute game of
the `respectedGameType`. Withdrawals that have been previously proven against a dispute game when
that game *was* respected can be finalized even if that dispute game is no longer of the respected

Choose a reason for hiding this comment

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

Looking at the impl, although checkWithdrawal no longer asserts against respectedGameType, we continue to assert against it in proveWithdrawalTransaction, implying the withdrawal GameType was once the respected one. If a GameType needs to be invalidated, the respectedGameType is changed and respectedGameTypeUpdatedAt is updated. This means another DisputeGame must be created, of the new respectedGameType and not the invalid GameType. 👍

the new system given that the variable would not be updating every time that the
`respectedGameType` variable is changed. Alternatively, we could keep `respectedGameTypeUpdatedAt`
untouched and instead introduce a new variable that more accurately reflects the system. This would
also avoid a breaking change to the contract ABI and the semantics of the original variable.

Choose a reason for hiding this comment

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

this variable could be decoupled from respectedGameType. Instead it could be called something like gameCreationValidFrom, and then the check would be like

require(
    createdAt >= gameCreationValidFrom,
    "OptimismPortal: dispute game created before latest creation validity timestamp"
);

what do you think?

the occurrences of respectedGameTypeUpdatedAt in the monorepo are low. sorry for the noob question but are there many concerns outside of the monorepo? perhaps integrators would be happy for the breaking change here as their withdrawal validity logic should be updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Realistically I think you're correct here -- it's possible we could even keep the semantic meaning of respectedGameTypeUpdatedAt (as in, we do continue to update it when setRespectedGameType is called) but add this new variable gameCreationValidFrom with these new semantics.

Copy link
Member

@clabby clabby left a comment

Choose a reason for hiding this comment

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

This looks good to me. Simple enough to change up. Also will include some changes to the deputy guardian.

@smartcontracts
Copy link
Contributor Author

Reminder to self: do not allow invalidation timestamp to be greater than current timestamp

Comment on lines +47 to +56
We propose removing the requirement that withdrawals must be finalized against a dispute game of
the `respectedGameType`. Withdrawals that have been previously proven against a dispute game when
that game *was* respected can be finalized even if that dispute game is no longer of the respected
game type.

We additionally propose that the `respectedGameTypeUpdatedAt` timestamp not be updated by default.
Instead, the timestamp can be selectively updated if withdrawal invalidation is actually required.
Combined with the first proposed change, this proposal means that older withdrawal proofs can
usually be finalized when the respected game type is changed but withdrawals can still be blanket
invalidated if necessary.
Copy link

@Ethnical Ethnical Sep 20, 2024

Choose a reason for hiding this comment

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

An issue can possibly arise if the second case for the withdrawal invalidation without checking the respectGameType like in the past.

For example, this might be a possible attack vector:

  1. The guardian make a tx to set the respectedGameType to 1 (permissioned game).
  2. The attacker monitors the mempool and frontruns in the same block the call to setRespectGame(1).
  3. In the same block, the attacker create a game using create() on the DisputeGameFactory contract. As, the createAt is a timestamp from the value block.timestamp, this will have the exact same value if we are before or after into the same block.
  4. The attacker call proveWithdrawalTransaction() and then wait for the PROOF_MATURITY_DELAY_SECONDS submit the finalizeWithdrawalTransaction().
  5. As the check (below in solidity) is using greater and equal than createdAt >= respectedGameTypeUpdatedAt the attacker might be able to finalize a transaction with the incorrect gameType.
  6. The impact seems to be really low, but this would make an inconsistent state (as the optimismPortal and the Guardian that restricted the to certain gameType) the Guardian will think that only the certain gameType would be valid, for the next withdrawal and would invalid the other gameType but here the other gameType would be finalized with success at the block.timestamp would be the same).
if (disputeGameProxy.gameType().raw() != respectedGameType.raw()) //@audit: The current design review propose to not use this anymore?
    revert InvalidGameType();

require(
    createdAt >= respectedGameTypeUpdatedAt, //@audit: Usage of the >= instead of > is a potential issue here?
    "OptimismPortal: dispute game created before respected game type was updated"
);

This scenario might be invalid as maybe this is desired from the new design (still strange imo)?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah would be worth making that a strict >. While that will mean that any withdrawals proven against the new game type after the change but in the same block are invalidated when they probably shouldn't be, that's a very unlikely corner case and much lower impact than having a withdrawal be unexpectedly valid.

Copy link

@Ethnical Ethnical left a comment

Choose a reason for hiding this comment

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

Agreed, and let a comment but the rest looks a nice initiative to me!

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.

5 participants