diff options
author | Fabio Berger <me@fabioberger.com> | 2018-06-20 19:25:29 +0800 |
---|---|---|
committer | Fabio Berger <me@fabioberger.com> | 2018-06-20 19:25:29 +0800 |
commit | 2ffab2218584fac5d3ea2b264a7c746d963083d9 (patch) | |
tree | f7558147b811c06300e2c7697591466ae7cf48ba /packages/contracts/src | |
parent | 5541327968ad6f974a37c49057253746f738a709 (diff) | |
parent | 096eaa20d785baee07b06b3f0848797e470fbda0 (diff) | |
download | dexon-sol-tools-2ffab2218584fac5d3ea2b264a7c746d963083d9.tar dexon-sol-tools-2ffab2218584fac5d3ea2b264a7c746d963083d9.tar.gz dexon-sol-tools-2ffab2218584fac5d3ea2b264a7c746d963083d9.tar.bz2 dexon-sol-tools-2ffab2218584fac5d3ea2b264a7c746d963083d9.tar.lz dexon-sol-tools-2ffab2218584fac5d3ea2b264a7c746d963083d9.tar.xz dexon-sol-tools-2ffab2218584fac5d3ea2b264a7c746d963083d9.tar.zst dexon-sol-tools-2ffab2218584fac5d3ea2b264a7c746d963083d9.zip |
Merge branch 'v2-prototype' into feature/combinatorial-testing
* v2-prototype: (22 commits)
Fix closing parens in liborder
Update after rebase
ERC721Proxy Always call safeTransferFrom
Rename makerEpoch => orderEpoch
Make cancelOrdersUpTo compatible with sender abstraction
Update PR template
Use Image component instead of img tag
Assembler orderHash function
Optimize and remove redundant encodePacked
Fix linting issue
Fix bug where we do fetch balances on wallet login
Check network state immediately instead of waiting for delay
Fix onboarding persisting when changing routes
Consolidate account state messaging logic
Only elevate wallet zIndex when onboarding is in progress
Rebase and update feedback
Run linter
Add Portal v2 logging
Simplified handling of source < 32 edge case
Basic EIP712 encoder
...
Diffstat (limited to 'packages/contracts/src')
15 files changed, 301 insertions, 82 deletions
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol index d09aba599..9dc9e6525 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol @@ -53,13 +53,7 @@ contract MixinERC721Transfer is bytes memory receiverData ) = decodeERC721AssetData(assetData); - // Transfer token. Saves gas by calling safeTransferFrom only - // when there is receiverData present. Either succeeds or throws. - if (receiverData.length > 0) { - ERC721Token(token).safeTransferFrom(from, to, tokenId, receiverData); - } else { - ERC721Token(token).transferFrom(from, to, tokenId); - } + ERC721Token(token).safeTransferFrom(from, to, tokenId, receiverData); } /// @dev Decodes ERC721 Asset data. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol index 0a0f0209a..c406354a7 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinExchangeCore.sol @@ -44,32 +44,36 @@ contract MixinExchangeCore is // Mapping of orderHash => cancelled mapping (bytes32 => bool) public cancelled; - // Mapping of makerAddress => lowest salt an order can have in order to be fillable - // Orders with a salt less than their maker's epoch are considered cancelled - mapping (address => uint256) public makerEpoch; + // Mapping of makerAddress => senderAddress => lowest salt an order can have in order to be fillable + // Orders with specified senderAddress and with a salt less than their epoch to are considered cancelled + mapping (address => mapping (address => uint256)) public orderEpoch; ////// Core exchange functions ////// - /// @dev Cancels all orders created by sender with a salt less than or equal to the specified salt value. - /// @param salt Orders created with a salt less or equal to this value will be cancelled. - function cancelOrdersUpTo(uint256 salt) + /// @dev Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch + /// and senderAddress equal to msg.sender (or null address if msg.sender == makerAddress). + /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled. + function cancelOrdersUpTo(uint256 targetOrderEpoch) external { address makerAddress = getCurrentContextAddress(); + // If this function is called via `executeTransaction`, we only update the orderEpoch for the makerAddress/msg.sender combination. + // This allows external filter contracts to add rules to how orders are cancelled via this function. + address senderAddress = makerAddress == msg.sender ? address(0) : msg.sender; - // makerEpoch is initialized to 0, so to cancelUpTo we need salt + 1 - uint256 newMakerEpoch = salt + 1; - uint256 oldMakerEpoch = makerEpoch[makerAddress]; + // orderEpoch is initialized to 0, so to cancelUpTo we need salt + 1 + uint256 newOrderEpoch = targetOrderEpoch + 1; + uint256 oldOrderEpoch = orderEpoch[makerAddress][senderAddress]; - // Ensure makerEpoch is monotonically increasing + // Ensure orderEpoch is monotonically increasing require( - newMakerEpoch > oldMakerEpoch, - INVALID_NEW_MAKER_EPOCH + newOrderEpoch > oldOrderEpoch, + INVALID_NEW_ORDER_EPOCH ); - // Update makerEpoch - makerEpoch[makerAddress] = newMakerEpoch; - emit CancelUpTo(makerAddress, newMakerEpoch); + // Update orderEpoch + orderEpoch[makerAddress][senderAddress] = newOrderEpoch; + emit CancelUpTo(makerAddress, senderAddress, newOrderEpoch); } /// @dev Fills the input order. @@ -180,7 +184,7 @@ contract MixinExchangeCore is orderInfo.orderStatus = uint8(OrderStatus.CANCELLED); return orderInfo; } - if (makerEpoch[order.makerAddress] > order.salt) { + if (orderEpoch[order.makerAddress][order.senderAddress] > order.salt) { orderInfo.orderStatus = uint8(OrderStatus.CANCELLED); return orderInfo; } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol index 30b0102fd..f1332363c 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinTransactions.sol @@ -20,8 +20,11 @@ pragma solidity ^0.4.24; import "./libs/LibExchangeErrors.sol"; import "./mixins/MSignatureValidator.sol"; import "./mixins/MTransactions.sol"; +import "./libs/LibExchangeErrors.sol"; +import "./libs/LibEIP712.sol"; contract MixinTransactions is + LibEIP712, LibExchangeErrors, MSignatureValidator, MTransactions @@ -34,6 +37,33 @@ contract MixinTransactions is // Address of current transaction signer address public currentContextAddress; + // Hash for the EIP712 ZeroEx Transaction Schema + bytes32 constant EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH = keccak256(abi.encodePacked( + "ZeroExTransaction(", + "uint256 salt,", + "address signer,", + "bytes data", + ")" + )); + + /// @dev Calculates EIP712 hash of the Transaction. + /// @param salt Arbitrary number to ensure uniqueness of transaction hash. + /// @param signer Address of transaction signer. + /// @param data AbiV2 encoded calldata. + /// @return EIP712 hash of the Transaction. + function hashZeroExTransaction(uint256 salt, address signer, bytes data) + internal + pure + returns (bytes32) + { + return keccak256(abi.encode( + EIP712_ZEROEX_TRANSACTION_SCHEMA_HASH, + salt, + signer, + keccak256(data) + )); + } + /// @dev Executes an exchange method call in the context of signer. /// @param salt Arbitrary number to ensure uniqueness of transaction hash. /// @param signer Address of transaction signer. @@ -53,13 +83,7 @@ contract MixinTransactions is REENTRANCY_ILLEGAL ); - // Calculate transaction hash - bytes32 transactionHash = keccak256(abi.encodePacked( - address(this), - signer, - salt, - data - )); + bytes32 transactionHash = hashEIP712Message(hashZeroExTransaction(salt, signer, data)); // Validate transaction has not been executed require( diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol index 7ca2dd052..98222f33f 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IExchangeCore.sol @@ -24,9 +24,10 @@ import "../libs/LibFillResults.sol"; contract IExchangeCore { - /// @dev Cancels all orders reated by sender with a salt less than or equal to the specified salt value. - /// @param salt Orders created with a salt less or equal to this value will be cancelled. - function cancelOrdersUpTo(uint256 salt) + /// @dev Cancels all orders created by makerAddress with a salt less than or equal to the targetOrderEpoch + /// and senderAddress equal to msg.sender (or null address if msg.sender == makerAddress). + /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled. + function cancelOrdersUpTo(uint256 targetOrderEpoch) external; /// @dev Fills the input order. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol new file mode 100644 index 000000000..b983347a4 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibEIP712.sol @@ -0,0 +1,64 @@ +/* + + Copyright 2018 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.4.24; + +contract LibEIP712 { + // EIP191 header for EIP712 prefix + string constant EIP191_HEADER = "\x19\x01"; + + // EIP712 Domain Name value + string constant EIP712_DOMAIN_NAME = "0x Protocol"; + + // EIP712 Domain Version value + string constant EIP712_DOMAIN_VERSION = "2"; + + // Hash of the EIP712 Domain Separator Schema + bytes32 public constant EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked( + "EIP712Domain(", + "string name,", + "string version,", + "address verifyingContract", + ")" + )); + + // Hash of the EIP712 Domain Separator data + bytes32 public EIP712_DOMAIN_HASH; + + constructor () + public + { + EIP712_DOMAIN_HASH = keccak256(abi.encode( + EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, + keccak256(bytes(EIP712_DOMAIN_NAME)), + keccak256(bytes(EIP712_DOMAIN_VERSION)), + address(this) + )); + } + + /// @dev Calculates EIP712 encoding for a hash struct in this EIP712 Domain. + /// @param hashStruct The EIP712 hash struct. + /// @return EIP712 hash applied to this EIP712 Domain. + function hashEIP712Message(bytes32 hashStruct) + internal + view + returns (bytes32) + { + return keccak256(abi.encodePacked(EIP191_HEADER, EIP712_DOMAIN_HASH, hashStruct)); + } +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol index 48dd0f8be..adf27bec3 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibExchangeErrors.sol @@ -36,7 +36,7 @@ contract LibExchangeErrors { string constant SIGNATURE_UNSUPPORTED = "SIGNATURE_UNSUPPORTED"; // Signature type unsupported. /// cancelOrdersUptTo errors /// - string constant INVALID_NEW_MAKER_EPOCH = "INVALID_NEW_MAKER_EPOCH"; // Specified salt must be greater than or equal to existing makerEpoch. + string constant INVALID_NEW_ORDER_EPOCH = "INVALID_NEW_ORDER_EPOCH"; // Specified salt must be greater than or equal to existing orderEpoch. /// fillOrKillOrder errors /// string constant COMPLETE_FILL_FAILED = "COMPLETE_FILL_FAILED"; // Desired takerAssetFillAmount could not be completely filled. @@ -55,7 +55,7 @@ contract LibExchangeErrors { string constant ASSET_PROXY_ID_MISMATCH = "ASSET_PROXY_ID_MISMATCH"; // newAssetProxyId does not match given assetProxyId. /// Length validation errors /// - string constant LENGTH_GREATER_THAN_0_REQUIRED = "LENGTH_GREATER_THAN_0_REQUIRED"; // Byte array must have a length greater than 0. + string constant LENGTH_GREATER_THAN_0_REQUIRED = "LENGTH_GREATER_THAN_0_REQUIRED"; // Byte array must have a length greater than 0. string constant LENGTH_0_REQUIRED = "LENGTH_1_REQUIRED"; // Byte array must have a length of 1. string constant LENGTH_65_REQUIRED = "LENGTH_66_REQUIRED"; // Byte array must have a length of 66. } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol index 05ea27ffc..bfc7aaae0 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/libs/LibOrder.sol @@ -18,13 +18,14 @@ pragma solidity ^0.4.24; -contract LibOrder { +import "./LibEIP712.sol"; - bytes32 constant DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256(abi.encodePacked( - "DomainSeparator(address contract)" - )); +contract LibOrder is + LibEIP712 +{ - bytes32 constant ORDER_SCHEMA_HASH = keccak256(abi.encodePacked( + // Hash for the EIP712 Order Schema + bytes32 constant EIP712_ORDER_SCHEMA_HASH = keccak256(abi.encodePacked( "Order(", "address makerAddress,", "address takerAddress,", @@ -37,7 +38,7 @@ contract LibOrder { "uint256 expirationTimeSeconds,", "uint256 salt,", "bytes makerAssetData,", - "bytes takerAssetData,", + "bytes takerAssetData", ")" )); @@ -85,27 +86,38 @@ contract LibOrder { view returns (bytes32 orderHash) { - // TODO: EIP712 is not finalized yet - // Source: https://github.com/ethereum/EIPs/pull/712 - orderHash = keccak256(abi.encodePacked( - DOMAIN_SEPARATOR_SCHEMA_HASH, - keccak256(abi.encodePacked(address(this))), - ORDER_SCHEMA_HASH, - keccak256(abi.encodePacked( - order.makerAddress, - order.takerAddress, - order.feeRecipientAddress, - order.senderAddress, - order.makerAssetAmount, - order.takerAssetAmount, - order.makerFee, - order.takerFee, - order.expirationTimeSeconds, - order.salt, - keccak256(abi.encodePacked(order.makerAssetData)), - keccak256(abi.encodePacked(order.takerAssetData)) - )) - )); + orderHash = hashEIP712Message(hashOrder(order)); return orderHash; } + + /// @dev Calculates EIP712 hash of the order. + /// @param order The order structure. + /// @return EIP712 hash of the order. + function hashOrder(Order memory order) + internal + pure + returns (bytes32 result) + { + bytes32 schemaHash = EIP712_ORDER_SCHEMA_HASH; + bytes32 makerAssetDataHash = keccak256(order.makerAssetData); + bytes32 takerAssetDataHash = keccak256(order.takerAssetData); + assembly { + // Backup + let temp1 := mload(sub(order, 32)) + let temp2 := mload(add(order, 320)) + let temp3 := mload(add(order, 352)) + + // Hash in place + mstore(sub(order, 32), schemaHash) + mstore(add(order, 320), makerAssetDataHash) + mstore(add(order, 352), takerAssetDataHash) + result := keccak256(sub(order, 32), 416) + + // Restore + mstore(sub(order, 32), temp1) + mstore(add(order, 320), temp2) + mstore(add(order, 352), temp3) + } + return result; + } } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol index de7c4d3af..fb345294c 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MExchangeCore.sol @@ -52,7 +52,8 @@ contract MExchangeCore is // CancelUpTo event is emitted whenever `cancelOrdersUpTo` is executed succesfully. event CancelUpTo( address indexed makerAddress, - uint256 makerEpoch + address indexed senderAddress, + uint256 orderEpoch ); /// @dev Updates state with results of a fill order. diff --git a/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol b/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol new file mode 100644 index 000000000..5baaf6e5a --- /dev/null +++ b/packages/contracts/src/contracts/current/test/ExchangeWrapper/ExchangeWrapper.sol @@ -0,0 +1,98 @@ +/* + + Copyright 2018 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.4.24; +pragma experimental ABIEncoderV2; + +import "../../protocol/Exchange/interfaces/IExchange.sol"; +import "../../protocol/Exchange/libs/LibOrder.sol"; + +contract ExchangeWrapper { + + // Exchange contract. + IExchange EXCHANGE; + + constructor (address _exchange) + public + { + EXCHANGE = IExchange(_exchange); + } + + /// @dev Fills an order using `msg.sender` as the taker. + /// @param order Order struct containing order specifications. + /// @param takerAssetFillAmount Desired amount of takerAsset to sell. + /// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash. + /// @param orderSignature Proof that order has been created by maker. + /// @param takerSignature Proof that taker wishes to call this function with given params. + function fillOrder( + LibOrder.Order memory order, + uint256 takerAssetFillAmount, + uint256 salt, + bytes memory orderSignature, + bytes memory takerSignature + ) + public + { + address takerAddress = msg.sender; + + // Encode arguments into byte array. + bytes memory data = abi.encodeWithSelector( + EXCHANGE.fillOrder.selector, + order, + takerAssetFillAmount, + orderSignature + ); + + // Call `fillOrder` via `executeTransaction`. + EXCHANGE.executeTransaction( + salt, + takerAddress, + data, + takerSignature + ); + } + + /// @dev Cancels all orders created by sender with a salt less than or equal to the targetOrderEpoch + /// and senderAddress equal to this contract. + /// @param targetOrderEpoch Orders created with a salt less or equal to this value will be cancelled. + /// @param salt Arbitrary value to gaurantee uniqueness of 0x transaction hash. + /// @param makerSignature Proof that maker wishes to call this function with given params. + function cancelOrdersUpTo( + uint256 targetOrderEpoch, + uint256 salt, + bytes makerSignature + ) + external + { + address makerAddress = msg.sender; + + // Encode arguments into byte array. + bytes memory data = abi.encodeWithSelector( + EXCHANGE.cancelOrdersUpTo.selector, + targetOrderEpoch + ); + + // Call `cancelOrdersUpTo` via `executeTransaction`. + EXCHANGE.executeTransaction( + salt, + makerAddress, + data, + makerSignature + ); + } +} diff --git a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol index 47ce0dcf3..010080703 100644 --- a/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol +++ b/packages/contracts/src/contracts/current/test/TestLibs/TestLibs.sol @@ -74,7 +74,7 @@ contract TestLibs is pure returns (bytes32) { - return ORDER_SCHEMA_HASH; + return EIP712_ORDER_SCHEMA_HASH; } function getDomainSeparatorSchemaHash() @@ -82,7 +82,7 @@ contract TestLibs is pure returns (bytes32) { - return DOMAIN_SEPARATOR_SCHEMA_HASH; + return EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH; } function publicAddFillResults(FillResults memory totalFillResults, FillResults memory singleFillResults) diff --git a/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol b/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol index 0594e2767..460c9ea42 100644 --- a/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol +++ b/packages/contracts/src/contracts/current/test/Whitelist/Whitelist.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.4.23; +pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../../protocol/Exchange/interfaces/IExchange.sol"; diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol index 6afb9973a..97fb5fb0f 100644 --- a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol +++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol @@ -80,9 +80,6 @@ contract LibMem // if (source > dest) { assembly { - // Record the total number of full words to copy - let nWords := div(length, 32) - // We subtract 32 from `sEnd` and `dEnd` because it // is easier to compare with in the loop, and these // are also the addresses we need for copying the @@ -98,20 +95,19 @@ contract LibMem let last := mload(sEnd) // Copy whole words front to back - for {let i := 0} lt(i, nWords) {i := add(i, 1)} { + // Note: the first check is always true, + // this could have been a do-while loop. + for {} lt(source, sEnd) {} { mstore(dest, mload(source)) source := add(source, 32) dest := add(dest, 32) } - + // Write the last 32 bytes mstore(dEnd, last) } } else { assembly { - // Record the total number of full words to copy - let nWords := div(length, 32) - // We subtract 32 from `sEnd` and `dEnd` because those // are the starting points when copying a word at the end. length := sub(length, 32) @@ -125,12 +121,18 @@ contract LibMem let first := mload(source) // Copy whole words back to front - for {let i := 0} lt(i, nWords) {i := add(i, 1)} { + // We use a signed comparisson here to allow dEnd to become + // negative (happens when source and dest < 32). Valid + // addresses in local memory will never be larger than + // 2**255, so they can be safely re-interpreted as signed. + // Note: the first check is always true, + // this could have been a do-while loop. + for {} slt(dest, dEnd) {} { mstore(dEnd, mload(sEnd)) sEnd := sub(sEnd, 32) dEnd := sub(dEnd, 32) } - + // Write the first 32 bytes mstore(dest, first) } diff --git a/packages/contracts/src/utils/artifacts.ts b/packages/contracts/src/utils/artifacts.ts index bf7221d6d..7ba467708 100644 --- a/packages/contracts/src/utils/artifacts.ts +++ b/packages/contracts/src/utils/artifacts.ts @@ -7,6 +7,7 @@ import * as DummyERC721Token from '../artifacts/DummyERC721Token.json'; import * as ERC20Proxy from '../artifacts/ERC20Proxy.json'; import * as ERC721Proxy from '../artifacts/ERC721Proxy.json'; import * as Exchange from '../artifacts/Exchange.json'; +import * as ExchangeWrapper from '../artifacts/ExchangeWrapper.json'; import * as MixinAuthorizable from '../artifacts/MixinAuthorizable.json'; import * as MultiSigWallet from '../artifacts/MultiSigWallet.json'; import * as MultiSigWalletWithTimeLock from '../artifacts/MultiSigWalletWithTimeLock.json'; @@ -29,6 +30,7 @@ export const artifacts = { ERC20Proxy: (ERC20Proxy as any) as ContractArtifact, ERC721Proxy: (ERC721Proxy as any) as ContractArtifact, Exchange: (Exchange as any) as ContractArtifact, + ExchangeWrapper: (ExchangeWrapper as any) as ContractArtifact, EtherToken: (EtherToken as any) as ContractArtifact, MixinAuthorizable: (MixinAuthorizable as any) as ContractArtifact, MultiSigWallet: (MultiSigWallet as any) as ContractArtifact, diff --git a/packages/contracts/src/utils/order_factory.ts b/packages/contracts/src/utils/order_factory.ts index 6e4c9a883..009dbc396 100644 --- a/packages/contracts/src/utils/order_factory.ts +++ b/packages/contracts/src/utils/order_factory.ts @@ -26,7 +26,7 @@ export class OrderFactory { ...this._defaultOrderParams, ...customOrderParams, } as any) as Order; - const orderHashBuff = orderHashUtils.getOrderHashBuff(order); + const orderHashBuff = orderHashUtils.getOrderHashBuffer(order); const signature = signingUtils.signMessage(orderHashBuff, this._privateKey, signatureType); const signedOrder = { ...order, diff --git a/packages/contracts/src/utils/transaction_factory.ts b/packages/contracts/src/utils/transaction_factory.ts index a060263b1..19ef4e1bf 100644 --- a/packages/contracts/src/utils/transaction_factory.ts +++ b/packages/contracts/src/utils/transaction_factory.ts @@ -1,10 +1,19 @@ -import { crypto, generatePseudoRandomSalt } from '@0xproject/order-utils'; +import { EIP712Schema, EIP712Types, EIP712Utils, generatePseudoRandomSalt } from '@0xproject/order-utils'; import { SignatureType } from '@0xproject/types'; import * as ethUtil from 'ethereumjs-util'; import { signingUtils } from './signing_utils'; import { SignedTransaction } from './types'; +const EIP712_ZEROEX_TRANSACTION_SCHEMA: EIP712Schema = { + name: 'ZeroExTransaction', + parameters: [ + { name: 'salt', type: EIP712Types.Uint256 }, + { name: 'signer', type: EIP712Types.Address }, + { name: 'data', type: EIP712Types.Bytes }, + ], +}; + export class TransactionFactory { private _signerBuff: Buffer; private _exchangeAddress: string; @@ -16,14 +25,22 @@ export class TransactionFactory { } public newSignedTransaction(data: string, signatureType: SignatureType = SignatureType.EthSign): SignedTransaction { const salt = generatePseudoRandomSalt(); - const txHash = crypto.solSHA3([this._exchangeAddress, this._signerBuff, salt, ethUtil.toBuffer(data)]); + const signer = `0x${this._signerBuff.toString('hex')}`; + const executeTransactionData = { + salt, + signer, + data, + }; + const executeTransactionHashBuff = EIP712Utils.structHash( + EIP712_ZEROEX_TRANSACTION_SCHEMA, + executeTransactionData, + ); + const txHash = EIP712Utils.createEIP712Message(executeTransactionHashBuff, this._exchangeAddress); const signature = signingUtils.signMessage(txHash, this._privateKey, signatureType); const signedTx = { exchangeAddress: this._exchangeAddress, - salt, - signer: `0x${this._signerBuff.toString('hex')}`, - data, signature: `0x${signature.toString('hex')}`, + ...executeTransactionData, }; return signedTx; } |