Orders with signatures that require regular validation can have their validation bypassed if the order is partially filled
The signature types `Wallet`, `Validator`, and `EIP1271Wallet` require explicit validation to authorize each action performed on a given order. This means that if an order was signed using one of these methods, the `Exchange` must perform a validation step on the signature each time the order is submitted for a partial fill. In contrast, the other canonical signature types (EIP712, `EthSign`, and PreSigned) are only required to be validated by the `Exchange` on the order's first fill; subsequent fills take the order's existing fill amount as implicit validation that the order has a valid, published signature.\\nThis re-validation step for `Wallet`, `Validator`, and `EIP1271Wallet` signatures is intended to facilitate their use with contracts whose validation depends on some state that may change over time. For example, a validating contract may call into a price feed and determine that some order is invalid if its price deviates from some expected range. In this case, the repeated validation allows 0x users to make orders with custom fill conditions which are evaluated at run-time.\\nWe found that if the sender provides the contract with an invalid signature after the order in question has already been partially filled, the regular validation check required for `Wallet`, `Validator`, and `EIP1271Wallet` signatures can be bypassed entirely.\\nSignature validation takes place in `MixinExchangeCore._assertFillableOrder`. A signature is only validated if it passes the following criteria:\\n```\\n// Validate either on the first fill or if the signature type requires\\n// regular validation.\\naddress makerAddress = order.makerAddress;\\nif (orderInfo.orderTakerAssetFilledAmount == 0 ||\\n    \\_doesSignatureRequireRegularValidation(\\n        orderInfo.orderHash,\\n        makerAddress,\\n        signature\\n    )\\n) {\\n```\\n\\nIn effect, signature validation only occurs if:\\n`orderInfo.orderTakerAssetFilledAmount == 0` OR\\n`_doesSignatureRequireRegularValidation(orderHash, makerAddress, signature)`\\nIf an order is partially filled, the first condition will evaluate to false. Then, that order's signature will only be validated if `_doesSignatureRequireRegularValidation` evaluates to true:\\n```\\nfunction \\_doesSignatureRequireRegularValidation(\\n    bytes32 hash,\\n    address signerAddress,\\n    bytes memory signature\\n)\\n    internal\\n    pure\\n    returns (bool needsRegularValidation)\\n{\\n    // Read the signatureType from the signature\\n    SignatureType signatureType = \\_readSignatureType(\\n        hash,\\n        signerAddress,\\n        signature\\n    );\\n\\n    // Any signature type that makes an external call needs to be revalidated\\n    // with every partial fill\\n    needsRegularValidation =\\n        signatureType == SignatureType.Wallet ||\\n        signatureType == SignatureType.Validator ||\\n        signatureType == SignatureType.EIP1271Wallet;\\n    return needsRegularValidation;\\n}\\n```\\n\\nThe `SignatureType` returned from `_readSignatureType` is directly cast from the final byte of the passed-in signature. Any value that does not cast to `Wallet`, `Validator`, and `EIP1271Wallet` will cause `_doesSignatureRequireRegularValidation` to return false, skipping validation.\\nThe result is that an order whose signature requires regular validation can be forced to skip validation if it has been partially filled, by passing in an invalid signature.
There are a few options for remediation:\\nHave the `Exchange` validate the provided signature every time an order is filled.\\nRecord the first seen signature type or signature hash for each order, and check that subsequent actions are submitted with a matching signature.\\nThe first option requires the fewest changes, and does not require storing additional state. While this does mean some additional cost validating subsequent signatures, we feel the increase in flexibility is well worth it, as a maker could choose to create multiple valid signatures for use across different order books.
```\\n// Validate either on the first fill or if the signature type requires\\n// regular validation.\\naddress makerAddress = order.makerAddress;\\nif (orderInfo.orderTakerAssetFilledAmount == 0 ||\\n    \\_doesSignatureRequireRegularValidation(\\n        orderInfo.orderHash,\\n        makerAddress,\\n        signature\\n    )\\n) {\\n```\\n