Skip to content
This repository has been archived by the owner on Jul 9, 2021. It is now read-only.

Commit

Permalink
Add OrderValidator and WalletOrderValidator signature strategies to E…
Browse files Browse the repository at this point in the history
…xchange (#1774)

* In `@0x/contracts-exchange`: Add `SignatureType.OrderValidator` support to contracts and refactor signature validation functions.

* In `@0x/types`: Add `SignatureType.OrderValidator` and `RevertReason.InappropriateSignature`.

* In `@0x/contracts-exchange`: Fix contracts and update tests for `SignatureType.OrderValidator`.

* Ran prettier/linter

* Update changelogs

* In `@0x/order-utils`: Add `SignatureOrderValidatorError` to `ExchangeRevertErrors`.

* In `@0x/contracts-exchange`: Add `SignatureOrderValidatorError` rich revert. Fix rebase issues. Rename `IValidator.isValidOrder` to `IValidator.isValidOrderSignature`.

* In `@0x/contracts-exchange`: Add revert test cases for `OrderValidator` signature type.

* In `@0x/order-utils`: Update changelog.

* In `@0x/contracts-exchange`: Split off `SignatureType.OrderValidator` scheme into its own interface and registry.

* In `@0x/types`: Add `SignatureType.WalletOrderValidator`.

* In `@0x/order-utils`: Add `SignatureWalletOrderValidatorError`.

* In `@0x/contracts-exchange`: Add `SignatureType.WalletOrderValidator` support.

* Ran prettier

* In `@0x/types`: Remove `RevertReason.WalletOrderValidator`.

* Update/fix changelogs in `@0x/contracts-exchange`, `@0x/order-utils`, and `@0x/types`.

* In `@0x/contracts-exchange`: Make `isValidOrderSignature` `external` instead of `public`.

* In `@0x/contracts-exchange`: Change `isValidOrderSignature` back to `public` because passing `calldata` to internal functions isn't supported.
  • Loading branch information
dorothy-zbornak authored and abandeali1 committed Jun 24, 2019
1 parent 45b770f commit 9a5b6dd
Show file tree
Hide file tree
Showing 26 changed files with 932 additions and 306 deletions.
8 changes: 8 additions & 0 deletions contracts/exchange/CHANGELOG.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
{
"note": "Upgrade all string reverts to rich reverts",
"pr": 1761
},
{
"note": "Add support for `SignatureType.OrderValidator` for orders",
"pr": 1774
},
{
"note": "Add support for `SignatureType.WalletOrderValidator` for orders",
"pr": 1774
}
]
},
Expand Down
1 change: 1 addition & 0 deletions contracts/exchange/compiler.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"src/interfaces/IExchange.sol",
"src/interfaces/IExchangeCore.sol",
"src/interfaces/IMatchOrders.sol",
"src/interfaces/IOrderValidator.sol",
"src/interfaces/ISignatureValidator.sol",
"src/interfaces/ITransactions.sol",
"src/interfaces/IValidator.sol",
Expand Down
31 changes: 27 additions & 4 deletions contracts/exchange/contracts/examples/Validator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@
*/

pragma solidity ^0.5.5;
pragma experimental ABIEncoderV2;

import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "../src/interfaces/IValidator.sol";
import "../src/interfaces/IOrderValidator.sol";


contract Validator is
IValidator
contract Validator is
IValidator,
IOrderValidator
{

// The single valid signer for this wallet.
// The single valid signer for this validator.
// solhint-disable-next-line var-name-mixedcase
address internal VALID_SIGNER;

Expand All @@ -35,12 +39,12 @@ contract Validator is
VALID_SIGNER = validSigner;
}

// solhint-disable no-unused-vars
/// @dev Verifies that a signature is valid. `signer` must match `VALID_SIGNER`.
/// @param hash Message hash that is signed.
/// @param signerAddress Address that should have signed the given hash.
/// @param signature Proof of signing.
/// @return Validity of signature.
// solhint-disable no-unused-vars
function isValidSignature(
bytes32 hash,
address signerAddress,
Expand All @@ -53,4 +57,23 @@ contract Validator is
return (signerAddress == VALID_SIGNER);
}
// solhint-enable no-unused-vars

// solhint-disable no-unused-vars
/// @dev Verifies that an order and signature is valid. `signer` must match `VALID_SIGNER`.
/// @param order The order.
/// @param orderHash The order hash.
/// @param signature Proof of signing.
/// @return Validity of signature.
function isValidOrderSignature(
LibOrder.Order calldata order,
bytes32 orderHash,
bytes calldata signature
)
external
view
returns (bool isValid)
{
return (order.makerAddress == VALID_SIGNER);
}
// solhint-enable no-unused-vars
}
53 changes: 44 additions & 9 deletions contracts/exchange/contracts/examples/Wallet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
*/

pragma solidity ^0.5.5;
pragma experimental ABIEncoderV2;

import "../src/interfaces/IWallet.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";


contract Wallet is
contract Wallet is
IWallet
{
using LibBytes for bytes;
Expand All @@ -40,26 +42,59 @@ contract Wallet is
/// @dev Validates an EIP712 signature.
/// The signer must match the owner of this wallet.
/// @param hash Message hash that is signed.
/// @param eip712Signature Proof of signing.
/// @param signature Proof of signing.
/// @return Validity of signature.
function isValidSignature(
bytes32 hash,
bytes calldata eip712Signature
bytes calldata signature
)
external
view
returns (bool isValid)
{
require(
eip712Signature.length == 65,
signature.length == 65,
"LENGTH_65_REQUIRED"
);

uint8 v = uint8(eip712Signature[0]);
bytes32 r = eip712Signature.readBytes32(1);
bytes32 s = eip712Signature.readBytes32(33);
return validateEIP712Signature(hash, signature);
}

/// @dev Validates an order AND EIP712 signature.
/// The signer must match the owner of this wallet.
/// @param order The order.
/// @param orderHash The order hash.
/// @param signature Proof of signing.
/// @return Validity of order and signature.
function isValidOrderSignature(
LibOrder.Order calldata order,
bytes32 orderHash,
bytes calldata signature
)
external
view
returns (bool isValid)
{
// Ensure order hash is correct.
require(
order.makerAddress == WALLET_OWNER,
"INVALID_ORDER_MAKER"
);
return validateEIP712Signature(orderHash, signature);
}

function validateEIP712Signature(
bytes32 hash,
bytes memory signature
)
private
view
returns (bool isValid)
{
uint8 v = uint8(signature[0]);
bytes32 r = signature.readBytes32(1);
bytes32 s = signature.readBytes32(33);
address recoveredAddress = ecrecover(hash, v, r, s);
isValid = WALLET_OWNER == recoveredAddress;
return isValid;
return WALLET_OWNER == recoveredAddress;
}
}
3 changes: 2 additions & 1 deletion contracts/exchange/contracts/src/MixinExchangeCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@ contract MixinExchangeCore is
// Validate Maker signature (check only if first time seen)
if (orderInfo.orderTakerAssetFilledAmount == 0) {
address makerAddress = order.makerAddress;
if (!isValidSignature(
if (!isValidOrderWithHashSignature(
order,
orderInfo.orderHash,
makerAddress,
signature)) {
Expand Down
38 changes: 38 additions & 0 deletions contracts/exchange/contracts/src/MixinExchangeRichErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,44 @@ contract MixinExchangeRichErrors is
);
}

function SignatureOrderValidatorError(
bytes32 orderHash,
address signer,
bytes memory signature,
bytes memory errorData
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
SIGNATURE_ORDER_VALIDATOR_ERROR_SELECTOR,
orderHash,
signer,
signature,
errorData
);
}

function SignatureWalletOrderValidatorError(
bytes32 orderHash,
address wallet,
bytes memory signature,
bytes memory errorData
)
internal
pure
returns (bytes memory)
{
return abi.encodeWithSelector(
SIGNATURE_WALLET_ORDER_VALIDATOR_ERROR_SELECTOR,
orderHash,
wallet,
signature,
errorData
);
}

function OrderStatusError(
LibOrder.OrderStatus orderStatus,
bytes32 orderHash
Expand Down
Loading

0 comments on commit 9a5b6dd

Please sign in to comment.