Fixed the bug and moved "contracts-tests" to "contracts-integrations"

This commit is contained in:
Alex Towle
2019-12-17 17:17:54 -08:00
parent 51ca3109eb
commit 47c3ed9705
25 changed files with 436 additions and 544 deletions

View File

@@ -35,8 +35,8 @@ contract DevUtils is
OrderValidationUtils,
LibTransactionDecoder,
LibEIP712ExchangeDomain,
EthBalanceChecker,
OrderTransferSimulationUtils
EthBalanceChecker
// OrderTransferSimulationUtils
{
constructor (address _exchange)
public

View File

@@ -147,7 +147,7 @@ contract LibAssetData {
balance = scaledBalance;
}
}
}
}
// Balance will be 0 if assetProxyId is unknown
return balance;
@@ -316,7 +316,7 @@ contract LibAssetData {
return (balances, allowances);
}
/// @dev Decode AssetProxy identifier
/// @dev Decode AssetProxy identifier
/// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
/// @return The AssetProxy identifier
function decodeAssetProxyId(bytes memory assetData)
@@ -353,7 +353,7 @@ contract LibAssetData {
/// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset.
/// @return The AssetProxy identifier, and the address of the ERC-20
/// @return The AssetProxy identifier, and the address of the ERC-20
/// contract hosting this asset.
function decodeERC20AssetData(bytes memory assetData)
public
@@ -591,7 +591,7 @@ contract LibAssetData {
function revertIfInvalidAssetData(bytes memory assetData)
public
pure
pure
{
bytes4 assetProxyId = assetData.readBytes4(0);

View File

@@ -31,6 +31,8 @@ import "@0x/contracts-utils/contracts/src/LibBytes.sol";
contract OrderTransferSimulationUtils is
LibExchangeRichErrorDecoder
{
bool second;
using LibBytes for bytes;
enum OrderTransferResults {
@@ -54,6 +56,52 @@ contract OrderTransferSimulationUtils is
_EXCHANGE = IExchange(_exchange);
}
/// @dev Simulates the maker transfers within an order and returns the index of the first failed transfer.
/// @param order The order to simulate transfers for.
/// @param takerAddress The address of the taker that will fill the order.
/// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill.
/// @return The index of the first failed transfer (or 4 if all transfers are successful).
function getSimulatedOrderMakerTransferResults(
LibOrder.Order memory order,
address takerAddress,
uint256 takerAssetFillAmount
)
public
returns (OrderTransferResults orderTransferResults)
{
LibFillResults.FillResults memory fillResults = LibFillResults.calculateFillResultsTrace(
order,
takerAssetFillAmount,
_EXCHANGE.protocolFeeMultiplier(),
tx.gasprice,
second
);
bytes[] memory assetData = new bytes[](2);
address[] memory fromAddresses = new address[](2);
address[] memory toAddresses = new address[](2);
uint256[] memory amounts = new uint256[](2);
// Transfer `makerAsset` from maker to taker
assetData[0] = order.makerAssetData;
fromAddresses[0] = order.makerAddress;
toAddresses[0] = takerAddress;
amounts[0] = fillResults.makerAssetFilledAmount;
// Transfer `makerFeeAsset` from maker to feeRecipient
assetData[1] = order.makerFeeAssetData;
fromAddresses[1] = order.makerAddress;
toAddresses[1] = order.feeRecipientAddress;
amounts[1] = fillResults.makerFeePaid;
return _simulateTransferFromCalls(
assetData,
fromAddresses,
toAddresses,
amounts
);
}
/// @dev Simulates all of the transfers within an order and returns the index of the first failed transfer.
/// @param order The order to simulate transfers for.
/// @param takerAddress The address of the taker that will fill the order.
@@ -104,6 +152,54 @@ contract OrderTransferSimulationUtils is
toAddresses[3] = order.feeRecipientAddress;
amounts[3] = fillResults.makerFeePaid;
return _simulateTransferFromCalls(
assetData,
fromAddresses,
toAddresses,
amounts
);
}
/// @dev Simulates all of the transfers for each given order and returns the indices of each first failed transfer.
/// @param orders Array of orders to individually simulate transfers for.
/// @param takerAddresses Array of addresses of takers that will fill each order.
/// @param takerAssetFillAmounts Array of amounts of takerAsset that will be filled for each order.
/// @return The indices of the first failed transfer (or 4 if all transfers are successful) for each order.
function getSimulatedOrdersTransferResults(
LibOrder.Order[] memory orders,
address[] memory takerAddresses,
uint256[] memory takerAssetFillAmounts
)
public
returns (OrderTransferResults[] memory orderTransferResults)
{
uint256 length = orders.length;
orderTransferResults = new OrderTransferResults[](length);
for (uint256 i = 0; i != length; i++) {
orderTransferResults[i] = getSimulatedOrderTransferResults(
orders[i],
takerAddresses[i],
takerAssetFillAmounts[i]
);
}
return orderTransferResults;
}
/// @dev Makes the simulation call with information about the transfers and processes
/// the returndata.
/// @param assetData The assetdata to use to make transfers.
/// @param fromAddresses The addresses to transfer funds.
/// @param toAddresses The addresses that will receive funds
/// @param amounts The amounts involved in the transfer.
function _simulateTransferFromCalls(
bytes[] memory assetData,
address[] memory fromAddresses,
address[] memory toAddresses,
uint256[] memory amounts
)
internal
returns (OrderTransferResults orderTransferResults)
{
// Encode data for `simulateDispatchTransferFromCalls(assetData, fromAddresses, toAddresses, amounts)`
bytes memory simulateDispatchTransferFromCallsData = abi.encodeWithSelector(
IExchange(address(0)).simulateDispatchTransferFromCalls.selector,
@@ -132,29 +228,4 @@ contract OrderTransferSimulationUtils is
revert("UNKNOWN_RETURN_DATA");
}
}
/// @dev Simulates all of the transfers for each given order and returns the indices of each first failed transfer.
/// @param orders Array of orders to individually simulate transfers for.
/// @param takerAddresses Array of addresses of takers that will fill each order.
/// @param takerAssetFillAmounts Array of amounts of takerAsset that will be filled for each order.
/// @return The indices of the first failed transfer (or 4 if all transfers are successful) for each order.
function getSimulatedOrdersTransferResults(
LibOrder.Order[] memory orders,
address[] memory takerAddresses,
uint256[] memory takerAssetFillAmounts
)
public
returns (OrderTransferResults[] memory orderTransferResults)
{
uint256 length = orders.length;
orderTransferResults = new OrderTransferResults[](length);
for (uint256 i = 0; i != length; i++) {
orderTransferResults[i] = getSimulatedOrderTransferResults(
orders[i],
takerAddresses[i],
takerAssetFillAmounts[i]
);
}
return orderTransferResults;
}
}

View File

@@ -25,10 +25,12 @@ import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "./LibAssetData.sol";
import "./OrderTransferSimulationUtils.sol";
contract OrderValidationUtils is
LibAssetData
LibAssetData,
OrderTransferSimulationUtils
{
using LibBytes for bytes;
using LibSafeMath for uint256;
@@ -50,7 +52,6 @@ contract OrderValidationUtils is
/// amount of each asset that can be filled.
function getOrderRelevantState(LibOrder.Order memory order, bytes memory signature)
public
view
returns (
LibOrder.OrderInfo memory orderInfo,
uint256 fillableTakerAssetAmount,
@@ -99,7 +100,6 @@ contract OrderValidationUtils is
} else {
// Get the transferable amount of the `makerFeeAsset`
uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(makerAddress, order.makerFeeAssetData);
uint256 transferableMakerToTakerAmount = LibMath.getPartialAmountFloor(
transferableMakerAssetAmount,
order.makerAssetAmount,
@@ -120,6 +120,13 @@ contract OrderValidationUtils is
transferableTakerAssetAmount
);
// Execute the maker transfers.
fillableTakerAssetAmount = getSimulatedOrderMakerTransferResults(
order,
order.takerAddress,
fillableTakerAssetAmount
) == OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0;
return (orderInfo, fillableTakerAssetAmount, isValidSignature);
}
@@ -135,7 +142,6 @@ contract OrderValidationUtils is
/// the `takerAssetData` to get the final amount of each asset that can be filled.
function getOrderRelevantStates(LibOrder.Order[] memory orders, bytes[] memory signatures)
public
view
returns (
LibOrder.OrderInfo[] memory ordersInfo,
uint256[] memory fillableTakerAssetAmounts,
@@ -148,6 +154,10 @@ contract OrderValidationUtils is
isValidSignature = new bool[](length);
for (uint256 i = 0; i != length; i++) {
if (i == 1) {
second = true;
}
(ordersInfo[i], fillableTakerAssetAmounts[i], isValidSignature[i]) = getOrderRelevantState(
orders[i],
signatures[i]