-
Notifications
You must be signed in to change notification settings - Fork 465
Always validate callback signatures & add support for EIP-1271 signatures #1885
Always validate callback signatures & add support for EIP-1271 signatures #1885
Conversation
…le with regular `Promise` types. `@0x/contracts/exchange` Make `OrderValidator` and `WalletOrderValidator` signature types checked for every fill (not just first)'
…derValidator` signature types on every fill `@0x/contracts-exchange`: Add `validatorAddress` field to `SignatureValidatorError` and `SignatureOrderValidatorError` rich reverts `@0x/contracts-exchange`: Add separate `SignatureOrderValidatorNotApprovedError` for `OrderValidator` signatures `@0x/contracts-exchange`: Consolidate Wallet and Validator test contracts into a single configurable `TestValidatorWallet` contract. `@0x/contracts-exchange`: Rewrite many tests in `signature_validator.ts` for brevity.
…rror` and `SignatureValidatorError` `RevertError` types. `@0x/order-utils`: Add `SignatureOrderValidatorNotApprovedError` and `SignatureValidatorNotApprovedError` `RevertError` types.
…alletOrderValidator` if `makerAddress == this`. `@0x/contracts-exchange`: Update tests for repeatable signature validation.
…tureType` `@0x/types`: Add `EIP1271Wallet` and `EIP1271OrderWallet` to `SignatureType`
…gnatureOrderWalletError` `RevertError` type.
…et` signature type `@0x/contracts-exchange`: Rename `SignatureWalletOrderValidatorError` to `SignatureOrderWalletError` `@0x/contracts-exchange`: Add `IEIP1271Wallet` interface `@0x/contracts-exchange`: Add `EIP1271Wallet` and `EIP1271OrderWallet` to `SignatureType` `@0x/contracts-exchange`: Always check `OrderValidator`, `OrderWallet`, `EIP1271OrderWallet` signature types on every fill `@0x/contracts-exchange`: Add tests for EIP1271 signature types. `@0x/contracts-exchange`: Update `LibExchangeRichErrorDecoder` for new/renamed Error types.
fa7d1f8
to
0e9d1cf
Compare
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.
My main point of feedback is that we have a lot of signature types right now. This makes it pretty difficult to decide which to use as a user and which to support as a relayer. It also adds overhead when duplicating this verification logic in other contracts (like the Coordinator
). I'm wondering how to best consolidate these, since it seems like there is a good amount of overlap between a lot of them.
`@0x/contracts-exchange`: Fighting with linearization issues.
`@0x/contracts-exchange`: Remove references to removed signature types and associated functions.
… types. `@0x/contracts-exchange`: Update `Whitelist` example for new signature types.
…dFillResults` public
if (signatureType == SignatureType.Validator) { | ||
// The entire order is verified by a validator contract. | ||
isValid = _validateBytesWithValidator( | ||
abi.encode(order, orderHash), |
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 wondering if it still makes sense to pass the orderHash
in here. Would you blindly trust that the hash corresponds to the data when verifying the signature? I feel like if you only want the hash, you'd probably just use the regular Wallet
type. If you want both the hash and the data, you probably won't trust the hash without verifying.
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 feel like the Validator
type isn't very useful with just a hash, generally speaking.
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.
My arguments for including the hash would be that the hash is a very useful, canonical ID, which is not cheap to compute. For example, a validator could use it to immediately look up the filled
state of the order.
Also, wouldn't just gating your callback such that msg.sender == exchange
be sufficient to trust that the hash provided is authentic?
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 suppose it can't hurt. Curious to see how much it gets used.
isValid = _validateOrderWithWallet( | ||
order, | ||
isValid = _validateBytesWithWallet( | ||
abi.encode(order, orderHash), |
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.
Same as above.
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.
Very nice job!
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.
Nice work! Solid test coverage as well. +1
MixinExchangeRichErrors, | ||
ReentrancyGuard, | ||
LibOrder, | ||
contract MixinSignatureValidator is |
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 is out of scope for this PR, but I think it could be good to abstract a lot of this logic into a generic library like libSignatureValidator
that can be used across our packages.
Description
This PR addresses ZEIP #33.
Contract Signature Types Always Checked
We now always check any signature type that relies on a contract. Prior to this, we only checked the signature callback on the first fill. Now this occurs on every subsequent fill. The signature types affected are:
Wallet
Validator
EIP1271Wallet
(new: see below)Consolidated Signature Types
EIP1271Wallet
, has been added for wallets that implement the EIP-1271 standard, which take an arbitrarybytes data
field along with a signature.WalletOrderValidator
has been removed sinceEIP1271Wallet
is a much more flexible alternative now.Validator
signature type for signatures that specify an external validator contract.ZeroExTransaction
s, in addition toOrder
s!Interface for
EIP1271Wallet
andValidator
contracts:Both of these signature types follow the EIP-1271 pattern and require a contract that exposes the following callback:
EIP-1271
data
EncodingThere are two ways the
data
parameter forEIP1271Wallet
andValidator
signatures can be encoded, depending on what type of data is signed:abi.encode(Order order, bytes32 orderHash)
abi.encode(ZeroExTransaction transaction, bytes32 transactionHash)
Bonus Material
signature_validator.ts
to match.core.ts
because I felt like they were already pretty well covered insignature_validator.ts
.validatorAddress
field has been added toSignatureValidatorError
.awaitTransactionSuccessAsync()
are actually compatible with the basePromise
type now (not justPromiseLike
).assertValidFill()
andcalculateMatchedFillResults()
functions on the Exchange have been made public.Testing instructions
yarn test:contracts
and cross your fingers.Types of changes
Checklist:
[WIP]
if necessary.