EP: Add LibSignature library (#21)
* `@0x/contracts-zero-ex`: Add `LibSignature` library * `@0x/contracts-zero-ex`: Update package.json scripts Co-authored-by: Lawrence Forman <me@merklejerk.com>
This commit is contained in:
@@ -51,6 +51,7 @@ import * as LibOwnableStorage from '../test/generated-artifacts/LibOwnableStorag
|
||||
import * as LibProxyRichErrors from '../test/generated-artifacts/LibProxyRichErrors.json';
|
||||
import * as LibProxyStorage from '../test/generated-artifacts/LibProxyStorage.json';
|
||||
import * as LibReentrancyGuardStorage from '../test/generated-artifacts/LibReentrancyGuardStorage.json';
|
||||
import * as LibSignature from '../test/generated-artifacts/LibSignature.json';
|
||||
import * as LibSignatureRichErrors from '../test/generated-artifacts/LibSignatureRichErrors.json';
|
||||
import * as LibSignedCallData from '../test/generated-artifacts/LibSignedCallData.json';
|
||||
import * as LibSimpleFunctionRegistryRichErrors from '../test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json';
|
||||
@@ -90,6 +91,7 @@ import * as TestFillQuoteTransformerExchange from '../test/generated-artifacts/T
|
||||
import * as TestFillQuoteTransformerHost from '../test/generated-artifacts/TestFillQuoteTransformerHost.json';
|
||||
import * as TestFullMigration from '../test/generated-artifacts/TestFullMigration.json';
|
||||
import * as TestInitialMigration from '../test/generated-artifacts/TestInitialMigration.json';
|
||||
import * as TestLibSignature from '../test/generated-artifacts/TestLibSignature.json';
|
||||
import * as TestLibTokenSpender from '../test/generated-artifacts/TestLibTokenSpender.json';
|
||||
import * as TestMetaTransactionsTransformERC20Feature from '../test/generated-artifacts/TestMetaTransactionsTransformERC20Feature.json';
|
||||
import * as TestMigrator from '../test/generated-artifacts/TestMigrator.json';
|
||||
@@ -153,6 +155,7 @@ export const artifacts = {
|
||||
TokenSpenderFeature: TokenSpenderFeature as ContractArtifact,
|
||||
TransformERC20Feature: TransformERC20Feature as ContractArtifact,
|
||||
UniswapFeature: UniswapFeature as ContractArtifact,
|
||||
LibSignature: LibSignature as ContractArtifact,
|
||||
LibSignedCallData: LibSignedCallData as ContractArtifact,
|
||||
LibTokenSpender: LibTokenSpender as ContractArtifact,
|
||||
FixinCommon: FixinCommon as ContractArtifact,
|
||||
@@ -208,6 +211,7 @@ export const artifacts = {
|
||||
TestFillQuoteTransformerHost: TestFillQuoteTransformerHost as ContractArtifact,
|
||||
TestFullMigration: TestFullMigration as ContractArtifact,
|
||||
TestInitialMigration: TestInitialMigration as ContractArtifact,
|
||||
TestLibSignature: TestLibSignature as ContractArtifact,
|
||||
TestLibTokenSpender: TestLibTokenSpender as ContractArtifact,
|
||||
TestMetaTransactionsTransformERC20Feature: TestMetaTransactionsTransformERC20Feature as ContractArtifact,
|
||||
TestMigrator: TestMigrator as ContractArtifact,
|
||||
|
||||
98
contracts/zero-ex/test/lib_signature_test.ts
Normal file
98
contracts/zero-ex/test/lib_signature_test.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { blockchainTests, expect } from '@0x/contracts-test-utils';
|
||||
import { hexUtils } from '@0x/utils';
|
||||
import * as ethjs from 'ethereumjs-util';
|
||||
|
||||
import { SignatureValidationError, SignatureValidationErrorCodes } from '../src/revert_errors';
|
||||
import { eip712SignHashWithKey, ethSignHashWithKey, SignatureType } from '../src/signature_utils';
|
||||
|
||||
import { artifacts } from './artifacts';
|
||||
import { TestLibSignatureContract } from './wrappers';
|
||||
|
||||
const EMPTY_REVERT = 'reverted with no data';
|
||||
|
||||
blockchainTests.resets('LibSignature library', env => {
|
||||
let testLib: TestLibSignatureContract;
|
||||
let signerKey: string;
|
||||
let signer: string;
|
||||
|
||||
before(async () => {
|
||||
signerKey = hexUtils.random();
|
||||
signer = ethjs.bufferToHex(ethjs.privateToAddress(ethjs.toBuffer(signerKey)));
|
||||
testLib = await TestLibSignatureContract.deployFrom0xArtifactAsync(
|
||||
artifacts.TestLibSignature,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
});
|
||||
|
||||
describe('getSignerOfHash()', () => {
|
||||
it('can recover the signer of an EIP712 signature', async () => {
|
||||
const hash = hexUtils.random();
|
||||
const sig = eip712SignHashWithKey(hash, signerKey);
|
||||
const recovered = await testLib.getSignerOfHash(hash, sig).callAsync();
|
||||
expect(recovered).to.eq(signer);
|
||||
});
|
||||
|
||||
it('can recover the signer of an EthSign signature', async () => {
|
||||
const hash = hexUtils.random();
|
||||
const sig = ethSignHashWithKey(hash, signerKey);
|
||||
const recovered = await testLib.getSignerOfHash(hash, sig).callAsync();
|
||||
expect(recovered).to.eq(signer);
|
||||
});
|
||||
|
||||
it('throws if the signature type is out of range', async () => {
|
||||
const hash = hexUtils.random();
|
||||
const badType = (Object.values(SignatureType).slice(-1)[0] as number) + 1;
|
||||
const sig = {
|
||||
...ethSignHashWithKey(hash, signerKey),
|
||||
signatureType: badType,
|
||||
};
|
||||
return expect(testLib.getSignerOfHash(hash, sig).callAsync()).to.be.rejectedWith(EMPTY_REVERT);
|
||||
});
|
||||
|
||||
it('throws if the signature data is malformed', async () => {
|
||||
const hash = hexUtils.random();
|
||||
const sig = {
|
||||
...ethSignHashWithKey(hash, signerKey),
|
||||
v: 1,
|
||||
};
|
||||
return expect(testLib.getSignerOfHash(hash, sig).callAsync()).to.revertWith(
|
||||
new SignatureValidationError(SignatureValidationErrorCodes.BadSignatureData, hash),
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if an EC value is out of range', async () => {
|
||||
const hash = hexUtils.random();
|
||||
const sig = {
|
||||
...ethSignHashWithKey(hash, signerKey),
|
||||
r: '0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141',
|
||||
};
|
||||
return expect(testLib.getSignerOfHash(hash, sig).callAsync()).to.revertWith(
|
||||
new SignatureValidationError(SignatureValidationErrorCodes.BadSignatureData, hash),
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if the type is Illegal', async () => {
|
||||
const hash = hexUtils.random();
|
||||
const sig = {
|
||||
...ethSignHashWithKey(hash, signerKey),
|
||||
signatureType: SignatureType.Illegal,
|
||||
};
|
||||
return expect(testLib.getSignerOfHash(hash, sig).callAsync()).to.revertWith(
|
||||
new SignatureValidationError(SignatureValidationErrorCodes.Illegal, hash),
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if the type is Invalid', async () => {
|
||||
const hash = hexUtils.random();
|
||||
const sig = {
|
||||
...ethSignHashWithKey(hash, signerKey),
|
||||
signatureType: SignatureType.Invalid,
|
||||
};
|
||||
return expect(testLib.getSignerOfHash(hash, sig).callAsync()).to.revertWith(
|
||||
new SignatureValidationError(SignatureValidationErrorCodes.AlwaysInvalid, hash),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -49,6 +49,7 @@ export * from '../test/generated-wrappers/lib_ownable_storage';
|
||||
export * from '../test/generated-wrappers/lib_proxy_rich_errors';
|
||||
export * from '../test/generated-wrappers/lib_proxy_storage';
|
||||
export * from '../test/generated-wrappers/lib_reentrancy_guard_storage';
|
||||
export * from '../test/generated-wrappers/lib_signature';
|
||||
export * from '../test/generated-wrappers/lib_signature_rich_errors';
|
||||
export * from '../test/generated-wrappers/lib_signed_call_data';
|
||||
export * from '../test/generated-wrappers/lib_simple_function_registry_rich_errors';
|
||||
@@ -88,6 +89,7 @@ export * from '../test/generated-wrappers/test_fill_quote_transformer_exchange';
|
||||
export * from '../test/generated-wrappers/test_fill_quote_transformer_host';
|
||||
export * from '../test/generated-wrappers/test_full_migration';
|
||||
export * from '../test/generated-wrappers/test_initial_migration';
|
||||
export * from '../test/generated-wrappers/test_lib_signature';
|
||||
export * from '../test/generated-wrappers/test_lib_token_spender';
|
||||
export * from '../test/generated-wrappers/test_meta_transactions_transform_erc20_feature';
|
||||
export * from '../test/generated-wrappers/test_migrator';
|
||||
|
||||
Reference in New Issue
Block a user