Added unit tests for LibEIP712
This commit is contained in:
		@@ -42,6 +42,7 @@ export const constants = {
 | 
			
		||||
    NUM_ERC1155_FUNGIBLE_TOKENS_MINT: 4,
 | 
			
		||||
    NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT: 4,
 | 
			
		||||
    NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
 | 
			
		||||
    NULL_BYTES32: '0x0000000000000000000000000000000000000000000000000000000000000000',
 | 
			
		||||
    UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
 | 
			
		||||
    TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)),
 | 
			
		||||
    INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@
 | 
			
		||||
        "test/TestLibAddress.sol",
 | 
			
		||||
        "test/TestLibAddressArray.sol",
 | 
			
		||||
        "test/TestLibBytes.sol",
 | 
			
		||||
        "test/TestLibEIP712.sol",
 | 
			
		||||
        "test/TestOwnable.sol",
 | 
			
		||||
        "test/TestReentrancyGuard.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");
 | 
			
		||||
  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"
 | 
			
		||||
    },
 | 
			
		||||
    "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."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ import * as TestConstants from '../generated-artifacts/TestConstants.json';
 | 
			
		||||
import * as TestLibAddress from '../generated-artifacts/TestLibAddress.json';
 | 
			
		||||
import * as TestLibAddressArray from '../generated-artifacts/TestLibAddressArray.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 TestReentrancyGuard from '../generated-artifacts/TestReentrancyGuard.json';
 | 
			
		||||
import * as TestSafeMath from '../generated-artifacts/TestSafeMath.json';
 | 
			
		||||
@@ -33,6 +34,7 @@ export const artifacts = {
 | 
			
		||||
    TestLibAddress: TestLibAddress as ContractArtifact,
 | 
			
		||||
    TestLibAddressArray: TestLibAddressArray as ContractArtifact,
 | 
			
		||||
    TestLibBytes: TestLibBytes as ContractArtifact,
 | 
			
		||||
    TestLibEIP712: TestLibEIP712 as ContractArtifact,
 | 
			
		||||
    TestOwnable: TestOwnable as ContractArtifact,
 | 
			
		||||
    TestReentrancyGuard: TestReentrancyGuard 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_array';
 | 
			
		||||
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_reentrancy_guard';
 | 
			
		||||
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/TestLibAddressArray.json",
 | 
			
		||||
        "generated-artifacts/TestLibBytes.json",
 | 
			
		||||
        "generated-artifacts/TestLibEIP712.json",
 | 
			
		||||
        "generated-artifacts/TestOwnable.json",
 | 
			
		||||
        "generated-artifacts/TestReentrancyGuard.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 ethers from 'ethers';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { BigNumber } from './configured_bignumber';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export const signTypedDataUtils = {
 | 
			
		||||
    /**
 | 
			
		||||
     * 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[] {
 | 
			
		||||
        if (found.includes(primaryType) || types[primaryType] === undefined) {
 | 
			
		||||
            return found;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user