@0x/base-contract
: Make PromiseWithTransactionHash
fully compatible with regular Promise
types.
`@0x/contracts/exchange` Make `OrderValidator` and `WalletOrderValidator` signature types checked for every fill (not just first)'
This commit is contained in:
parent
2e5645108b
commit
5f8ebc3601
@ -354,9 +354,15 @@ contract MixinExchangeCore is
|
||||
}
|
||||
}
|
||||
|
||||
// Validate Maker signature (check only if first time seen)
|
||||
if (orderInfo.orderTakerAssetFilledAmount == 0) {
|
||||
address makerAddress = order.makerAddress;
|
||||
// Validate either on the first fill or if the signature type requires
|
||||
// regular validation.
|
||||
address makerAddress = order.makerAddress;
|
||||
if (orderInfo.orderTakerAssetFilledAmount == 0 ||
|
||||
doesSignatureRequireRegularValidation(
|
||||
orderInfo.orderHash,
|
||||
makerAddress,
|
||||
signature
|
||||
)) {
|
||||
if (!_isValidOrderWithHashSignature(
|
||||
order,
|
||||
orderInfo.orderHash,
|
||||
|
@ -31,13 +31,13 @@ import "./MixinTransactions.sol";
|
||||
import "./MixinExchangeRichErrors.sol";
|
||||
|
||||
|
||||
contract MixinSignatureValidator is
|
||||
MixinExchangeRichErrors,
|
||||
ReentrancyGuard,
|
||||
LibOrder,
|
||||
contract MixinSignatureValidator is
|
||||
MixinExchangeRichErrors,
|
||||
ReentrancyGuard,
|
||||
LibOrder,
|
||||
ISignatureValidator,
|
||||
MixinTransactions
|
||||
{
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
|
||||
// Mapping of hash => signer => signed
|
||||
@ -161,13 +161,41 @@ contract MixinSignatureValidator is
|
||||
);
|
||||
}
|
||||
|
||||
/// @dev Checks if a signature is of a type that should be verified for
|
||||
/// every subsequent fill.
|
||||
/// @param orderHash The hash of the order.
|
||||
/// @param signerAddress The address of the signer.
|
||||
/// @param signature The signature for `orderHash`.
|
||||
/// @return needsRegularValidation True if the signature should be validated
|
||||
/// for every operation.
|
||||
function doesSignatureRequireRegularValidation(
|
||||
bytes32 orderHash,
|
||||
address signerAddress,
|
||||
bytes memory signature
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bool needsRegularValidation)
|
||||
{
|
||||
SignatureType signatureType = _readValidSignatureType(
|
||||
orderHash,
|
||||
signerAddress,
|
||||
signature
|
||||
);
|
||||
// Only signature types that take a full order should be validated
|
||||
// regularly.
|
||||
return
|
||||
signatureType == SignatureType.OrderValidator ||
|
||||
signatureType == SignatureType.WalletOrderValidator;
|
||||
}
|
||||
|
||||
/// @dev Verifies that an order, with provided order hash, has been signed
|
||||
/// by the given signer.
|
||||
/// @param order The order.
|
||||
/// @param orderHash The hash of the order.
|
||||
/// @param signerAddress Address that should have signed the.Signat given hash.
|
||||
/// @param signature Proof that the hash has been signed by signer.
|
||||
/// @return True if the signature is valid for the given hash and signer.
|
||||
/// @return isValid True if the signature is valid for the given hash and signer.
|
||||
function _isValidOrderWithHashSignature(
|
||||
Order memory order,
|
||||
bytes32 orderHash,
|
||||
|
@ -96,4 +96,20 @@ contract ISignatureValidator {
|
||||
public
|
||||
view
|
||||
returns (bool isValid);
|
||||
|
||||
/// @dev Checks if a signature is of a type that should be verified for
|
||||
/// every subsequent fill.
|
||||
/// @param orderHash The hash of the order.
|
||||
/// @param signerAddress The address of the signer.
|
||||
/// @param signature The signature for `orderHash`.
|
||||
/// @return needsRegularValidation True if the signature should be validated
|
||||
/// for every operation.
|
||||
function doesSignatureRequireRegularValidation(
|
||||
bytes32 orderHash,
|
||||
address signerAddress,
|
||||
bytes memory signature
|
||||
)
|
||||
public
|
||||
pure
|
||||
returns (bool needsRegularValidation);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import { assetDataUtils, ExchangeRevertErrors, orderHashUtils, signatureUtils }
|
||||
import { SignatureType, SignedOrder } from '@0x/types';
|
||||
import { BigNumber, providerUtils, StringRevertError } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
import { LogWithDecodedArgs } from 'ethereum-types';
|
||||
import { LogWithDecodedArgs, TransactionReceiptWithDecodedLogs } from 'ethereum-types';
|
||||
import ethUtil = require('ethereumjs-util');
|
||||
|
||||
import {
|
||||
@ -31,7 +31,7 @@ const expect = chai.expect;
|
||||
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
// tslint:disable:no-unnecessary-type-assertion
|
||||
describe('MixinSignatureValidator', () => {
|
||||
describe.only('MixinSignatureValidator', () => {
|
||||
let chainId: number;
|
||||
let signedOrder: SignedOrder;
|
||||
let orderFactory: OrderFactory;
|
||||
@ -93,12 +93,9 @@ describe('MixinSignatureValidator', () => {
|
||||
|
||||
signatureValidatorLogDecoder = new LogDecoder(web3Wrapper, artifacts);
|
||||
const approveValidator = async (validatorAddress: string) => {
|
||||
type SendApproveTx = (address: string, approved: boolean, txData: { from: string }) => Promise<string>;
|
||||
const sendTx = async (fn: { sendTransactionAsync: SendApproveTx }) => {
|
||||
return web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await fn.sendTransactionAsync(validatorAddress, true, { from: signerAddress }),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
type SendApproveTx = (address: string, approved: boolean, txData: { from: string }) => Promise<any>;
|
||||
const sendTx = async (fn: { awaitTransactionSuccessAsync: SendApproveTx }) => {
|
||||
return fn.awaitTransactionSuccessAsync(validatorAddress, true, { from: signerAddress }) as Promise<any>;
|
||||
};
|
||||
await sendTx(signatureValidator.setSignatureValidatorApproval);
|
||||
await sendTx(signatureValidator.setOrderValidatorApproval);
|
||||
@ -410,13 +407,10 @@ describe('MixinSignatureValidator', () => {
|
||||
|
||||
it('should return false when SignatureType=Validator, signature is valid and validator is not approved', async () => {
|
||||
// Set approval of signature validator to false
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await signatureValidator.setSignatureValidatorApproval.sendTransactionAsync(
|
||||
testValidator.address,
|
||||
false,
|
||||
{ from: signerAddress },
|
||||
),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
await signatureValidator.setSignatureValidatorApproval.awaitTransactionSuccessAsync(
|
||||
testValidator.address,
|
||||
false,
|
||||
{ from: signerAddress },
|
||||
);
|
||||
// Validate signature
|
||||
const validatorAddress = ethUtil.toBuffer(`${testValidator.address}`);
|
||||
@ -430,10 +424,7 @@ describe('MixinSignatureValidator', () => {
|
||||
it('should return true when SignatureType=Presigned and signer has presigned hash', async () => {
|
||||
// Presign hash
|
||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await signatureValidator.preSign.sendTransactionAsync(orderHashHex, { from: signedOrder.makerAddress }),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
);
|
||||
await signatureValidator.preSign.awaitTransactionSuccessAsync(orderHashHex, { from: signedOrder.makerAddress });
|
||||
// Validate presigned signature
|
||||
const signature = ethUtil.toBuffer(`0x${SignatureType.PreSigned}`);
|
||||
const signatureHex = ethUtil.bufferToHex(signature);
|
||||
@ -574,11 +565,10 @@ describe('MixinSignatureValidator', () => {
|
||||
|
||||
it('should return false when SignatureType=OrderValidator, signature is valid and validator is not approved', async () => {
|
||||
// Set approval of signature validator to false
|
||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||
await signatureValidator.setOrderValidatorApproval.sendTransactionAsync(testValidator.address, false, {
|
||||
from: signerAddress,
|
||||
}),
|
||||
constants.AWAIT_TRANSACTION_MINED_MS,
|
||||
await signatureValidator.setOrderValidatorApproval.awaitTransactionSuccessAsync(
|
||||
testValidator.address,
|
||||
false,
|
||||
{ from: signerAddress },
|
||||
);
|
||||
// Validate signature
|
||||
const validatorAddress = ethUtil.toBuffer(`${testValidator.address}`);
|
||||
|
@ -38,19 +38,27 @@ export interface AbiEncoderByFunctionSignature {
|
||||
* `awaitTransactionSuccessAsync()`.
|
||||
* Maybe there's a better place for this.
|
||||
*/
|
||||
export class PromiseWithTransactionHash<T> implements PromiseLike<T> {
|
||||
export class PromiseWithTransactionHash<T> implements Promise<T> {
|
||||
public readonly txHashPromise: Promise<string>;
|
||||
private readonly _promise: Promise<T>;
|
||||
constructor(txHashPromise: Promise<string>, promise: Promise<T>) {
|
||||
this.txHashPromise = txHashPromise;
|
||||
this._promise = promise;
|
||||
}
|
||||
// tslint:disable-next-line:async-suffix
|
||||
public then<TResult>(
|
||||
onFulfilled?: (v: T) => TResult | PromiseLike<TResult>,
|
||||
onRejected?: (reason: any) => PromiseLike<never>,
|
||||
): PromiseLike<TResult> {
|
||||
onFulfilled?: (v: T) => TResult | Promise<TResult>,
|
||||
onRejected?: (reason: any) => Promise<never>,
|
||||
): Promise<TResult> {
|
||||
return this._promise.then<TResult>(onFulfilled, onRejected);
|
||||
}
|
||||
// tslint:disable-next-line:async-suffix
|
||||
public catch<TResult>(onRejected?: (reason: any) => Promise<TResult>): Promise<TResult | T> {
|
||||
return this._promise.catch(onRejected);
|
||||
}
|
||||
get [Symbol.toStringTag](): 'Promise' {
|
||||
return this._promise[Symbol.toStringTag];
|
||||
}
|
||||
}
|
||||
|
||||
export class BaseContract {
|
||||
|
Loading…
x
Reference in New Issue
Block a user