diff options
Diffstat (limited to 'packages/contracts/src')
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/Forwarder.sol (renamed from packages/contracts/src/2.0.0/forwarder/Forwarder.sol) | 0 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/MixinAssets.sol (renamed from packages/contracts/src/2.0.0/forwarder/MixinAssets.sol) | 10 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol (renamed from packages/contracts/src/2.0.0/forwarder/MixinExchangeWrapper.sol) | 8 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/MixinForwarderCore.sol (renamed from packages/contracts/src/2.0.0/forwarder/MixinForwarderCore.sol) | 8 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/MixinWeth.sol (renamed from packages/contracts/src/2.0.0/forwarder/MixinWeth.sol) | 2 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/interfaces/IAssets.sol (renamed from packages/contracts/src/2.0.0/forwarder/interfaces/IAssets.sol) | 0 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/interfaces/IForwarder.sol (renamed from packages/contracts/src/2.0.0/forwarder/interfaces/IForwarder.sol) | 0 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/interfaces/IForwarderCore.sol (renamed from packages/contracts/src/2.0.0/forwarder/interfaces/IForwarderCore.sol) | 4 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/libs/LibConstants.sol (renamed from packages/contracts/src/2.0.0/forwarder/libs/LibConstants.sol) | 8 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/libs/LibForwarderErrors.sol (renamed from packages/contracts/src/2.0.0/forwarder/libs/LibForwarderErrors.sol) | 2 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MAssets.sol (renamed from packages/contracts/src/2.0.0/forwarder/mixins/MAssets.sol) | 0 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MExchangeWrapper.sol (renamed from packages/contracts/src/2.0.0/forwarder/mixins/MExchangeWrapper.sol) | 4 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MWeth.sol (renamed from packages/contracts/src/2.0.0/forwarder/mixins/MWeth.sol) | 0 | ||||
-rw-r--r-- | packages/contracts/src/2.0.0/extensions/OrderValidator/OrderValidator.sol | 218 |
14 files changed, 241 insertions, 23 deletions
diff --git a/packages/contracts/src/2.0.0/forwarder/Forwarder.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/Forwarder.sol index 6b17bb29b..6b17bb29b 100644 --- a/packages/contracts/src/2.0.0/forwarder/Forwarder.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/Forwarder.sol diff --git a/packages/contracts/src/2.0.0/forwarder/MixinAssets.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinAssets.sol index e06f9a8e3..d6a38aa6e 100644 --- a/packages/contracts/src/2.0.0/forwarder/MixinAssets.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinAssets.sol @@ -18,10 +18,10 @@ pragma solidity 0.4.24; -import "../utils/LibBytes/LibBytes.sol"; -import "../utils/Ownable/Ownable.sol"; -import "../tokens/ERC20Token/IERC20Token.sol"; -import "../tokens/ERC721Token/IERC721Token.sol"; +import "../../utils/LibBytes/LibBytes.sol"; +import "../../utils/Ownable/Ownable.sol"; +import "../../tokens/ERC20Token/IERC20Token.sol"; +import "../../tokens/ERC721Token/IERC721Token.sol"; import "./libs/LibConstants.sol"; import "./mixins/MAssets.sol"; @@ -67,7 +67,7 @@ contract MixinAssets is } else if (proxyId == ERC721_DATA_ID) { transferERC721Token(assetData, amount); } else { - revert("UNSUPPORTED_TOKEN_PROXY"); + revert("UNSUPPORTED_ASSET_PROXY"); } } diff --git a/packages/contracts/src/2.0.0/forwarder/MixinExchangeWrapper.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol index 4584bb840..218713d3c 100644 --- a/packages/contracts/src/2.0.0/forwarder/MixinExchangeWrapper.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol @@ -21,10 +21,10 @@ pragma experimental ABIEncoderV2; import "./libs/LibConstants.sol"; import "./mixins/MExchangeWrapper.sol"; -import "../protocol/Exchange/libs/LibAbiEncoder.sol"; -import "../protocol/Exchange/libs/LibOrder.sol"; -import "../protocol/Exchange/libs/LibFillResults.sol"; -import "../protocol/Exchange/libs/LibMath.sol"; +import "../../protocol/Exchange/libs/LibAbiEncoder.sol"; +import "../../protocol/Exchange/libs/LibOrder.sol"; +import "../../protocol/Exchange/libs/LibFillResults.sol"; +import "../../protocol/Exchange/libs/LibMath.sol"; contract MixinExchangeWrapper is diff --git a/packages/contracts/src/2.0.0/forwarder/MixinForwarderCore.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinForwarderCore.sol index 93cbf79be..42cec4d36 100644 --- a/packages/contracts/src/2.0.0/forwarder/MixinForwarderCore.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinForwarderCore.sol @@ -24,10 +24,10 @@ import "./mixins/MWeth.sol"; import "./mixins/MAssets.sol"; import "./mixins/MExchangeWrapper.sol"; import "./interfaces/IForwarderCore.sol"; -import "../utils/LibBytes/LibBytes.sol"; -import "../protocol/Exchange/libs/LibOrder.sol"; -import "../protocol/Exchange/libs/LibFillResults.sol"; -import "../protocol/Exchange/libs/LibMath.sol"; +import "../../utils/LibBytes/LibBytes.sol"; +import "../../protocol/Exchange/libs/LibOrder.sol"; +import "../../protocol/Exchange/libs/LibFillResults.sol"; +import "../../protocol/Exchange/libs/LibMath.sol"; contract MixinForwarderCore is diff --git a/packages/contracts/src/2.0.0/forwarder/MixinWeth.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinWeth.sol index e07940776..93e85e599 100644 --- a/packages/contracts/src/2.0.0/forwarder/MixinWeth.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinWeth.sol @@ -18,7 +18,7 @@ pragma solidity 0.4.24; -import "../protocol/Exchange/libs/LibMath.sol"; +import "../../protocol/Exchange/libs/LibMath.sol"; import "./libs/LibConstants.sol"; import "./mixins/MWeth.sol"; diff --git a/packages/contracts/src/2.0.0/forwarder/interfaces/IAssets.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/interfaces/IAssets.sol index 1e034c003..1e034c003 100644 --- a/packages/contracts/src/2.0.0/forwarder/interfaces/IAssets.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/interfaces/IAssets.sol diff --git a/packages/contracts/src/2.0.0/forwarder/interfaces/IForwarder.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/interfaces/IForwarder.sol index f5a26e2ba..f5a26e2ba 100644 --- a/packages/contracts/src/2.0.0/forwarder/interfaces/IForwarder.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/interfaces/IForwarder.sol diff --git a/packages/contracts/src/2.0.0/forwarder/interfaces/IForwarderCore.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/interfaces/IForwarderCore.sol index 3ecbb133b..74c7da01d 100644 --- a/packages/contracts/src/2.0.0/forwarder/interfaces/IForwarderCore.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/interfaces/IForwarderCore.sol @@ -19,8 +19,8 @@ pragma solidity 0.4.24; pragma experimental ABIEncoderV2; -import "../../protocol/Exchange/libs/LibOrder.sol"; -import "../../protocol/Exchange/libs/LibFillResults.sol"; +import "../../../protocol/Exchange/libs/LibOrder.sol"; +import "../../../protocol/Exchange/libs/LibFillResults.sol"; contract IForwarderCore { diff --git a/packages/contracts/src/2.0.0/forwarder/libs/LibConstants.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/libs/LibConstants.sol index fb9691fe8..704e42ce3 100644 --- a/packages/contracts/src/2.0.0/forwarder/libs/LibConstants.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/libs/LibConstants.sol @@ -18,10 +18,10 @@ pragma solidity 0.4.24; -import "../../utils/LibBytes/LibBytes.sol"; -import "../../protocol/Exchange/interfaces/IExchange.sol"; -import "../../tokens/EtherToken/IEtherToken.sol"; -import "../../tokens/ERC20Token/IERC20Token.sol"; +import "../../../utils/LibBytes/LibBytes.sol"; +import "../../../protocol/Exchange/interfaces/IExchange.sol"; +import "../../../tokens/EtherToken/IEtherToken.sol"; +import "../../../tokens/ERC20Token/IERC20Token.sol"; contract LibConstants { diff --git a/packages/contracts/src/2.0.0/forwarder/libs/LibForwarderErrors.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/libs/LibForwarderErrors.sol index cdfb77a0b..fb3ade1db 100644 --- a/packages/contracts/src/2.0.0/forwarder/libs/LibForwarderErrors.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/libs/LibForwarderErrors.sol @@ -27,7 +27,7 @@ contract LibForwarderErrors { string constant OVERSOLD_WETH = "OVERSOLD_WETH"; // More WETH sold than provided with current message call. string constant COMPLETE_FILL_FAILED = "COMPLETE_FILL_FAILED"; // Desired purchase amount not completely filled (required for ZRX fees only). string constant TRANSFER_FAILED = "TRANSFER_FAILED"; // Asset transfer failed. - string constant UNSUPPORTED_TOKEN_PROXY = "UNSUPPORTED_TOKEN_PROXY"; // Proxy in assetData not supported. + string constant UNSUPPORTED_ASSET_PROXY = "UNSUPPORTED_ASSET_PROXY"; // Proxy in assetData not supported. string constant DEFAULT_FUNCTION_WETH_CONTRACT_ONLY = "DEFAULT_FUNCTION_WETH_CONTRACT_ONLY"; // Fallback function may only be used for WETH withdrawals. string constant INVALID_MSG_VALUE = "INVALID_MSG_VALUE"; // msg.value must be greater than 0. string constant INVALID_AMOUNT = "INVALID_AMOUNT"; // Amount must equal 1. diff --git a/packages/contracts/src/2.0.0/forwarder/mixins/MAssets.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MAssets.sol index 83636432a..83636432a 100644 --- a/packages/contracts/src/2.0.0/forwarder/mixins/MAssets.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MAssets.sol diff --git a/packages/contracts/src/2.0.0/forwarder/mixins/MExchangeWrapper.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MExchangeWrapper.sol index 360dea0e4..13c26b03a 100644 --- a/packages/contracts/src/2.0.0/forwarder/mixins/MExchangeWrapper.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MExchangeWrapper.sol @@ -19,8 +19,8 @@ pragma solidity 0.4.24; pragma experimental ABIEncoderV2; -import "../../protocol/Exchange/libs/LibOrder.sol"; -import "../../protocol/Exchange/libs/LibFillResults.sol"; +import "../../../protocol/Exchange/libs/LibOrder.sol"; +import "../../../protocol/Exchange/libs/LibFillResults.sol"; contract MExchangeWrapper { diff --git a/packages/contracts/src/2.0.0/forwarder/mixins/MWeth.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MWeth.sol index 88e77be4e..88e77be4e 100644 --- a/packages/contracts/src/2.0.0/forwarder/mixins/MWeth.sol +++ b/packages/contracts/src/2.0.0/extensions/Forwarder/mixins/MWeth.sol diff --git a/packages/contracts/src/2.0.0/extensions/OrderValidator/OrderValidator.sol b/packages/contracts/src/2.0.0/extensions/OrderValidator/OrderValidator.sol new file mode 100644 index 000000000..a18345245 --- /dev/null +++ b/packages/contracts/src/2.0.0/extensions/OrderValidator/OrderValidator.sol @@ -0,0 +1,218 @@ +/* + + 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"; +import "../../tokens/ERC20Token/IERC20Token.sol"; +import "../../tokens/ERC721Token/IERC721Token.sol"; +import "../../utils/LibBytes/LibBytes.sol"; + + +contract OrderValidator { + + bytes4 constant internal ERC20_DATA_ID = bytes4(keccak256("ERC20Token(address)")); + bytes4 constant internal ERC721_DATA_ID = bytes4(keccak256("ERC721Token(address,uint256)")); + + using LibBytes for bytes; + + struct TraderInfo { + uint256 makerBalance; // Maker's balance of makerAsset + uint256 makerAllowance; // Maker's allowance to corresponding AssetProxy + uint256 takerBalance; // Taker's balance of takerAsset + uint256 takerAllowance; // Taker's allowance to corresponding AssetProxy + uint256 makerZrxBalance; // Maker's balance of ZRX + uint256 makerZrxAllowance; // Maker's allowance of ZRX to ERC20Proxy + uint256 takerZrxBalance; // Taker's balance of ZRX + uint256 takerZrxAllowance; // Taker's allowance of ZRX to ERC20Proxy + } + + // solhint-disable var-name-mixedcase + IExchange internal EXCHANGE; + bytes internal ZRX_ASSET_DATA; + // solhint-enable var-name-mixedcase + + constructor (address _exchange, bytes memory _zrxAssetData) + public + { + EXCHANGE = IExchange(_exchange); + ZRX_ASSET_DATA = _zrxAssetData; + } + + /// @dev Fetches information for order and maker/taker of order. + /// @param order The order structure. + /// @param takerAddress Address that will be filling the order. + /// @return OrderInfo and TraderInfo instances for given order. + function getOrderAndTraderInfo(LibOrder.Order memory order, address takerAddress) + public + view + returns (LibOrder.OrderInfo memory orderInfo, TraderInfo memory traderInfo) + { + orderInfo = EXCHANGE.getOrderInfo(order); + traderInfo = getTraderInfo(order, takerAddress); + return (orderInfo, traderInfo); + } + + /// @dev Fetches information for all passed in orders and the makers/takers of each order. + /// @param orders Array of order specifications. + /// @param takerAddresses Array of taker addresses corresponding to each order. + /// @return Arrays of OrderInfo and TraderInfo instances that correspond to each order. + function getOrdersAndTradersInfo(LibOrder.Order[] memory orders, address[] memory takerAddresses) + public + view + returns (LibOrder.OrderInfo[] memory ordersInfo, TraderInfo[] memory tradersInfo) + { + ordersInfo = EXCHANGE.getOrdersInfo(orders); + tradersInfo = getTradersInfo(orders, takerAddresses); + return (ordersInfo, tradersInfo); + } + + /// @dev Fetches balance and allowances for maker and taker of order. + /// @param order The order structure. + /// @param takerAddress Address that will be filling the order. + /// @return Balances and allowances of maker and taker of order. + function getTraderInfo(LibOrder.Order memory order, address takerAddress) + public + view + returns (TraderInfo memory traderInfo) + { + (traderInfo.makerBalance, traderInfo.makerAllowance) = getBalanceAndAllowance(order.makerAddress, order.makerAssetData); + (traderInfo.takerBalance, traderInfo.takerAllowance) = getBalanceAndAllowance(takerAddress, order.takerAssetData); + bytes memory zrxAssetData = ZRX_ASSET_DATA; + (traderInfo.makerZrxBalance, traderInfo.makerZrxAllowance) = getBalanceAndAllowance(order.makerAddress, zrxAssetData); + (traderInfo.takerZrxBalance, traderInfo.takerZrxAllowance) = getBalanceAndAllowance(takerAddress, zrxAssetData); + return traderInfo; + } + + /// @dev Fetches balances and allowances of maker and taker for each provided order. + /// @param orders Array of order specifications. + /// @param takerAddresses Array of taker addresses corresponding to each order. + /// @return Array of balances and allowances for maker and taker of each order. + function getTradersInfo(LibOrder.Order[] memory orders, address[] memory takerAddresses) + public + view + returns (TraderInfo[] memory) + { + uint256 ordersLength = orders.length; + TraderInfo[] memory tradersInfo = new TraderInfo[](ordersLength); + for (uint256 i = 0; i != ordersLength; i++) { + tradersInfo[i] = getTraderInfo(orders[i], takerAddresses[i]); + } + return tradersInfo; + } + + /// @dev Fetches token balances and allowances of an address to given assetProxy. Supports ERC20 and ERC721. + /// @param target Address to fetch balances and allowances of. + /// @param assetData Encoded data that can be decoded by a specified proxy contract when transferring asset. + /// @return Balance of asset and allowance set to given proxy of asset. + /// For ERC721 tokens, these values will always be 1 or 0. + function getBalanceAndAllowance(address target, bytes memory assetData) + public + view + returns (uint256 balance, uint256 allowance) + { + bytes4 assetProxyId = assetData.readBytes4(0); + address token = assetData.readAddress(16); + address assetProxy = EXCHANGE.getAssetProxy(assetProxyId); + + if (assetProxyId == ERC20_DATA_ID) { + // Query balance + balance = IERC20Token(token).balanceOf(target); + + // Query allowance + allowance = IERC20Token(token).allowance(target, assetProxy); + } else if (assetProxyId == ERC721_DATA_ID) { + uint256 tokenId = assetData.readUint256(36); + + // Query owner of tokenId + address owner = getERC721TokenOwner(token, tokenId); + + // Set balance to 1 if tokenId is owned by target + balance = target == owner ? 1 : 0; + + // Check if ERC721Proxy is approved to spend tokenId + bool isApproved = IERC721Token(token).isApprovedForAll(target, assetProxy) || IERC721Token(token).getApproved(tokenId) == assetProxy; + + // Set alowance to 1 if ERC721Proxy is approved to spend tokenId + allowance = isApproved ? 1 : 0; + } else { + revert("UNSUPPORTED_ASSET_PROXY"); + } + return (balance, allowance); + } + + /// @dev Fetches token balances and allowances of an address for each given assetProxy. Supports ERC20 and ERC721. + /// @param target Address to fetch balances and allowances of. + /// @param assetData Array of encoded byte arrays that can be decoded by a specified proxy contract when transferring asset. + /// @return Balances and allowances of assets. + /// For ERC721 tokens, these values will always be 1 or 0. + function getBalancesAndAllowances(address target, bytes[] memory assetData) + public + view + returns (uint256[] memory, uint256[] memory) + { + uint256 length = assetData.length; + uint256[] memory balances = new uint256[](length); + uint256[] memory allowances = new uint256[](length); + for (uint256 i = 0; i != length; i++) { + (balances[i], allowances[i]) = getBalanceAndAllowance(target, assetData[i]); + } + return (balances, allowances); + } + + /// @dev Calls `token.ownerOf(tokenId)`, but returns a null owner instead of reverting on an unowned token. + /// @param token Address of ERC721 token. + /// @param tokenId The identifier for the specific NFT. + /// @return Owner of tokenId or null address if unowned. + function getERC721TokenOwner(address token, uint256 tokenId) + public + view + returns (address owner) + { + assembly { + // load free memory pointer + let cdStart := mload(64) + + // bytes4(keccak256(ownerOf(uint256))) = 0x6352211e + mstore(cdStart, 0x6352211e00000000000000000000000000000000000000000000000000000000) + mstore(add(cdStart, 4), tokenId) + + // staticcall `ownerOf(tokenId)` + // `ownerOf` will revert if tokenId is not owned + let success := staticcall( + gas, // forward all gas + token, // call token contract + cdStart, // start of calldata + 36, // length of input is 36 bytes + cdStart, // write output over input + 32 // size of output is 32 bytes + ) + + // Success implies that tokenId is owned + // Copy owner from return data if successful + if success { + owner := mload(cdStart) + } + } + + // Owner initialized to address(0), no need to modify if call is unsuccessful + return owner; + } +} |