diff options
-rw-r--r-- | packages/migrations/artifacts/2.0.0/IValidator.json | 76 | ||||
-rw-r--r-- | packages/migrations/artifacts/2.0.0/IWallet.json | 72 | ||||
-rw-r--r-- | packages/migrations/compiler.json | 3 | ||||
-rw-r--r-- | packages/migrations/package.json | 2 | ||||
-rw-r--r-- | packages/order-utils/package.json | 4 | ||||
-rw-r--r-- | packages/order-utils/src/artifacts.ts | 6 | ||||
-rw-r--r-- | packages/order-utils/src/signature_utils.ts | 42 |
7 files changed, 196 insertions, 9 deletions
diff --git a/packages/migrations/artifacts/2.0.0/IValidator.json b/packages/migrations/artifacts/2.0.0/IValidator.json new file mode 100644 index 000000000..dcc08aa40 --- /dev/null +++ b/packages/migrations/artifacts/2.0.0/IValidator.json @@ -0,0 +1,76 @@ +{ + "schemaVersion": "2.0.0", + "contractName": "IValidator", + "compilerOutput": { + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "hash", + "type": "bytes32" + }, + { + "name": "signer", + "type": "address" + }, + { + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "name": "isValid", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "0x", + "opcodes": "", + "sourceMap": "" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": "0x", + "opcodes": "", + "sourceMap": "" + } + } + }, + "sources": { + "current/protocol/Exchange/interfaces/IValidator.sol": { + "id": 0 + } + }, + "sourceCodes": { + "current/protocol/Exchange/interfaces/IValidator.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.23;\n\ncontract IValidator {\n\n /// @dev Verifies that a signature is valid.\n /// @param hash Message hash that is signed.\n /// @param signer Address that should have signed the given hash.\n /// @param signature Proof of signing.\n /// @return Validity of order signature.\n function isValidSignature(\n bytes32 hash,\n address signer,\n bytes signature\n )\n external\n view\n returns (bool isValid);\n}\n" + }, + "sourceTreeHashHex": "0x2db97becd6f94a55648dce974f3aa4cfa0cd2e3209d2ed1b75cc50dbe4bf35ae", + "compiler": { + "name": "solc", + "version": "soljson-v0.4.24+commit.e67f0147.js", + "settings": { + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap" + ] + } + } + } + }, + "networks": {} +}
\ No newline at end of file diff --git a/packages/migrations/artifacts/2.0.0/IWallet.json b/packages/migrations/artifacts/2.0.0/IWallet.json new file mode 100644 index 000000000..4f92368ec --- /dev/null +++ b/packages/migrations/artifacts/2.0.0/IWallet.json @@ -0,0 +1,72 @@ +{ + "schemaVersion": "2.0.0", + "contractName": "IWallet", + "compilerOutput": { + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "hash", + "type": "bytes32" + }, + { + "name": "signature", + "type": "bytes" + } + ], + "name": "isValidSignature", + "outputs": [ + { + "name": "isValid", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "evm": { + "bytecode": { + "linkReferences": {}, + "object": "0x", + "opcodes": "", + "sourceMap": "" + }, + "deployedBytecode": { + "linkReferences": {}, + "object": "0x", + "opcodes": "", + "sourceMap": "" + } + } + }, + "sources": { + "current/protocol/Exchange/interfaces/IWallet.sol": { + "id": 0 + } + }, + "sourceCodes": { + "current/protocol/Exchange/interfaces/IWallet.sol": "/*\n\n Copyright 2018 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma solidity ^0.4.24;\n\ncontract IWallet {\n\n /// @dev Verifies that a signature is valid.\n /// @param hash Message hash that is signed.\n /// @param signature Proof of signing.\n /// @return Validity of order signature.\n function isValidSignature(\n bytes32 hash,\n bytes signature\n )\n external\n view\n returns (bool isValid);\n}\n" + }, + "sourceTreeHashHex": "0x86b701eae05b54e6e83ae81e518db9b84b28a8d6c33c8b5ae8a89ff78c61f732", + "compiler": { + "name": "solc", + "version": "soljson-v0.4.24+commit.e67f0147.js", + "settings": { + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode.object", + "evm.bytecode.sourceMap", + "evm.deployedBytecode.object", + "evm.deployedBytecode.sourceMap" + ] + } + } + } + }, + "networks": {} +}
\ No newline at end of file diff --git a/packages/migrations/compiler.json b/packages/migrations/compiler.json index 782b939dc..c64e5b229 100644 --- a/packages/migrations/compiler.json +++ b/packages/migrations/compiler.json @@ -11,7 +11,8 @@ "MultiSigWalletWithTimeLock", "MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress", "TokenRegistry", - "ISigner" + "IWallet", + "IValidator" ], "compilerSettings": { "outputSelection": { diff --git a/packages/migrations/package.json b/packages/migrations/package.json index ebef2dfb4..b8137cab9 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -30,7 +30,7 @@ "v1": "artifacts/1.0.0/@(DummyERC20Token|TokenTransferProxy_v1|Exchange_v1|TokenRegistry|MultiSigWallet|MultiSigWalletWithTimeLock|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|TokenRegistry|ZRXToken|WETH9).json", "v2": - "artifacts/2.0.0/@(DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|ZRXToken|WETH9|ISigner).json" + "artifacts/2.0.0/@(DummyERC20Token|DummyERC721Token|ERC20Proxy|ERC721Proxy|Exchange|MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress|ZRXToken|WETH9|IWallet|IValidator).json" } }, "license": "Apache-2.0", diff --git a/packages/order-utils/package.json b/packages/order-utils/package.json index 50f7e7c14..9ed53e4b0 100644 --- a/packages/order-utils/package.json +++ b/packages/order-utils/package.json @@ -11,7 +11,7 @@ "watch": "tsc -w", "prebuild": "run-s clean update_artifacts generate_contract_wrappers", "build": "tsc && copyfiles -u 3 './lib/src/monorepo_scripts/**/*' ./scripts", - "generate_contract_wrappers": "abi-gen --abis 'lib/src/artifacts/@(Exchange|ISigner).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'", + "generate_contract_wrappers": "abi-gen --abis 'lib/src/artifacts/@(Exchange|IWallet|IValidator).json' --template ../contract_templates/contract.handlebars --partials '../contract_templates/partials/**/*.handlebars' --output src/generated_contract_wrappers --backend ethers && prettier --write 'src/generated_contract_wrappers/**.ts'", "update_artifacts": "for i in ${npm_package_config_contracts}; do copyfiles -u 4 ../migrations/artifacts/2.0.0/$i.json lib/src/artifacts; done;", "test": "run-s build run_mocha", "test:circleci": "yarn test:coverage", @@ -26,7 +26,7 @@ "upload_docs_json": "aws s3 cp generated_docs/index.json $S3_URL --profile 0xproject --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers --content-type application/json" }, "config": { - "contracts": "ISigner Exchange", + "contracts": "IWallet IValidator Exchange", "postpublish": { "docPublishConfigs": { "extraFileIncludes": [ diff --git a/packages/order-utils/src/artifacts.ts b/packages/order-utils/src/artifacts.ts index 6eb5ad0c0..f6fd00472 100644 --- a/packages/order-utils/src/artifacts.ts +++ b/packages/order-utils/src/artifacts.ts @@ -1,8 +1,10 @@ import { Artifact } from '@0xproject/types'; import * as Exchange from './artifacts/Exchange.json'; -import * as ISigner from './artifacts/ISigner.json'; +import * as IValidator from './artifacts/IValidator.json'; +import * as IWallet from './artifacts/IWallet.json'; export const artifacts = { Exchange: (Exchange as any) as Artifact, - ISigner: (ISigner as any) as Artifact, + IWallet: (IWallet as any) as Artifact, + IValidator: (IValidator as any) as Artifact, }; diff --git a/packages/order-utils/src/signature_utils.ts b/packages/order-utils/src/signature_utils.ts index 8e387a6ae..427448260 100644 --- a/packages/order-utils/src/signature_utils.ts +++ b/packages/order-utils/src/signature_utils.ts @@ -7,7 +7,8 @@ import * as _ from 'lodash'; import { artifacts } from './artifacts'; import { assert } from './assert'; import { ExchangeContract } from './generated_contract_wrappers/exchange'; -import { ISignerContract } from './generated_contract_wrappers/i_signer'; +import { IWalletContract } from './generated_contract_wrappers/i_signer'; +import { IValidatorContract } from './generated_contract_wrappers/i_validator'; import { MessagePrefixOpts, MessagePrefixType, OrderError } from './types'; /** @@ -51,12 +52,27 @@ export async function isValidSignatureAsync( throw new Error('Caller signature type cannot be validated off-chain'); case SignatureType.Wallet: { - const signerContract = new ISignerContract(artifacts.ISigner.abi, signerAddress, provider); + const signerContract = new IWalletContract(artifacts.IWallet.abi, signerAddress, provider); const isValid = await signerContract.isValidSignature.callAsync(data, signature); return isValid; } - // TODO: Add SignatureType.Validator + case SignatureType.Validator: { + const validatorAddress = getValidatorAddressFromSignature(signature); + const exchangeContract = new ExchangeContract(artifacts.Exchange.abi, signerAddress, provider); + const isValidatorApproved = await exchangeContract.allowedValidators.callAsync( + signerAddress, + validatorAddress, + ); + if (!isValidatorApproved) { + throw new Error(`Validator ${validatorAddress} was not pre-approved by ${signerAddress}.`); + } + + const validatorSignature = getValidatorSignatureFromSignature(signature); + const validatorContract = new IValidatorContract(artifacts.IValidator.abi, signerAddress, provider); + const isValid = await validatorContract.isValidSignature.callAsync(data, signerAddress, validatorSignature); + return isValid; + } case SignatureType.PreSigned: { return isValidPresignedSignatureAsync(provider, data, signature, signerAddress); @@ -219,6 +235,26 @@ function parseECSignature(signature: string): ECSignature { return ecSignature; } +function getValidatorSignatureFromSignature(signature: string): string { + const signatureTypeIndex = getSignatureTypeIndexIfExists(signature); + if (signatureTypeIndex !== SignatureType.Validator) { + throw new Error('Cannot get validator address from non-validator signature'); + } + // tslint:disable-next-line:custom-no-magic-numbers + const validatorSignature = signature.slice(0, -22); + return validatorSignature; +} + +function getValidatorAddressFromSignature(signature: string): string { + const signatureTypeIndex = getSignatureTypeIndexIfExists(signature); + if (signatureTypeIndex !== SignatureType.Validator) { + throw new Error('Cannot get validator address from non-validator signature'); + } + // tslint:disable-next-line:custom-no-magic-numbers + const validatorAddress = signature.slice(-22, -2); + return `0x${validatorAddress}`; +} + function getSignatureTypeIndexIfExists(signature: string): number { const unprefixedSignature = ethUtil.stripHexPrefix(signature); // tslint:disable-next-line:custom-no-magic-numbers |