diff options
Diffstat (limited to 'packages/contracts/src/contracts/current/protocol')
11 files changed, 249 insertions, 126 deletions
diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol index ddcd78e93..7ca823d1f 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC20Proxy.sol @@ -22,41 +22,16 @@ pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; import "./MixinAssetProxy.sol"; import "./MixinAuthorizable.sol"; -import "../../tokens/ERC20Token/IERC20Token.sol"; +import "./MixinERC20Transfer.sol"; contract ERC20Proxy is - LibBytes, MixinAssetProxy, - MixinAuthorizable + MixinAuthorizable, + MixinERC20Transfer { - // Id of this proxy. uint8 constant PROXY_ID = 1; - /// @dev Internal version of `transferFrom`. - /// @param assetData Encoded byte array. - /// @param from Address to transfer asset from. - /// @param to Address to transfer asset to. - /// @param amount Amount of asset to transfer. - function transferFromInternal( - bytes memory assetData, - address from, - address to, - uint256 amount - ) - internal - { - // Decode asset data. - address token = readAddress(assetData, 0); - - // Transfer tokens. - bool success = IERC20Token(token).transferFrom(from, to, amount); - require( - success, - TRANSFER_FAILED - ); - } - /// @dev Gets the proxy id associated with the proxy address. /// @return Proxy id. function getProxyId() diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol index 861fac2c1..7ff25aea3 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/ERC721Proxy.sol @@ -22,52 +22,16 @@ pragma experimental ABIEncoderV2; import "../../utils/LibBytes/LibBytes.sol"; import "./MixinAssetProxy.sol"; import "./MixinAuthorizable.sol"; -import "../../tokens/ERC721Token/ERC721Token.sol"; +import "./MixinERC721Transfer.sol"; contract ERC721Proxy is - LibBytes, MixinAssetProxy, - MixinAuthorizable + MixinAuthorizable, + MixinERC721Transfer { - // Id of this proxy. uint8 constant PROXY_ID = 2; - /// @dev Internal version of `transferFrom`. - /// @param assetData Encoded byte array. - /// @param from Address to transfer asset from. - /// @param to Address to transfer asset to. - /// @param amount Amount of asset to transfer. - function transferFromInternal( - bytes memory assetData, - address from, - address to, - uint256 amount - ) - internal - { - // There exists only 1 of each token. - require( - amount == 1, - INVALID_AMOUNT - ); - - // Decode asset data. - ( - address token, - uint256 tokenId, - 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); - } - } - /// @dev Gets the proxy id associated with the proxy address. /// @return Proxy id. function getProxyId() @@ -77,34 +41,4 @@ contract ERC721Proxy is { return PROXY_ID; } - - /// @dev Decodes ERC721 Asset data. - /// @param assetData Encoded byte array. - /// @return proxyId Intended ERC721 proxy id. - /// @return token ERC721 token address. - /// @return tokenId ERC721 token id. - /// @return receiverData Additional data with no specific format, which - /// is passed to the receiving contract's onERC721Received. - function decodeERC721AssetData(bytes memory assetData) - internal - pure - returns ( - address token, - uint256 tokenId, - bytes memory receiverData - ) - { - // Decode asset data. - token = readAddress(assetData, 0); - tokenId = readUint256(assetData, 20); - if (assetData.length > 52) { - receiverData = readBytes(assetData, 52); - } - - return ( - token, - tokenId, - receiverData - ); - } } diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol new file mode 100644 index 000000000..4af39a00b --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC20Transfer.sol @@ -0,0 +1,81 @@ +/* + + 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 "../../utils/LibBytes/LibBytes.sol"; +import "../../tokens/ERC20Token/IERC20Token.sol"; +import "./libs/LibTransferErrors.sol"; + +contract MixinERC20Transfer is + LibBytes, + LibTransferErrors +{ + /// @dev Internal version of `transferFrom`. + /// @param assetData Encoded byte array. + /// @param from Address to transfer asset from. + /// @param to Address to transfer asset to. + /// @param amount Amount of asset to transfer. + function transferFromInternal( + bytes memory assetData, + address from, + address to, + uint256 amount + ) + internal + { + // Decode asset data. + address token = readAddress(assetData, 0); + + // Transfer tokens. + // We do a raw call so we can check the success separate + // from the return data. + bool success = token.call(abi.encodeWithSelector( + IERC20Token(token).transferFrom.selector, + from, + to, + amount + )); + require( + success, + TRANSFER_FAILED + ); + + // Check return data. + // If there is no return data, we assume the token incorrectly + // does not return a bool. In this case we expect it to revert + // on failure, which was handled above. + // If the token does return data, we require that it is a single + // value that evaluates to true. + assembly { + if returndatasize { + success := 0 + if eq(returndatasize, 32) { + // First 64 bytes of memory are reserved scratch space + returndatacopy(0, 0, 32) + success := mload(0) + } + } + } + require( + success, + TRANSFER_FAILED + ); + } +} diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol new file mode 100644 index 000000000..d09aba599 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/MixinERC721Transfer.sol @@ -0,0 +1,94 @@ +/* + + 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 "../../utils/LibBytes/LibBytes.sol"; +import "../../tokens/ERC721Token/ERC721Token.sol"; +import "./libs/LibTransferErrors.sol"; + +contract MixinERC721Transfer is + LibBytes, + LibTransferErrors +{ + /// @dev Internal version of `transferFrom`. + /// @param assetData Encoded byte array. + /// @param from Address to transfer asset from. + /// @param to Address to transfer asset to. + /// @param amount Amount of asset to transfer. + function transferFromInternal( + bytes memory assetData, + address from, + address to, + uint256 amount + ) + internal + { + // There exists only 1 of each token. + require( + amount == 1, + INVALID_AMOUNT + ); + + // Decode asset data. + ( + address token, + uint256 tokenId, + 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); + } + } + + /// @dev Decodes ERC721 Asset data. + /// @param assetData Encoded byte array. + /// @return proxyId Intended ERC721 proxy id. + /// @return token ERC721 token address. + /// @return tokenId ERC721 token id. + /// @return receiverData Additional data with no specific format, which + /// is passed to the receiving contract's onERC721Received. + function decodeERC721AssetData(bytes memory assetData) + internal + pure + returns ( + address token, + uint256 tokenId, + bytes memory receiverData + ) + { + // Decode asset data. + token = readAddress(assetData, 0); + tokenId = readUint256(assetData, 20); + if (assetData.length > 52) { + receiverData = readBytes(assetData, 52); + } + + return ( + token, + tokenId, + receiverData + ); + } +} diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol index 65bdacdb7..dca4f400f 100644 --- a/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibAssetProxyErrors.sol @@ -25,8 +25,4 @@ contract LibAssetProxyErrors { string constant TARGET_ALREADY_AUTHORIZED = "TARGET_ALREADY_AUTHORIZED"; // Target address must not already be authorized. string constant INDEX_OUT_OF_BOUNDS = "INDEX_OUT_OF_BOUNDS"; // Specified array index is out of bounds. string constant AUTHORIZED_ADDRESS_MISMATCH = "AUTHORIZED_ADDRESS_MISMATCH"; // Address at index does not match given target address. - - /// AssetProxy errors /// - string constant INVALID_AMOUNT = "INVALID_AMOUNT"; // Transfer amount must equal 1. - string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Transfer failed. } diff --git a/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibTransferErrors.sol b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibTransferErrors.sol new file mode 100644 index 000000000..ba784ab22 --- /dev/null +++ b/packages/contracts/src/contracts/current/protocol/AssetProxy/libs/LibTransferErrors.sol @@ -0,0 +1,25 @@ +/* + + 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 LibTransferErrors { + /// Transfer errors /// + string constant INVALID_AMOUNT = "INVALID_AMOUNT"; // Transfer amount must equal 1. + string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Transfer failed. +} diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol index 1a556dfe2..8ad15aaff 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinSignatureValidator.sol @@ -82,7 +82,7 @@ contract MixinSignatureValidator is address signer, bytes memory signature ) - internal + public view returns (bool isValid) { diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol index a7849f4cb..724f95518 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/MixinWrapperFunctions.sol @@ -263,40 +263,50 @@ contract MixinWrapperFunctions is /// @param orders Array of order specifications. /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders. /// @param signatures Proofs that orders have been created by makers. + /// @return Amounts filled and fees paid by makers and taker. + /// NOTE: makerAssetFilledAmount and takerAssetFilledAmount may include amounts filled of different assets. function batchFillOrders( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, bytes[] memory signatures ) public + returns (FillResults memory totalFillResults) { for (uint256 i = 0; i < orders.length; i++) { - fillOrder( + FillResults memory singleFillResults = fillOrder( orders[i], takerAssetFillAmounts[i], signatures[i] ); + addFillResults(totalFillResults, singleFillResults); } + return totalFillResults; } /// @dev Synchronously executes multiple calls of fillOrKill. /// @param orders Array of order specifications. /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders. /// @param signatures Proofs that orders have been created by makers. + /// @return Amounts filled and fees paid by makers and taker. + /// NOTE: makerAssetFilledAmount and takerAssetFilledAmount may include amounts filled of different assets. function batchFillOrKillOrders( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, bytes[] memory signatures ) public + returns (FillResults memory totalFillResults) { for (uint256 i = 0; i < orders.length; i++) { - fillOrKillOrder( + FillResults memory singleFillResults = fillOrKillOrder( orders[i], takerAssetFillAmounts[i], signatures[i] ); + addFillResults(totalFillResults, singleFillResults); } + return totalFillResults; } /// @dev Fills an order with specified parameters and ECDSA signature. @@ -304,20 +314,25 @@ contract MixinWrapperFunctions is /// @param orders Array of order specifications. /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders. /// @param signatures Proofs that orders have been created by makers. + /// @return Amounts filled and fees paid by makers and taker. + /// NOTE: makerAssetFilledAmount and takerAssetFilledAmount may include amounts filled of different assets. function batchFillOrdersNoThrow( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, bytes[] memory signatures ) public + returns (FillResults memory totalFillResults) { for (uint256 i = 0; i < orders.length; i++) { - fillOrderNoThrow( + FillResults memory singleFillResults = fillOrderNoThrow( orders[i], takerAssetFillAmounts[i], signatures[i] ); + addFillResults(totalFillResults, singleFillResults); } + return totalFillResults; } /// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol index 26e360c91..02aa9776e 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/ISignatureValidator.sol @@ -39,4 +39,18 @@ contract ISignatureValidator { bool approval ) external; + + /// @dev Verifies that a signature is valid. + /// @param hash Message hash that is signed. + /// @param signer Address of signer. + /// @param signature Proof of signing. + /// @return Validity of order signature. + function isValidSignature( + bytes32 hash, + address signer, + bytes memory signature + ) + public + view + returns (bool isValid); } diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol index acd4f359c..84bb683bc 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/interfaces/IWrapperFunctions.sol @@ -22,10 +22,7 @@ pragma experimental ABIEncoderV2; import "../libs/LibOrder.sol"; import "../libs/LibFillResults.sol"; -contract IWrapperFunctions is - LibOrder, - LibFillResults -{ +contract IWrapperFunctions { /// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled. /// @param order LibOrder.Order struct containing order specifications. /// @param takerAssetFillAmount Desired amount of takerAsset to sell. @@ -56,35 +53,41 @@ contract IWrapperFunctions is /// @param orders Array of order specifications. /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders. /// @param signatures Proofs that orders have been created by makers. + /// @return Amounts filled and fees paid by makers and taker. function batchFillOrders( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, bytes[] memory signatures ) - public; + public + returns (LibFillResults.FillResults memory totalFillResults); /// @dev Synchronously executes multiple calls of fillOrKill. /// @param orders Array of order specifications. /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders. /// @param signatures Proofs that orders have been created by makers. + /// @return Amounts filled and fees paid by makers and taker. function batchFillOrKillOrders( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, bytes[] memory signatures ) - public; + public + returns (LibFillResults.FillResults memory totalFillResults); /// @dev Fills an order with specified parameters and ECDSA signature. /// Returns false if the transaction would otherwise revert. /// @param orders Array of order specifications. /// @param takerAssetFillAmounts Array of desired amounts of takerAsset to sell in orders. /// @param signatures Proofs that orders have been created by makers. + /// @return Amounts filled and fees paid by makers and taker. function batchFillOrdersNoThrow( LibOrder.Order[] memory orders, uint256[] memory takerAssetFillAmounts, bytes[] memory signatures ) - public; + public + returns (LibFillResults.FillResults memory totalFillResults); /// @dev Synchronously executes multiple calls of fillOrder until total amount of takerAsset is sold by taker. /// @param orders Array of order specifications. diff --git a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol index 7eed453ff..5e286e43a 100644 --- a/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol +++ b/packages/contracts/src/contracts/current/protocol/Exchange/mixins/MSignatureValidator.sol @@ -35,18 +35,4 @@ contract MSignatureValidator is PreSigned, // 0x07 Trezor // 0x08 } - - /// @dev Verifies that a signature is valid. - /// @param hash Message hash that is signed. - /// @param signer Address of signer. - /// @param signature Proof of signing. - /// @return Validity of order signature. - function isValidSignature( - bytes32 hash, - address signer, - bytes memory signature - ) - internal - view - returns (bool isValid); } |