Skip to content

Conversation

@nicholaspai
Copy link
Member

@nicholaspai nicholaspai commented Mar 9, 2022

Issue:

  • [C01] Slow relays on multiple chains
    • In each root bundle, the slowRelayRoot represents all the slow relays in a batch, which could involve
      multiple tokens and spoke pools. A valid root bundle would ensure the poolRebalanceRoot has a leaf
      for every spoke chain. When this rebalance leaf is processed, the slowRelayRoot will also be sent to
      the corresponding spoke pool.
    • Notably, every spoke pool receives the same slowRelayRoot, which represents all slow relays in the
      batch across the whole system. When the slow relay is executed, the Spoke Pool does not filter on the
      destination chain id, which means that any slow relay can be executed on any spoke chain where the
      Spoke Pool has sufficient funds in the destinationToken. Consider including the destination chain ID in
      the slow relay details so the Spoke Pool can filter out relays that are intended for other chains.
  • [M01] Inconsistent signature checking
    • Depositors can update the relay fee associated with their transfer by signing a message describing this
      intention. The message is verified on the origin chain before emitting the event that notifies relayers,
      and verified again on the destination chain before the new fee can be used to fill the relay. If the
      depositor used a static ECDSA signature and both chains support the ecrecover opcode, both
      verifications should be identical. However, verification uses the OpenZeppelin Signature Checker
      library, which also supports EIP-1271 validation for smart contracts. If the smart contract validation
      behaves differently on the two chains, valid contract signatures may be rejected on the destination
      chain. A plausible example would be a multisignature wallet on the source chain that is not replicated
      on the destination chain.
    • Instead of validating the signature on the destination chain, consider including the
      RequestedSpeedUpDeposit event in the off-chain UMIP specification, so that relayers that comply with
      the event would be reimbursed. This mitigation would need a mechanism to handle relayers that
      incorrectly fill relays with excessively large relayer fees, which would prevent the recipient from
      receiving their full payment. Alternatively, consider removing support for EIP-1271 validation and
      relying entirely on ECDSA signatures.

Resolution:

  • By removing EIP191 support, we remove an attack vector whereby someone can forge a "speed up request" signature on the destination chain by deploying a custom contract. We also remove the possibility that a signature is not recoverable on the destination chain because the contract that signed the message and submitted it on the origin chain cannot be replicated on the destination side.
  • Adding destinationChainId to the Relay Data is important so that slow relays can be associated deterministically to relays on a specific chain. Imagine a scenario where a slow relay to fill a relay on chain 100 is added to the slowRelayRoot. This slow relay is valid so the root bundle including the slowRelayRoot on the HubPool successfully passes liveness. Now, anyone can submit that slow relay leaf to a chain 200 to take funds out of a SpokePool

uint256 fillAmount,
uint256 repaymentChainId,
uint256 originChainId,
uint256 destinationChainId,
Copy link
Member

Choose a reason for hiding this comment

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

if you do this then please also add the originChainId to FundsDeposited

Copy link
Member Author

Choose a reason for hiding this comment

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

done

import { toBNWei, SignerWithAddress, Contract, ethers, seedWallet, toBN } from "../utils";
import { constructRelayParams, warmSpokePool, sendRelay } from "./utils";
import * as constants from "../constants";
import { spokePoolFixture, enableRoutes } from "../fixtures/SpokePool.Fixture";
Copy link
Member

Choose a reason for hiding this comment

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

🍉

Copy link
Member

@chrismaree chrismaree left a comment

Choose a reason for hiding this comment

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

LGTM! makes sence as a change

Copy link
Contributor

@mrice32 mrice32 left a comment

Choose a reason for hiding this comment

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

Looks great! Two minor comments

// This function is isolated and made virtual to allow different L2's to implement chain specific recovery of
// signers from signatures because some L2s might not support ecrecover, such as those with account abstraction
// like ZKSync.
// like ZKSync. To be safe, consider always reverting this function for L2s where ecrecover is different from how
Copy link
Contributor

Choose a reason for hiding this comment

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

Does ZKSync not support standard ecrecover?

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess they do now, but its a special case so we need to be careful when integrating with zksync: https://v2-docs.zksync.io/dev/testnet/status.html#currently-supported-features

address destinationToken,
uint256 amount,
uint256 originChainId,
uint256 destinationChainId,
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we should omit this to save calldata and assume that the current chainId is the one they intended? Thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yup done

@nicholaspai nicholaspai marked this pull request as ready for review March 10, 2022 12:56
@nicholaspai nicholaspai merged commit 6e69fdc into master Mar 11, 2022
@nicholaspai nicholaspai deleted the npai/fix-oz branch March 11, 2022 15:33
@nicholaspai nicholaspai added the OZ Audit - March Resolves issue discovered in March 2022 OZ Audit label Mar 15, 2022
@nicholaspai nicholaspai changed the title fix: Remove EIP-191 signature recovery support and add destination chain ID to relay data fix: [C01, M01] Remove EIP-191 signature recovery support and add destination chain ID to relay data Mar 15, 2022
@nicholaspai nicholaspai changed the title fix: [C01, M01] Remove EIP-191 signature recovery support and add destination chain ID to relay data fix: [C01, M01] Remove EIP-1271 signature recovery support and add destination chain ID to relay data Apr 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

OZ Audit - March Resolves issue discovered in March 2022 OZ Audit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants