Added unit tests for LibEIP712
This commit is contained in:
parent
065f46a020
commit
f9292a8fb8
@ -42,6 +42,7 @@ export const constants = {
|
|||||||
NUM_ERC1155_FUNGIBLE_TOKENS_MINT: 4,
|
NUM_ERC1155_FUNGIBLE_TOKENS_MINT: 4,
|
||||||
NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT: 4,
|
NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT: 4,
|
||||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||||
|
NULL_BYTES32: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
|
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
|
||||||
TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)),
|
TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)),
|
||||||
INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
|
INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
"test/TestLibAddress.sol",
|
"test/TestLibAddress.sol",
|
||||||
"test/TestLibAddressArray.sol",
|
"test/TestLibAddressArray.sol",
|
||||||
"test/TestLibBytes.sol",
|
"test/TestLibBytes.sol",
|
||||||
|
"test/TestLibEIP712.sol",
|
||||||
"test/TestOwnable.sol",
|
"test/TestOwnable.sol",
|
||||||
"test/TestReentrancyGuard.sol",
|
"test/TestReentrancyGuard.sol",
|
||||||
"test/TestSafeMath.sol"
|
"test/TestSafeMath.sol"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright 2018 ZeroEx Intl.
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
52
contracts/utils/contracts/test/TestLibEIP712.sol
Normal file
52
contracts/utils/contracts/test/TestLibEIP712.sol
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
import "../src/LibEIP712.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestLibEIP712 is
|
||||||
|
LibEIP712
|
||||||
|
{
|
||||||
|
function externalHashEIP712DomainSeperator(
|
||||||
|
string calldata name,
|
||||||
|
string calldata version,
|
||||||
|
uint256 chainid,
|
||||||
|
address verifyingcontractaddress
|
||||||
|
)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (bytes32)
|
||||||
|
{
|
||||||
|
return _hashEIP712Domain(
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
chainid,
|
||||||
|
verifyingcontractaddress
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function externalHashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (bytes32)
|
||||||
|
{
|
||||||
|
return _hashEIP712Message(eip712DomainHash, hashStruct);
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,7 @@
|
|||||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis": "./generated-artifacts/@(IOwnable|LibAddress|LibBytes|LibEIP1271|LibEIP712|Ownable|ReentrancyGuard|SafeMath|TestConstants|TestLibAddress|TestLibAddressArray|TestLibBytes|TestOwnable|TestReentrancyGuard|TestSafeMath).json",
|
"abis": "./generated-artifacts/@(IOwnable|LibAddress|LibBytes|LibEIP1271|LibEIP712|Ownable|ReentrancyGuard|SafeMath|TestConstants|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestOwnable|TestReentrancyGuard|TestSafeMath).json",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -17,6 +17,7 @@ import * as TestConstants from '../generated-artifacts/TestConstants.json';
|
|||||||
import * as TestLibAddress from '../generated-artifacts/TestLibAddress.json';
|
import * as TestLibAddress from '../generated-artifacts/TestLibAddress.json';
|
||||||
import * as TestLibAddressArray from '../generated-artifacts/TestLibAddressArray.json';
|
import * as TestLibAddressArray from '../generated-artifacts/TestLibAddressArray.json';
|
||||||
import * as TestLibBytes from '../generated-artifacts/TestLibBytes.json';
|
import * as TestLibBytes from '../generated-artifacts/TestLibBytes.json';
|
||||||
|
import * as TestLibEIP712 from '../generated-artifacts/TestLibEIP712.json';
|
||||||
import * as TestOwnable from '../generated-artifacts/TestOwnable.json';
|
import * as TestOwnable from '../generated-artifacts/TestOwnable.json';
|
||||||
import * as TestReentrancyGuard from '../generated-artifacts/TestReentrancyGuard.json';
|
import * as TestReentrancyGuard from '../generated-artifacts/TestReentrancyGuard.json';
|
||||||
import * as TestSafeMath from '../generated-artifacts/TestSafeMath.json';
|
import * as TestSafeMath from '../generated-artifacts/TestSafeMath.json';
|
||||||
@ -33,6 +34,7 @@ export const artifacts = {
|
|||||||
TestLibAddress: TestLibAddress as ContractArtifact,
|
TestLibAddress: TestLibAddress as ContractArtifact,
|
||||||
TestLibAddressArray: TestLibAddressArray as ContractArtifact,
|
TestLibAddressArray: TestLibAddressArray as ContractArtifact,
|
||||||
TestLibBytes: TestLibBytes as ContractArtifact,
|
TestLibBytes: TestLibBytes as ContractArtifact,
|
||||||
|
TestLibEIP712: TestLibEIP712 as ContractArtifact,
|
||||||
TestOwnable: TestOwnable as ContractArtifact,
|
TestOwnable: TestOwnable as ContractArtifact,
|
||||||
TestReentrancyGuard: TestReentrancyGuard as ContractArtifact,
|
TestReentrancyGuard: TestReentrancyGuard as ContractArtifact,
|
||||||
TestSafeMath: TestSafeMath as ContractArtifact,
|
TestSafeMath: TestSafeMath as ContractArtifact,
|
||||||
|
@ -15,6 +15,7 @@ export * from '../generated-wrappers/test_constants';
|
|||||||
export * from '../generated-wrappers/test_lib_address';
|
export * from '../generated-wrappers/test_lib_address';
|
||||||
export * from '../generated-wrappers/test_lib_address_array';
|
export * from '../generated-wrappers/test_lib_address_array';
|
||||||
export * from '../generated-wrappers/test_lib_bytes';
|
export * from '../generated-wrappers/test_lib_bytes';
|
||||||
|
export * from '../generated-wrappers/test_lib_e_i_p712';
|
||||||
export * from '../generated-wrappers/test_ownable';
|
export * from '../generated-wrappers/test_ownable';
|
||||||
export * from '../generated-wrappers/test_reentrancy_guard';
|
export * from '../generated-wrappers/test_reentrancy_guard';
|
||||||
export * from '../generated-wrappers/test_safe_math';
|
export * from '../generated-wrappers/test_safe_math';
|
||||||
|
107
contracts/utils/test/lib_eip712.ts
Normal file
107
contracts/utils/test/lib_eip712.ts
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import { chaiSetup, constants, hexConcat, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||||
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||||
|
import { BigNumber, signTypedDataUtils } from '@0x/utils';
|
||||||
|
import * as chai from 'chai';
|
||||||
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts, TestLibEIP712Contract } from '../src';
|
||||||
|
|
||||||
|
chaiSetup.configure();
|
||||||
|
const expect = chai.expect;
|
||||||
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a specific instance of EIP712 domain hashing.
|
||||||
|
* @param lib The LibEIP712 contract to call.
|
||||||
|
* @param name The name of the domain.
|
||||||
|
* @param version The version of the domain.
|
||||||
|
* @param chainId The chain id of the domain.
|
||||||
|
* @param verifyingContractAddress The verifying contract address of the domain.
|
||||||
|
*/
|
||||||
|
async function testHashEIP712DomainAsync(
|
||||||
|
lib: TestLibEIP712Contract,
|
||||||
|
name: string,
|
||||||
|
version: string,
|
||||||
|
chainId: number,
|
||||||
|
verifyingContractAddress: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const expectedHash = signTypedDataUtils.generateDomainHash({
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
chainId,
|
||||||
|
verifyingContractAddress,
|
||||||
|
});
|
||||||
|
const actualHash = await lib.externalHashEIP712DomainSeperator.callAsync(
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
new BigNumber(chainId),
|
||||||
|
verifyingContractAddress,
|
||||||
|
);
|
||||||
|
expect(actualHash).to.be.eq(hexConcat(expectedHash));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a specific instance of EIP712 message hashing.
|
||||||
|
* @param lib The LibEIP712 contract to call.
|
||||||
|
* @param domainHash The hash of the EIP712 domain of this instance.
|
||||||
|
* @param hashStruct The hash of the struct of this instance.
|
||||||
|
*/
|
||||||
|
async function testHashEIP712MessageAsync(
|
||||||
|
lib: TestLibEIP712Contract,
|
||||||
|
domainHash: string,
|
||||||
|
hashStruct: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const input = '0x1901'.concat(domainHash.slice(2, domainHash.length).concat(hashStruct.slice(2, hashStruct.length)));
|
||||||
|
const expectedHash = '0x'.concat(ethUtil.sha3(input).toString('hex'));
|
||||||
|
const actualHash = await lib.externalHashEIP712Message.callAsync(
|
||||||
|
domainHash,
|
||||||
|
hashStruct,
|
||||||
|
);
|
||||||
|
expect(actualHash).to.be.eq(expectedHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('LibEIP712', () => {
|
||||||
|
let lib: TestLibEIP712Contract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await blockchainLifecycle.startAsync();
|
||||||
|
// Deploy SafeMath
|
||||||
|
lib = await TestLibEIP712Contract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestLibEIP712,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await blockchainLifecycle.revertAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_hashEIP712Domain', async () => {
|
||||||
|
it('should correctly hash empty input', async () => {
|
||||||
|
await testHashEIP712DomainAsync(
|
||||||
|
lib,
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
0,
|
||||||
|
constants.NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_hashEIP712Message', () => {
|
||||||
|
it('should correctly hash empty input', async () => {
|
||||||
|
/*
|
||||||
|
const expectedHash = hashEIP712Message(constants.NULL_BYTES32, constants.NULL_BYTES32);
|
||||||
|
const actualHash = await lib.externalHashEIP712Message.callAsync(constants.NULL_BYTES32, constants.NULL_BYTES32);
|
||||||
|
expect(actualHash).to.be.eq(expectedHash);
|
||||||
|
*/
|
||||||
|
await testHashEIP712MessageAsync(
|
||||||
|
lib,
|
||||||
|
constants.NULL_BYTES32,
|
||||||
|
constants.NULL_BYTES32,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -15,6 +15,7 @@
|
|||||||
"generated-artifacts/TestLibAddress.json",
|
"generated-artifacts/TestLibAddress.json",
|
||||||
"generated-artifacts/TestLibAddressArray.json",
|
"generated-artifacts/TestLibAddressArray.json",
|
||||||
"generated-artifacts/TestLibBytes.json",
|
"generated-artifacts/TestLibBytes.json",
|
||||||
|
"generated-artifacts/TestLibEIP712.json",
|
||||||
"generated-artifacts/TestOwnable.json",
|
"generated-artifacts/TestOwnable.json",
|
||||||
"generated-artifacts/TestReentrancyGuard.json",
|
"generated-artifacts/TestReentrancyGuard.json",
|
||||||
"generated-artifacts/TestSafeMath.json"
|
"generated-artifacts/TestSafeMath.json"
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { EIP712Object, EIP712ObjectValue, EIP712TypedData, EIP712Types } from '@0x/types';
|
import { EIP712DomainWithDefaultSchema, EIP712Object, EIP712ObjectValue, EIP712TypedData, EIP712Types } from '@0x/types';
|
||||||
import * as ethUtil from 'ethereumjs-util';
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
import * as ethers from 'ethers';
|
import * as ethers from 'ethers';
|
||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { BigNumber } from './configured_bignumber';
|
import { BigNumber } from './configured_bignumber';
|
||||||
|
|
||||||
|
|
||||||
export const signTypedDataUtils = {
|
export const signTypedDataUtils = {
|
||||||
/**
|
/**
|
||||||
* Generates the EIP712 Typed Data hash for signing
|
* Generates the EIP712 Typed Data hash for signing
|
||||||
@ -20,6 +21,28 @@ export const signTypedDataUtils = {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Generates the hash of a EIP712 Domain with the default schema
|
||||||
|
* @param domain An EIP712 domain with the default schema containing a name, version, chain id,
|
||||||
|
* and verifying address.
|
||||||
|
* @return A buffer that contains the hash of the domain.
|
||||||
|
*/
|
||||||
|
generateDomainHash(domain: EIP712Object): Buffer {
|
||||||
|
return signTypedDataUtils._structHash(
|
||||||
|
'EIP712Domain',
|
||||||
|
domain,
|
||||||
|
// HACK(jalextowle): When we consolidate our testing packages into test-utils, we can use a constant
|
||||||
|
// to eliminate code duplication. At the moment, there isn't a good way to do that because of cyclic-dependencies.
|
||||||
|
{
|
||||||
|
EIP712Domain: [
|
||||||
|
{ name: 'name', type: 'string' },
|
||||||
|
{ name: 'version', type: 'string' },
|
||||||
|
{ name: 'chainId', type: 'uint256' },
|
||||||
|
{ name: 'verifyingContractAddress', type: 'address' },
|
||||||
|
]
|
||||||
|
} as EIP712Types,
|
||||||
|
);
|
||||||
|
},
|
||||||
_findDependencies(primaryType: string, types: EIP712Types, found: string[] = []): string[] {
|
_findDependencies(primaryType: string, types: EIP712Types, found: string[] = []): string[] {
|
||||||
if (found.includes(primaryType) || types[primaryType] === undefined) {
|
if (found.includes(primaryType) || types[primaryType] === undefined) {
|
||||||
return found;
|
return found;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user