diff --git a/contracts/erc1155/contracts/src/ERC1155.sol b/contracts/erc1155/contracts/src/ERC1155.sol index ab81c61aec..c76fedf007 100644 --- a/contracts/erc1155/contracts/src/ERC1155.sol +++ b/contracts/erc1155/contracts/src/ERC1155.sol @@ -17,6 +17,7 @@ */ pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "@0x/contracts-utils/contracts/src/LibAddress.sol"; diff --git a/contracts/erc1155/contracts/src/ERC1155Mintable.sol b/contracts/erc1155/contracts/src/ERC1155Mintable.sol index 5d99a535cf..9db42f8888 100644 --- a/contracts/erc1155/contracts/src/ERC1155Mintable.sol +++ b/contracts/erc1155/contracts/src/ERC1155Mintable.sol @@ -1,4 +1,23 @@ +/* + + 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; +pragma experimental ABIEncoderV2; import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; import "./ERC1155.sol"; diff --git a/contracts/erc1155/contracts/src/MixinNonFungibleToken.sol b/contracts/erc1155/contracts/src/MixinNonFungibleToken.sol index 719b093c0b..ce43e0f4bc 100644 --- a/contracts/erc1155/contracts/src/MixinNonFungibleToken.sol +++ b/contracts/erc1155/contracts/src/MixinNonFungibleToken.sol @@ -17,6 +17,7 @@ */ pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; contract MixinNonFungibleToken { @@ -64,7 +65,7 @@ contract MixinNonFungibleToken { // A base type has the NF bit but does has an index. return (id & TYPE_NF_BIT == TYPE_NF_BIT) && (id & NF_INDEX_MASK != 0); } - + /// @dev returns owner of a non-fungible token function ownerOf(uint256 id) public view returns (address) { return nfOwners[id]; diff --git a/contracts/erc1155/contracts/src/interfaces/IERC1155.sol b/contracts/erc1155/contracts/src/interfaces/IERC1155.sol index 80e34f98df..de0720e608 100644 --- a/contracts/erc1155/contracts/src/interfaces/IERC1155.sol +++ b/contracts/erc1155/contracts/src/interfaces/IERC1155.sol @@ -17,13 +17,14 @@ */ pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; /// @title ERC-1155 Multi Token Standard /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1155.md /// Note: The ERC-165 identifier for this interface is 0xd9b67a26. interface IERC1155 { - + /// @dev Either TransferSingle or TransferBatch MUST emit when tokens are transferred, /// including zero value transfers as well as minting or burning. /// Operator will always be msg.sender. diff --git a/contracts/erc1155/contracts/src/interfaces/IERC1155Mintable.sol b/contracts/erc1155/contracts/src/interfaces/IERC1155Mintable.sol index cb271e1bfe..036156a4ed 100644 --- a/contracts/erc1155/contracts/src/interfaces/IERC1155Mintable.sol +++ b/contracts/erc1155/contracts/src/interfaces/IERC1155Mintable.sol @@ -1,4 +1,23 @@ +/* + + 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; +pragma experimental ABIEncoderV2; import "./IERC1155.sol"; diff --git a/contracts/erc1155/contracts/src/interfaces/IERC1155Receiver.sol b/contracts/erc1155/contracts/src/interfaces/IERC1155Receiver.sol index 79165538bf..6ce95759f9 100644 --- a/contracts/erc1155/contracts/src/interfaces/IERC1155Receiver.sol +++ b/contracts/erc1155/contracts/src/interfaces/IERC1155Receiver.sol @@ -17,10 +17,11 @@ */ pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; interface IERC1155Receiver { - + /// @notice Handle the receipt of a single ERC1155 token type /// @dev The smart contract calls this function on the recipient /// after a `safeTransferFrom`. This function MAY throw to revert and reject the diff --git a/contracts/exchange/test/wrapper_unit_tests.ts b/contracts/exchange/test/wrapper_unit_tests.ts index 7b13d86769..eba2244663 100644 --- a/contracts/exchange/test/wrapper_unit_tests.ts +++ b/contracts/exchange/test/wrapper_unit_tests.ts @@ -139,8 +139,8 @@ blockchainTests('Exchange wrapper functions unit tests.', env => { expect(actual[13]).to.be.eq(expected.takerFeeAssetData); } - describe('fillOrKillOrder', () => { - it('works if the order is filled by exactly `takerAssetFillAmount`', async () => { + describe.only('fillOrKillOrder', () => { + it.only('works if the order is filled by exactly `takerAssetFillAmount`', async () => { const fillAmount = randomAmount(); const order = randomOrder({ // `_fillOrder()` is overridden to always return `order.takerAssetAmount` as diff --git a/packages/utils/src/abi_decoder.ts b/packages/utils/src/abi_decoder.ts index 04a81c3ee4..dc2b09d042 100644 --- a/packages/utils/src/abi_decoder.ts +++ b/packages/utils/src/abi_decoder.ts @@ -1,21 +1,18 @@ import { AbiDefinition, AbiType, + DataItem, DecodedLogArgs, EventAbi, - EventParameter, LogEntry, LogWithDecodedArgs, MethodAbi, RawLog, - SolidityTypes, } from 'ethereum-types'; import * as ethers from 'ethers'; import * as _ from 'lodash'; import { AbiEncoder } from '.'; -import { addressUtils } from './address_utils'; -import { BigNumber } from './configured_bignumber'; import { DecodedCalldata, SelectorToFunctionInfo } from './types'; /** @@ -56,58 +53,53 @@ export class AbiDecoder { * @return The decoded log if the requisite ABI was available. Otherwise the log unaltered. */ public tryToDecodeLogOrNoop(log: LogEntry): LogWithDecodedArgs | RawLog { + // Lookup event corresponding to log const eventId = log.topics[0]; const numIndexedArgs = log.topics.length - 1; if (this._eventIds[eventId] === undefined || this._eventIds[eventId][numIndexedArgs] === undefined) { return log; } const event = this._eventIds[eventId][numIndexedArgs]; - const ethersInterface = new ethers.utils.Interface([event]); - const decodedParams: DecodedLogArgs = {}; - let topicsIndex = 1; - let decodedData: any[]; - try { - decodedData = ethersInterface.events[event.name].decode(log.data); - } catch (error) { - if (error.code === ethers.errors.INVALID_ARGUMENT) { - // Because we index events by Method ID, and Method IDs are derived from the method - // name and the input parameters, it's possible that the return value of the event - // does not match our ABI. If that's the case, then ethers will throw an error - // when we try to parse the event. We handle that case here by returning the log rather - // than throwing an error. + // Create decoders for indexed data + const indexedDataDecoders = _.mapValues(_.filter(event.inputs, { indexed: true }), input => + // tslint:disable:next-line no-unnecessary-type-assertion + AbiEncoder.create(input as DataItem), + ); + + // Decode indexed data + const decodedIndexedData = _.map( + log.topics.slice(1), // ignore first topic, which is the event id. + (input, i) => indexedDataDecoders[i].decode(input), + ); + + // Decode non-indexed data + const decodedNonIndexedData = AbiEncoder.create(_.filter(event.inputs, { indexed: false })).decodeAsArray( + log.data, + ); + + // Construct DecodedLogArgs struct by mapping event parameters to their respective decoded argument. + const decodedArgs: DecodedLogArgs = {}; + let indexedOffset = 0; + let nonIndexedOffset = 0; + for (const param of event.inputs) { + const value = param.indexed + ? decodedIndexedData[indexedOffset++] + : decodedNonIndexedData[nonIndexedOffset++]; + + if (value === undefined) { return log; } - throw error; - } - let didFailToDecode = false; - _.forEach(event.inputs, (param: EventParameter, i: number) => { - // Indexed parameters are stored in topics. Non-indexed ones in decodedData - let value: BigNumber | string | number = param.indexed ? log.topics[topicsIndex++] : decodedData[i]; - if (value === undefined) { - didFailToDecode = true; - return; - } - if (param.type === SolidityTypes.Address) { - const baseHex = 16; - value = addressUtils.padZeros(new BigNumber((value as string).toLowerCase()).toString(baseHex)); - } else if (param.type === SolidityTypes.Uint256 || param.type === SolidityTypes.Uint) { - value = new BigNumber(value); - } else if (param.type === SolidityTypes.Uint8) { - value = new BigNumber(value).toNumber(); - } - decodedParams[param.name] = value; - }); - if (didFailToDecode) { - return log; - } else { - return { - ...log, - event: event.name, - args: decodedParams, - }; + decodedArgs[param.name] = value; } + + // Decoding was successful. Return decoded log. + return { + ...log, + event: event.name, + args: decodedArgs as ArgsType, + }; } /** * Decodes calldata for a known ABI.