diff --git a/contracts/tec/compiler.json b/contracts/tec/compiler.json index b791a6ac92..ffa41c6ed7 100644 --- a/contracts/tec/compiler.json +++ b/contracts/tec/compiler.json @@ -16,5 +16,5 @@ } } }, - "contracts": ["TEC", "TestLibs", "MixinSignatureValidator"] + "contracts": ["src/MixinSignatureValidator.sol", "src/TEC.sol", "test/TestLibs.sol"] } diff --git a/contracts/tec/package.json b/contracts/tec/package.json index 9e17b2396d..65aa11483a 100644 --- a/contracts/tec/package.json +++ b/contracts/tec/package.json @@ -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" }, diff --git a/contracts/tec/src/artifacts.ts b/contracts/tec/src/artifacts.ts new file mode 100644 index 0000000000..43340f831f --- /dev/null +++ b/contracts/tec/src/artifacts.ts @@ -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, +}; diff --git a/contracts/tec/src/artifacts/index.ts b/contracts/tec/src/artifacts/index.ts deleted file mode 100644 index 95e501d12b..0000000000 --- a/contracts/tec/src/artifacts/index.ts +++ /dev/null @@ -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, -}; diff --git a/contracts/tec/src/wrappers.ts b/contracts/tec/src/wrappers.ts new file mode 100644 index 0000000000..0fff57ed58 --- /dev/null +++ b/contracts/tec/src/wrappers.ts @@ -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'; diff --git a/contracts/tec/src/wrappers/index.ts b/contracts/tec/src/wrappers/index.ts deleted file mode 100644 index 719d3182eb..0000000000 --- a/contracts/tec/src/wrappers/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from '../../generated-wrappers/tec'; -export * from '../../generated-wrappers/test_libs'; -export * from '../../generated-wrappers/test_internals'; diff --git a/contracts/tec/test/internals.ts b/contracts/tec/test/internals.ts deleted file mode 100644 index 791e0d3259..0000000000 --- a/contracts/tec/test/internals.ts +++ /dev/null @@ -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); - }); - }); -}); diff --git a/contracts/tec/test/mixins.ts b/contracts/tec/test/mixins.ts new file mode 100644 index 0000000000..c7e75d6063 --- /dev/null +++ b/contracts/tec/test/mixins.ts @@ -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, + ); + }); + }); +}); diff --git a/contracts/tec/test/utils/index.ts b/contracts/tec/test/utils/index.ts index c7fbfbe109..595702c89e 100644 --- a/contracts/tec/test/utils/index.ts +++ b/contracts/tec/test/utils/index.ts @@ -1 +1,3 @@ export { approvalHashUtils } from './approval_hash'; +export { TECTransactionFactory } from './tec_transaction_factory'; +export * from './types'; diff --git a/contracts/tec/test/utils/tec_transaction_factory.ts b/contracts/tec/test/utils/tec_transaction_factory.ts new file mode 100644 index 0000000000..ea17a53133 --- /dev/null +++ b/contracts/tec/test/utils/tec_transaction_factory.ts @@ -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; + } +} diff --git a/contracts/tec/test/utils/types.ts b/contracts/tec/test/utils/types.ts index 3e32b8fbe2..499e64cc80 100644 --- a/contracts/tec/test/utils/types.ts +++ b/contracts/tec/test/utils/types.ts @@ -5,3 +5,10 @@ export interface TECApproval { transactionSignature: string; approvalExpirationTimeSeconds: BigNumber; } + +export enum TECSignatureType { + Illegal, + EIP712, + EthSign, + NSignatureTypes, +} diff --git a/contracts/tec/tsconfig.json b/contracts/tec/tsconfig.json index 4d7f4a8efd..b33be974cb 100644 --- a/contracts/tec/tsconfig.json +++ b/contracts/tec/tsconfig.json @@ -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"] }