Add signature validator tests

This commit is contained in:
Amir Bandeali 2019-02-13 14:13:32 -08:00
parent 99aeaddf42
commit bebcd99b3b
12 changed files with 174 additions and 80 deletions

View File

@ -16,5 +16,5 @@
}
}
},
"contracts": ["TEC", "TestLibs", "MixinSignatureValidator"]
"contracts": ["src/MixinSignatureValidator.sol", "src/TEC.sol", "test/TestLibs.sol"]
}

View File

@ -33,7 +33,8 @@
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
},
"config": {
"abis": "generated-artifacts/@(TEC|TestLibs|TestInternals).json"
"abis": "./generated-artifacts/@(MixinSignatureValidator|TEC|TestLibs).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {
"type": "git",
@ -78,6 +79,7 @@
"@0x/typescript-typings": "^4.0.0",
"@0x/utils": "^4.1.0",
"@0x/web3-wrapper": "^5.0.0",
"ethereumjs-util": "^5.1.1",
"ethereum-types": "^2.0.0",
"lodash": "^4.17.11"
},

View File

@ -0,0 +1,15 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
import { ContractArtifact } from 'ethereum-types';
import * as MixinSignatureValidator from '../generated-artifacts/MixinSignatureValidator.json';
import * as TEC from '../generated-artifacts/TEC.json';
import * as TestLibs from '../generated-artifacts/TestLibs.json';
export const artifacts = {
TEC: TEC as ContractArtifact,
TestLibs: TestLibs as ContractArtifact,
MixinSignatureValidator: MixinSignatureValidator as ContractArtifact,
};

View File

@ -1,11 +0,0 @@
import { ContractArtifact } from 'ethereum-types';
import * as TEC from '../../generated-artifacts/TEC.json';
import * as TestInternals from '../../generated-artifacts/TestInternals.json';
import * as TestLibs from '../../generated-artifacts/TestLibs.json';
export const artifacts = {
TEC: TEC as ContractArtifact,
TestLibs: TestLibs as ContractArtifact,
TestInternals: TestInternals as ContractArtifact,
};

View File

@ -0,0 +1,8 @@
/*
* -----------------------------------------------------------------------------
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../generated-wrappers/mixin_signature_validator';
export * from '../generated-wrappers/tec';
export * from '../generated-wrappers/test_libs';

View File

@ -1,3 +0,0 @@
export * from '../../generated-wrappers/tec';
export * from '../../generated-wrappers/test_libs';
export * from '../../generated-wrappers/test_internals';

View File

@ -1,56 +0,0 @@
import { chaiSetup, constants, provider, TransactionFactory, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { transactionHashUtils } from '@0x/order-utils';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { artifacts, TestInternalsContract } from '../src';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Internals tests', () => {
let transactionSignerAddress: string;
let approvalSignerAddress: string;
let testInternals: TestInternalsContract;
let transactionFactory: TransactionFactory;
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
testInternals = await TestInternalsContract.deployFrom0xArtifactAsync(
artifacts.TestInternals,
provider,
txDefaults,
);
const accounts = await web3Wrapper.getAvailableAddressesAsync();
[transactionSignerAddress, approvalSignerAddress] = accounts.slice(0, 2);
const transactionSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[0];
const approvalSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[1];
transactionFactory = new TransactionFactory(transactionSignerPrivateKey, testInternals.address);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('getSignerAddress', () => {
it('should return the correct address', async () => {
const data = constants.NULL_BYTES;
const transaction = transactionFactory.newSignedTransaction(data);
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
const signerAddress = await testInternals.publicGetSignerAddress.callAsync(
transactionHash,
transaction.signature,
);
expect(transaction.signerAddress).to.eq(signerAddress);
});
});
});

View File

@ -0,0 +1,103 @@
import {
chaiSetup,
constants,
expectContractCallFailedAsync,
provider,
txDefaults,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { transactionHashUtils } from '@0x/order-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import * as ethUtil from 'ethereumjs-util';
import { artifacts, MixinSignatureValidatorContract, TECSignatureType, TECTransactionFactory } from '../src';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Mixins tests', () => {
let transactionSignerAddress: string;
let approvalSignerAddress: string;
let signatureValidator: MixinSignatureValidatorContract;
let transactionFactory: TECTransactionFactory;
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
signatureValidator = await MixinSignatureValidatorContract.deployFrom0xArtifactAsync(
artifacts.MixinSignatureValidator,
provider,
txDefaults,
);
const accounts = await web3Wrapper.getAvailableAddressesAsync();
[transactionSignerAddress, approvalSignerAddress] = accounts.slice(0, 2);
const transactionSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[0];
const approvalSignerPrivateKey = constants.TESTRPC_PRIVATE_KEYS[1];
transactionFactory = new TECTransactionFactory(transactionSignerPrivateKey, signatureValidator.address);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('getSignerAddress', () => {
it('should return the correct address using the EthSign signature type', async () => {
const data = constants.NULL_BYTES;
const transaction = transactionFactory.newSignedTECTransaction(data, TECSignatureType.EthSign);
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
const signerAddress = await signatureValidator.getSignerAddress.callAsync(
transactionHash,
transaction.signature,
);
expect(transaction.signerAddress).to.eq(signerAddress);
});
it('should return the correct address using the EIP712 signature type', async () => {
const data = constants.NULL_BYTES;
const transaction = transactionFactory.newSignedTECTransaction(data, TECSignatureType.EIP712);
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
const signerAddress = await signatureValidator.getSignerAddress.callAsync(
transactionHash,
transaction.signature,
);
expect(transaction.signerAddress).to.eq(signerAddress);
});
it('should revert with with the Illegal signature type', async () => {
const data = constants.NULL_BYTES;
const transaction = transactionFactory.newSignedTECTransaction(data);
const illegalSignatureByte = ethUtil.toBuffer(TECSignatureType.Illegal).toString('hex');
transaction.signature = `${transaction.signature.slice(
0,
transaction.signature.length - 2,
)}${illegalSignatureByte}`;
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
expectContractCallFailedAsync(
signatureValidator.getSignerAddress.callAsync(transactionHash, transaction.signature),
RevertReason.SignatureIllegal,
);
});
it("should revert with with a signature type that doesn't exist", async () => {
const data = constants.NULL_BYTES;
const transaction = transactionFactory.newSignedTECTransaction(data);
const invalidSignatureByte = '03';
transaction.signature = `${transaction.signature.slice(
0,
transaction.signature.length - 2,
)}${invalidSignatureByte}`;
const transactionHash = transactionHashUtils.getTransactionHashHex(transaction);
expectContractCallFailedAsync(
signatureValidator.getSignerAddress.callAsync(transactionHash, transaction.signature),
RevertReason.SignatureUnsupported,
);
});
});
});

View File

@ -1 +1,3 @@
export { approvalHashUtils } from './approval_hash';
export { TECTransactionFactory } from './tec_transaction_factory';
export * from './types';

View File

@ -0,0 +1,31 @@
import { TransactionFactory } from '@0x/contracts-test-utils';
import { SignatureType, SignedZeroExTransaction } from '@0x/types';
import * as ethUtil from 'ethereumjs-util';
import { TECSignatureType } from './types';
export class TECTransactionFactory extends TransactionFactory {
constructor(privateKey: Buffer, exchangeAddress: string) {
super(privateKey, exchangeAddress);
}
public newSignedTECTransaction(
data: string,
signatureType: TECSignatureType = TECSignatureType.EthSign,
): SignedZeroExTransaction {
let exchangeSignatureType;
if (signatureType === TECSignatureType.EthSign) {
exchangeSignatureType = SignatureType.EthSign;
} else if (signatureType === TECSignatureType.EIP712) {
exchangeSignatureType = SignatureType.EIP712;
} else {
throw new Error(`Error: ${signatureType} not a valid signature type`);
}
const signedTransaction = super.newSignedTransaction(data, exchangeSignatureType);
const tecSignatureTypeByte = ethUtil.toBuffer(signatureType).toString('hex');
signedTransaction.signature = `${signedTransaction.signature.slice(
0,
signedTransaction.signature.length - 2,
)}${tecSignatureTypeByte}`;
return signedTransaction;
}
}

View File

@ -5,3 +5,10 @@ export interface TECApproval {
transactionSignature: string;
approvalExpirationTimeSeconds: BigNumber;
}
export enum TECSignatureType {
Illegal,
EIP712,
EthSign,
NSignatureTypes,
}

View File

@ -1,15 +1,11 @@
{
"extends": "../../tsconfig",
"compilerOptions": {
"outDir": "lib",
"rootDir": ".",
"resolveJsonModule": true
},
"compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
"include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
"files": [
"./generated-artifacts/TEC.json",
"./generated-artifacts/TestLibs.json",
"./generated-artifacts/TestInternals.json"
"generated-artifacts/MixinSignatureValidator.json",
"generated-artifacts/TEC.json",
"generated-artifacts/TestLibs.json"
],
"exclude": ["./deploy/solc/solc_bin"]
}