Fixes #1998, still needs Integration testing
This commit is contained in:
@@ -20,7 +20,7 @@ import { assert } from './assert';
|
||||
import { eip712Utils } from './eip712_utils';
|
||||
import { orderHashUtils } from './order_hash';
|
||||
import { transactionHashUtils } from './transaction_hash';
|
||||
import { TypedDataError } from './types';
|
||||
import { PresignedSignatureOpts, SignatureValidationOpts, TypedDataError, ValidatorSignatureOpts } from './types';
|
||||
import { utils } from './utils';
|
||||
|
||||
export const signatureUtils = {
|
||||
@@ -38,6 +38,7 @@ export const signatureUtils = {
|
||||
data: string,
|
||||
signature: string,
|
||||
signerAddress: string,
|
||||
signatureValidationOpts?: SignatureValidationOpts,
|
||||
): Promise<boolean> {
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
assert.isHexString('data', data);
|
||||
@@ -75,17 +76,22 @@ export const signatureUtils = {
|
||||
}
|
||||
|
||||
case SignatureType.Validator: {
|
||||
const exchangeAddress = signatureValidationOpts &&
|
||||
(signatureValidationOpts as ValidatorSignatureOpts).exchangeAddress;
|
||||
const isValid = await signatureUtils.isValidValidatorSignatureAsync(
|
||||
provider,
|
||||
data,
|
||||
signature,
|
||||
signerAddress,
|
||||
exchangeAddress,
|
||||
);
|
||||
return isValid;
|
||||
}
|
||||
|
||||
case SignatureType.PreSigned: {
|
||||
return signatureUtils.isValidPresignedSignatureAsync(provider, data, signerAddress);
|
||||
const exchangeAddress = signatureValidationOpts &&
|
||||
(signatureValidationOpts as PresignedSignatureOpts).exchangeAddress;
|
||||
return signatureUtils.isValidPresignedSignatureAsync(provider, data, signerAddress, exchangeAddress);
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -103,14 +109,23 @@ export const signatureUtils = {
|
||||
supportedProvider: SupportedProvider,
|
||||
data: string,
|
||||
signerAddress: string,
|
||||
exchangeAddress?: string,
|
||||
): Promise<boolean> {
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
assert.isHexString('data', data);
|
||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const networkId = await web3Wrapper.getNetworkIdAsync();
|
||||
const addresses = getContractAddressesForNetworkOrThrow(networkId);
|
||||
const exchangeContract = new ExchangeContract(addresses.exchange, provider);
|
||||
|
||||
let exchangeContract: ExchangeContract;
|
||||
if (exchangeAddress) {
|
||||
assert.isETHAddressHex('exchange', exchangeAddress);
|
||||
exchangeContract = new ExchangeContract(exchangeAddress, provider);
|
||||
} else {
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const networkId = await web3Wrapper.getNetworkIdAsync();
|
||||
const addresses = getContractAddressesForNetworkOrThrow(networkId);
|
||||
exchangeContract = new ExchangeContract(addresses.exchange, provider);
|
||||
}
|
||||
|
||||
const isValid = await exchangeContract.preSigned.callAsync(data, signerAddress);
|
||||
return isValid;
|
||||
},
|
||||
@@ -151,13 +166,25 @@ export const signatureUtils = {
|
||||
data: string,
|
||||
signature: string,
|
||||
signerAddress: string,
|
||||
exchangeAddress?: string,
|
||||
): Promise<boolean> {
|
||||
const provider = providerUtils.standardizeOrThrow(supportedProvider);
|
||||
assert.isHexString('data', data);
|
||||
assert.isHexString('signature', signature);
|
||||
assert.isETHAddressHex('signerAddress', signerAddress);
|
||||
const validatorSignature = parseValidatorSignature(signature);
|
||||
const exchangeContract = new ExchangeContract(signerAddress, provider);
|
||||
|
||||
let exchangeContract: ExchangeContract;
|
||||
if (exchangeAddress) {
|
||||
assert.isETHAddressHex('exchange', exchangeAddress);
|
||||
exchangeContract = new ExchangeContract(exchangeAddress, provider);
|
||||
} else {
|
||||
const web3Wrapper = new Web3Wrapper(provider);
|
||||
const networkId = await web3Wrapper.getNetworkIdAsync();
|
||||
const addresses = getContractAddressesForNetworkOrThrow(networkId);
|
||||
exchangeContract = new ExchangeContract(addresses.exchange, provider);
|
||||
}
|
||||
|
||||
const validatorSignature = signatureUtils.parseValidatorSignature(signature);
|
||||
const isValidatorApproved = await exchangeContract.allowedValidators.callAsync(
|
||||
signerAddress,
|
||||
validatorSignature.validatorAddress,
|
||||
@@ -168,7 +195,7 @@ export const signatureUtils = {
|
||||
);
|
||||
}
|
||||
|
||||
const validatorContract = new IValidatorContract(signerAddress, provider);
|
||||
const validatorContract = new IValidatorContract(validatorSignature.signature, provider);
|
||||
const isValid = await validatorContract.isValidSignature.callAsync(
|
||||
data,
|
||||
signerAddress,
|
||||
@@ -485,18 +512,23 @@ export const signatureUtils = {
|
||||
|
||||
return ecSignature;
|
||||
},
|
||||
};
|
||||
|
||||
function parseValidatorSignature(signature: string): ValidatorSignature {
|
||||
assert.isOneOfExpectedSignatureTypes(signature, [SignatureType.Validator]);
|
||||
// tslint:disable:custom-no-magic-numbers
|
||||
const validatorSignature = {
|
||||
validatorAddress: signature.slice(-22, -2),
|
||||
signature: signature.slice(0, -22),
|
||||
};
|
||||
// tslint:enable:custom-no-magic-numbers
|
||||
return validatorSignature;
|
||||
}
|
||||
/**
|
||||
* Parse a hex-encoded Validator signature into validator address and signature components
|
||||
* @param signature A hex encoded Validator 0x Protocol signature
|
||||
* @return A ValidatorSignature with validatorAddress and signature parameters
|
||||
*/
|
||||
parseValidatorSignature(signature: string): ValidatorSignature {
|
||||
assert.isOneOfExpectedSignatureTypes(signature, [SignatureType.Validator]);
|
||||
// tslint:disable:custom-no-magic-numbers
|
||||
const validatorSignature = {
|
||||
validatorAddress: `0x${signature.slice(-42, -2)}`,
|
||||
signature: signature.slice(0, -42),
|
||||
};
|
||||
// tslint:enable:custom-no-magic-numbers
|
||||
return validatorSignature;
|
||||
},
|
||||
};
|
||||
|
||||
function parseSignatureHexAsVRS(signatureHex: string): ECSignature {
|
||||
const signatureBuffer = ethUtil.toBuffer(signatureHex);
|
||||
|
||||
@@ -25,6 +25,15 @@ export interface CreateOrderOpts {
|
||||
expirationTimeSeconds?: BigNumber;
|
||||
}
|
||||
|
||||
export type SignatureValidationOpts = ValidatorSignatureOpts | PresignedSignatureOpts;
|
||||
|
||||
export interface ValidatorSignatureOpts {
|
||||
exchangeAddress: string;
|
||||
}
|
||||
|
||||
export interface PresignedSignatureOpts {
|
||||
exchangeAddress: string;
|
||||
}
|
||||
/**
|
||||
* remainingFillableMakerAssetAmount: An array of BigNumbers corresponding to the `orders` parameter.
|
||||
* You can use `OrderStateUtils` `@0x/order-utils` to perform blockchain lookups for these values.
|
||||
|
||||
@@ -157,6 +157,23 @@ describe('Signature utils', () => {
|
||||
expect(salt.isLessThan(twoPow256)).to.be.true();
|
||||
});
|
||||
});
|
||||
describe('#parseValidatorSignature', () => {
|
||||
const ethSignSignature =
|
||||
'0x1c3582f06356a1314dbf1c0e534c4d8e92e59b056ee607a7ff5a825f5f2cc5e6151c5cc7fdd420f5608e4d5bef108e42ad90c7a4b408caef32e24374cf387b0d7603';
|
||||
const validatorAddress = '0x63ac26ad9477d6be19a5fabe394bcc4886057c53';
|
||||
const signature = `${ethSignSignature}${validatorAddress.substr(2)}05`;
|
||||
it('throws if signature type is not Validator type signature', () => {
|
||||
expect(signatureUtils.parseValidatorSignature.bind(null, ethSignSignature)).to.throw(
|
||||
'Unexpected signatureType: 3. Valid signature types: 5',
|
||||
);
|
||||
});
|
||||
it('extracts signature and validator address', () => {
|
||||
const validatorSignature = signatureUtils.parseValidatorSignature(signature);
|
||||
|
||||
expect(validatorSignature.validatorAddress).to.equal(validatorAddress);
|
||||
expect(validatorSignature.signature).to.equal(ethSignSignature);
|
||||
});
|
||||
});
|
||||
describe('#ecSignOrderAsync', () => {
|
||||
it('should default to eth_sign if eth_signTypedData is unavailable', async () => {
|
||||
const expectedSignature =
|
||||
|
||||
Reference in New Issue
Block a user