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

New/Consolidated Signature Type(s) and Behavior #33

Open
dorothy-zbornak opened this issue Apr 19, 2019 · 3 comments

Comments

@dorothy-zbornak
Copy link

commented Apr 19, 2019

Summary

Add more robust order and transaction signature validation with the following signature types:

  • Validator (*replaces existing behavior)
  • EIP1271Wallet

Validator contracts for these signature types accept abi-encoded Order and ZeroExTransaction types, depending on where the signature is used. These new signature types, in addition to the existing Wallet type, should be checked for every fill operation. This is in contrast to 2.0 where we only validate the signature on the first fill.

Motivation

In 2.0, we have Validator and Wallet signature types, which can only validate against a hash, which means the order/transaction must be somehow registered with the validator contract prior to execution to determine meaningful context. It would be more useful if the validator contract was provided with the complete order/transaction data so they can implement more nuanced and dynamic filtering criteria.

Recent improvements to solidity and ABIEncoderV2 have made this approach relatively simple to execute.

Status

Branch: 3.0

  • #1774 merged: First pass (lots of new signature types).
  • #1885 in review: Consolidated signature types, validating on every fill, EIP-1271 pattern.

Specification

Restrictions

  • Validator contracts will be called via staticcall(). If the contract attempts to update state during call, the validation will fail.
  • Validator contracts using the Validator signature type must be registered in advance via setSignatureValidatorApproval() (unchanged from 2.0). This only has to be done once per validator-signer pair.

Signature Encoding

The Validator signature type is tightly packed with the ordered fields:

// Arbitrary data passed to validator as `signature`. 0 or more bytes.
bytes signatureData
// Address of the validator contract. 20 bytes.
address validatorAddress
// Signature type. Always `0x05`. 1 byte.
uint8 signatureType

The EIP1271Wallet signature type is tightly packed with the following ordered fields. Note that the address of the validator contract is implied as the order maker or transaction signer.

// Arbitrary signature data passed to validator as `signature`. 0 or more bytes.
bytes signatureData
// Signature type. Always `0x07`. 1 byte.
uint8 signatureType

Implementation

Contracts validating the Validator and EIP1271 signature types follow the EIP-1271 pattern and must expose the following callback:

function isValidSignature(
    // ABI-encoded data associated with the signature.
    bytes calldata data,
    // arbitrary signature bytes passed in top-level call.
    bytes calldata signature
)
    external
    view
    // Should return 0x20c13b0b if the signature is valid.
    returns (bytes4 magicValue);

EIP-1271 data Encoding

There are two ways the data parameter for EIP1271Wallet and Validator signatures can be encoded, depending on what type of data is signed:

  • For Orders: abi.encode(Order order, bytes32 orderHash)
  • For ZeroExTransactions: abi.encode(ZeroExTransaction transaction, bytes32 transactionHash)

Example

Here is a complete (if trivial) implementation that validates an Order signature:

pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;

contract MyOrderValidator {

    // 0x order structure
    struct Order {
        address makerAddress;
        address takerAddress;
        address feeRecipientAddress;
        address senderAddress;
        uint256 makerAssetAmount;
        uint256 takerAssetAmount;
        uint256 makerFee;
        uint256 takerFee;
        uint256 expirationTimeSeconds;
        uint256 salt;
        bytes makerAssetData;
        bytes takerAssetData;
        bytes makerFeeAssetData;
        bytes takerFeeAssetData;
    }

    /// @dev Validate an order signature.
    /// @param data The ABI-encoded order and hash.
    /// @param signature Signature data for the order.
    /// @return magicValue 0x20c13b0b if the signature is valid.
    function isValidSignature(
        bytes calldata data,
        bytes calldata signature
    )
        external
        view
        returns (bytes4 magicValue)
    {
        // Decode the order and hash.
        (Order memory order, bytes32 orderHash) = abi.decode(data, (Order, bytes32));
        // Validate the order
        // ...
        magicValue = 0x20c13b0b; // Success
    }
}

@abandeali1 abandeali1 added 3.0 and removed 3.0 labels May 3, 2019

@dekz dekz changed the title [3.0] OrderValidator Signature Type(s) OrderValidator Signature Type(s) May 6, 2019

@abandeali1

This comment has been minimized.

Copy link
Member

commented May 6, 2019

It might be valuable to support EIP-1271 as well (either in addition to or as a replacement to the WalletOrderValidator type).

@dorothy-zbornak

This comment has been minimized.

Copy link
Author

commented Jun 24, 2019

Updated to reflect that Order* signature types should always be checked on every fill (not just the first).

A separate issue for EIP-1271 signature types is now at #46 .

@dorothy-zbornak dorothy-zbornak changed the title OrderValidator Signature Type(s) New/Consolidated Signature Type(s) and Behavior Jun 26, 2019

@dorothy-zbornak

This comment has been minimized.

Copy link
Author

commented Jun 26, 2019

Updated for consolidated signature types and EIP-1271 pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.