aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/0x.js.ts14
-rw-r--r--src/contract_wrappers/exchange_wrapper.ts4
-rw-r--r--src/utils/utils.ts16
-rw-r--r--test/exchange_wrapper_test.ts34
4 files changed, 40 insertions, 28 deletions
diff --git a/src/0x.js.ts b/src/0x.js.ts
index 8f1178b2a..f275d9fbd 100644
--- a/src/0x.js.ts
+++ b/src/0x.js.ts
@@ -40,19 +40,7 @@ export class ZeroEx {
assert.doesConformToSchema('signature', signature, ecSignatureSchema);
assert.isETHAddressHex('signerAddressHex', signerAddressHex);
- const dataBuff = ethUtil.toBuffer(dataHex);
- const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
- try {
- const pubKey = ethUtil.ecrecover(
- msgHashBuff,
- signature.v,
- ethUtil.toBuffer(signature.r),
- ethUtil.toBuffer(signature.s));
- const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
- return retrievedAddress === signerAddressHex;
- } catch (err) {
- return false;
- }
+ return utils.isValidSignature(dataHex, signature, signerAddressHex);
}
/**
* Generates pseudo-random 256 bit salt.
diff --git a/src/contract_wrappers/exchange_wrapper.ts b/src/contract_wrappers/exchange_wrapper.ts
index d144d8aad..5b5d1e914 100644
--- a/src/contract_wrappers/exchange_wrapper.ts
+++ b/src/contract_wrappers/exchange_wrapper.ts
@@ -70,8 +70,8 @@ export class ExchangeWrapper extends ContractWrapper {
await this.stopWatchingExchangeLogEventsAsync();
delete this.exchangeContractIfExists;
}
- public async isValidSignatureAsync(dataHex: string, ecSignature: ECSignature,
- signerAddressHex: string): Promise<boolean> {
+ private async isValidSignatureUsingContractCallAsync(dataHex: string, ecSignature: ECSignature,
+ signerAddressHex: string): Promise<boolean> {
assert.isHexString('dataHex', dataHex);
assert.doesConformToSchema('ecSignature', ecSignature, ecSignatureSchema);
assert.isETHAddressHex('signerAddressHex', signerAddressHex);
diff --git a/src/utils/utils.ts b/src/utils/utils.ts
index 5786bab07..ea3d8c7e1 100644
--- a/src/utils/utils.ts
+++ b/src/utils/utils.ts
@@ -4,6 +4,7 @@ import * as ethABI from 'ethereumjs-abi';
import * as ethUtil from 'ethereumjs-util';
import {Order, SignedOrder, SolidityTypes} from '../types';
import * as BigNumber from 'bignumber.js';
+import {ECSignature} from '../types';
export const utils = {
/**
@@ -50,6 +51,21 @@ export const utils = {
const hashHex = ethUtil.bufferToHex(hashBuff);
return hashHex;
},
+ isValidSignature(dataHex: string, signature: ECSignature, signerAddressHex: string): boolean {
+ const dataBuff = ethUtil.toBuffer(dataHex);
+ const msgHashBuff = ethUtil.hashPersonalMessage(dataBuff);
+ try {
+ const pubKey = ethUtil.ecrecover(
+ msgHashBuff,
+ signature.v,
+ ethUtil.toBuffer(signature.r),
+ ethUtil.toBuffer(signature.s));
+ const retrievedAddress = ethUtil.bufferToHex(ethUtil.pubToAddress(pubKey));
+ return retrievedAddress === signerAddressHex;
+ } catch (err) {
+ return false;
+ }
+ },
getCurrentUnixTimestamp(): BigNumber.BigNumber {
return new BigNumber(Date.now() / 1000);
},
diff --git a/test/exchange_wrapper_test.ts b/test/exchange_wrapper_test.ts
index 08936f1d2..aed3c3c0b 100644
--- a/test/exchange_wrapper_test.ts
+++ b/test/exchange_wrapper_test.ts
@@ -51,7 +51,7 @@ describe('ExchangeWrapper', () => {
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
- describe('#isValidSignatureAsync', () => {
+ describe('#isValidSignatureUsingContractCallAsync', () => {
// The Exchange smart contract `isValidSignature` method only validates orderHashes and assumes
// the length of the data is exactly 32 bytes. Thus for these tests, we use data of this size.
const dataHex = '0x6927e990021d23b1eb7b8789f6a6feaf98fe104bb0cf8259421b79f9a34222b0';
@@ -68,8 +68,9 @@ describe('ExchangeWrapper', () => {
r: signature.r,
s: signature.s,
};
- return expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address))
- .to.be.rejected();
+ return expect((zeroEx.exchange as any)
+ .isValidSignatureUsingContractCallAsync(dataHex, malformedSignature, address),
+ ).to.be.rejected();
});
it('r lacks 0x prefix', async () => {
const malformedR = signature.r.replace('0x', '');
@@ -78,8 +79,9 @@ describe('ExchangeWrapper', () => {
r: malformedR,
s: signature.s,
};
- return expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address))
- .to.be.rejected();
+ return expect((zeroEx.exchange as any)
+ .isValidSignatureUsingContractCallAsync(dataHex, malformedSignature, address),
+ ).to.be.rejected();
});
it('r is too short', async () => {
const malformedR = signature.r.substr(10);
@@ -88,8 +90,9 @@ describe('ExchangeWrapper', () => {
r: malformedR,
s: signature.s.replace('0', 'z'),
};
- return expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address))
- .to.be.rejected();
+ return expect((zeroEx.exchange as any)
+ .isValidSignatureUsingContractCallAsync(dataHex, malformedSignature, address),
+ ).to.be.rejected();
});
it('s is not hex', async () => {
const malformedS = signature.s.replace('0', 'z');
@@ -98,26 +101,31 @@ describe('ExchangeWrapper', () => {
r: signature.r,
s: malformedS,
};
- return expect(zeroEx.exchange.isValidSignatureAsync(dataHex, malformedSignature, address))
- .to.be.rejected();
+ return expect((zeroEx.exchange as any)
+ .isValidSignatureUsingContractCallAsync(dataHex, malformedSignature, address),
+ ).to.be.rejected();
});
});
it('should return false if the data doesn\'t pertain to the signature & address', async () => {
- const isValid = await zeroEx.exchange.isValidSignatureAsync('0x0', signature, address);
+ const isValid = await (zeroEx.exchange as any)
+ .isValidSignatureUsingContractCallAsync('0x0', signature, address);
expect(isValid).to.be.false();
});
it('should return false if the address doesn\'t pertain to the signature & dataHex', async () => {
const validUnrelatedAddress = '0x8b0292B11a196601eD2ce54B665CaFEca0347D42';
- const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, signature, validUnrelatedAddress);
+ const isValid = await (zeroEx.exchange as any)
+ .isValidSignatureUsingContractCallAsync(dataHex, signature, validUnrelatedAddress);
expect(isValid).to.be.false();
});
it('should return false if the signature doesn\'t pertain to the dataHex & address', async () => {
const wrongSignature = {...signature, v: 28};
- const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, wrongSignature, address);
+ const isValid = await (zeroEx.exchange as any)
+ .isValidSignatureUsingContractCallAsync(dataHex, wrongSignature, address);
expect(isValid).to.be.false();
});
it('should return true if the signature does pertain to the dataHex & address', async () => {
- const isValid = await zeroEx.exchange.isValidSignatureAsync(dataHex, signature, address);
+ const isValid = await (zeroEx.exchange as any)
+ .isValidSignatureUsingContractCallAsync(dataHex, signature, address);
expect(isValid).to.be.true();
});
});