Update Exchange contract to use libraries
This commit is contained in:
parent
7eb64eb3dc
commit
ae859fa01e
@ -19,9 +19,11 @@ pragma solidity ^0.5.9;
|
|||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||||
|
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
|
||||||
import "./interfaces/IExchangeCore.sol";
|
import "./interfaces/IExchangeCore.sol";
|
||||||
import "./interfaces/IExchangeRichErrors.sol";
|
import "./interfaces/IExchangeRichErrors.sol";
|
||||||
import "./LibExchangeRichErrors.sol";
|
import "./LibExchangeRichErrors.sol";
|
||||||
@ -30,11 +32,14 @@ import "./MixinSignatureValidator.sol";
|
|||||||
|
|
||||||
|
|
||||||
contract MixinExchangeCore is
|
contract MixinExchangeCore is
|
||||||
|
LibEIP712ExchangeDomain,
|
||||||
IExchangeCore,
|
IExchangeCore,
|
||||||
LibMath,
|
|
||||||
MixinAssetProxyDispatcher,
|
MixinAssetProxyDispatcher,
|
||||||
MixinSignatureValidator
|
MixinSignatureValidator
|
||||||
{
|
{
|
||||||
|
using LibOrder for LibOrder.Order;
|
||||||
|
using LibSafeMath for uint256;
|
||||||
|
|
||||||
// Mapping of orderHash => amount of takerAsset already bought by maker
|
// Mapping of orderHash => amount of takerAsset already bought by maker
|
||||||
mapping (bytes32 => uint256) public filled;
|
mapping (bytes32 => uint256) public filled;
|
||||||
|
|
||||||
@ -121,7 +126,7 @@ contract MixinExchangeCore is
|
|||||||
returns (LibOrder.OrderInfo memory orderInfo)
|
returns (LibOrder.OrderInfo memory orderInfo)
|
||||||
{
|
{
|
||||||
// Compute the order hash
|
// Compute the order hash
|
||||||
orderInfo.orderHash = LibOrder.getOrderHash(order);
|
orderInfo.orderHash = order.getOrderHash(EIP712_EXCHANGE_DOMAIN_HASH);
|
||||||
|
|
||||||
// Fetch filled amount
|
// Fetch filled amount
|
||||||
orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash];
|
orderInfo.orderTakerAssetFilledAmount = filled[orderInfo.orderHash];
|
||||||
@ -200,8 +205,8 @@ contract MixinExchangeCore is
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Get amount of takerAsset to fill
|
// Get amount of takerAsset to fill
|
||||||
uint256 remainingTakerAssetAmount = _safeSub(order.takerAssetAmount, orderInfo.orderTakerAssetFilledAmount);
|
uint256 remainingTakerAssetAmount = order.takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount);
|
||||||
uint256 takerAssetFilledAmount = _min256(takerAssetFillAmount, remainingTakerAssetAmount);
|
uint256 takerAssetFilledAmount = LibSafeMath.min256(takerAssetFillAmount, remainingTakerAssetAmount);
|
||||||
|
|
||||||
// Compute proportional fill amounts
|
// Compute proportional fill amounts
|
||||||
fillResults = LibFillResults.calculateFillResults(order, takerAssetFilledAmount);
|
fillResults = LibFillResults.calculateFillResults(order, takerAssetFilledAmount);
|
||||||
@ -263,7 +268,7 @@ contract MixinExchangeCore is
|
|||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
// Update state
|
// Update state
|
||||||
filled[orderHash] = _safeAdd(orderTakerAssetFilledAmount, fillResults.takerAssetFilledAmount);
|
filled[orderHash] = orderTakerAssetFilledAmount.safeAdd(fillResults.takerAssetFilledAmount);
|
||||||
|
|
||||||
// Emit a Fill() event THE HARD WAY to avoid a stack overflow.
|
// Emit a Fill() event THE HARD WAY to avoid a stack overflow.
|
||||||
// All this logic is equivalent to:
|
// All this logic is equivalent to:
|
||||||
|
@ -29,6 +29,7 @@ contract MixinMatchOrders is
|
|||||||
IMatchOrders
|
IMatchOrders
|
||||||
{
|
{
|
||||||
using LibBytes for bytes;
|
using LibBytes for bytes;
|
||||||
|
using LibSafeMath for uint256;
|
||||||
|
|
||||||
/// @dev Match complementary orders that have a profitable spread.
|
/// @dev Match complementary orders that have a profitable spread.
|
||||||
/// Each order is filled at their respective price point, and
|
/// Each order is filled at their respective price point, and
|
||||||
@ -163,8 +164,8 @@ contract MixinMatchOrders is
|
|||||||
// AND
|
// AND
|
||||||
// <rightOrder.makerAssetAmount> / <rightOrder.takerAssetAmount> >= <leftOrder.takerAssetAmount> / <leftOrder.makerAssetAmount>
|
// <rightOrder.makerAssetAmount> / <rightOrder.takerAssetAmount> >= <leftOrder.takerAssetAmount> / <leftOrder.makerAssetAmount>
|
||||||
// These equations can be combined to get the following:
|
// These equations can be combined to get the following:
|
||||||
if (_safeMul(leftOrder.makerAssetAmount, rightOrder.makerAssetAmount) <
|
if (leftOrder.makerAssetAmount.safeMul(rightOrder.makerAssetAmount) <
|
||||||
_safeMul(leftOrder.takerAssetAmount, rightOrder.takerAssetAmount)) {
|
leftOrder.takerAssetAmount.safeMul(rightOrder.takerAssetAmount)) {
|
||||||
LibRichErrors._rrevert(LibExchangeRichErrors.NegativeSpreadError(
|
LibRichErrors._rrevert(LibExchangeRichErrors.NegativeSpreadError(
|
||||||
leftOrderInfo.orderHash,
|
leftOrderInfo.orderHash,
|
||||||
rightOrderInfo.orderHash
|
rightOrderInfo.orderHash
|
||||||
@ -245,33 +246,29 @@ contract MixinMatchOrders is
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Update the orderInfo structs with the updated takerAssetFilledAmount
|
// Update the orderInfo structs with the updated takerAssetFilledAmount
|
||||||
leftOrderInfo.orderTakerAssetFilledAmount = _safeAdd(
|
leftOrderInfo.orderTakerAssetFilledAmount = leftOrderInfo.orderTakerAssetFilledAmount.safeAdd(
|
||||||
leftOrderInfo.orderTakerAssetFilledAmount,
|
|
||||||
matchResults.left.takerAssetFilledAmount
|
matchResults.left.takerAssetFilledAmount
|
||||||
);
|
);
|
||||||
rightOrderInfo.orderTakerAssetFilledAmount = _safeAdd(
|
rightOrderInfo.orderTakerAssetFilledAmount = rightOrderInfo.orderTakerAssetFilledAmount.safeAdd(
|
||||||
rightOrderInfo.orderTakerAssetFilledAmount,
|
|
||||||
matchResults.right.takerAssetFilledAmount
|
matchResults.right.takerAssetFilledAmount
|
||||||
);
|
);
|
||||||
|
|
||||||
// Aggregate the new fill results with the previous fill results for the current orders.
|
// Aggregate the new fill results with the previous fill results for the current orders.
|
||||||
leftFillResults = LibFillResults._addFillResults(
|
leftFillResults = LibFillResults.addFillResults(
|
||||||
leftFillResults,
|
leftFillResults,
|
||||||
matchResults.left
|
matchResults.left
|
||||||
);
|
);
|
||||||
rightFillResults = LibFillResults._addFillResults(
|
rightFillResults = LibFillResults.addFillResults(
|
||||||
rightFillResults,
|
rightFillResults,
|
||||||
matchResults.right
|
matchResults.right
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update the profit in the left and right maker assets using the profits from
|
// Update the profit in the left and right maker assets using the profits from
|
||||||
// the match.
|
// the match.
|
||||||
batchMatchedFillResults.profitInLeftMakerAsset = _safeAdd(
|
batchMatchedFillResults.profitInLeftMakerAsset = batchMatchedFillResults.profitInLeftMakerAsset.safeAdd(
|
||||||
batchMatchedFillResults.profitInLeftMakerAsset,
|
|
||||||
matchResults.profitInLeftMakerAsset
|
matchResults.profitInLeftMakerAsset
|
||||||
);
|
);
|
||||||
batchMatchedFillResults.profitInRightMakerAsset = _safeAdd(
|
batchMatchedFillResults.profitInRightMakerAsset = batchMatchedFillResults.profitInRightMakerAsset.safeAdd(
|
||||||
batchMatchedFillResults.profitInRightMakerAsset,
|
|
||||||
matchResults.profitInRightMakerAsset
|
matchResults.profitInRightMakerAsset
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -368,7 +365,12 @@ contract MixinMatchOrders is
|
|||||||
takerAddress,
|
takerAddress,
|
||||||
rightSignature
|
rightSignature
|
||||||
);
|
);
|
||||||
_assertValidMatch(leftOrder, rightOrder);
|
_assertValidMatch(
|
||||||
|
leftOrder,
|
||||||
|
rightOrder,
|
||||||
|
leftOrderInfo,
|
||||||
|
rightOrderInfo
|
||||||
|
);
|
||||||
|
|
||||||
// Compute proportional fill amounts
|
// Compute proportional fill amounts
|
||||||
matchedFillResults = LibFillResults.calculateMatchedFillResults(
|
matchedFillResults = LibFillResults.calculateMatchedFillResults(
|
||||||
@ -493,10 +495,7 @@ contract MixinMatchOrders is
|
|||||||
leftOrder.takerFeeAssetData,
|
leftOrder.takerFeeAssetData,
|
||||||
takerAddress,
|
takerAddress,
|
||||||
leftFeeRecipientAddress,
|
leftFeeRecipientAddress,
|
||||||
_safeAdd(
|
matchedFillResults.left.takerFeePaid.safeAdd(matchedFillResults.right.takerFeePaid)
|
||||||
matchedFillResults.left.takerFeePaid,
|
|
||||||
matchedFillResults.right.takerFeePaid
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Right taker fee -> right fee recipient
|
// Right taker fee -> right fee recipient
|
||||||
|
@ -25,6 +25,7 @@ import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
|||||||
import "@0x/contracts-utils/contracts/src/ReentrancyGuard.sol";
|
import "@0x/contracts-utils/contracts/src/ReentrancyGuard.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
|
||||||
|
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
|
||||||
import "./interfaces/IWallet.sol";
|
import "./interfaces/IWallet.sol";
|
||||||
import "./interfaces/IEIP1271Wallet.sol";
|
import "./interfaces/IEIP1271Wallet.sol";
|
||||||
import "./interfaces/IExchangeRichErrors.sol";
|
import "./interfaces/IExchangeRichErrors.sol";
|
||||||
@ -35,11 +36,14 @@ import "./MixinTransactions.sol";
|
|||||||
|
|
||||||
contract MixinSignatureValidator is
|
contract MixinSignatureValidator is
|
||||||
ReentrancyGuard,
|
ReentrancyGuard,
|
||||||
|
LibEIP712ExchangeDomain,
|
||||||
LibEIP1271,
|
LibEIP1271,
|
||||||
ISignatureValidator,
|
ISignatureValidator,
|
||||||
MixinTransactions
|
MixinTransactions
|
||||||
{
|
{
|
||||||
using LibBytes for bytes;
|
using LibBytes for bytes;
|
||||||
|
using LibOrder for LibOrder.Order;
|
||||||
|
using LibZeroExTransaction for LibZeroExTransaction.ZeroExTransaction;
|
||||||
|
|
||||||
// Magic bytes to be returned by `Wallet` signature type validators.
|
// Magic bytes to be returned by `Wallet` signature type validators.
|
||||||
// bytes4(keccak256("isValidWalletSignature(bytes32,address,bytes)"))
|
// bytes4(keccak256("isValidWalletSignature(bytes32,address,bytes)"))
|
||||||
@ -134,7 +138,7 @@ contract MixinSignatureValidator is
|
|||||||
view
|
view
|
||||||
returns (bool isValid)
|
returns (bool isValid)
|
||||||
{
|
{
|
||||||
bytes32 orderHash = LibOrder.getOrderHash(order);
|
bytes32 orderHash = order.getOrderHash(EIP712_EXCHANGE_DOMAIN_HASH);
|
||||||
return _isValidOrderWithHashSignature(
|
return _isValidOrderWithHashSignature(
|
||||||
order,
|
order,
|
||||||
orderHash,
|
orderHash,
|
||||||
@ -154,7 +158,7 @@ contract MixinSignatureValidator is
|
|||||||
view
|
view
|
||||||
returns (bool isValid)
|
returns (bool isValid)
|
||||||
{
|
{
|
||||||
bytes32 transactionHash = LibZeroExTransaction.getTransactionHash(transaction);
|
bytes32 transactionHash = transaction.getTransactionHash(EIP712_EXCHANGE_DOMAIN_HASH);
|
||||||
isValid = _isValidTransactionWithHashSignature(
|
isValid = _isValidTransactionWithHashSignature(
|
||||||
transaction,
|
transaction,
|
||||||
transactionHash,
|
transactionHash,
|
||||||
|
@ -20,6 +20,7 @@ pragma solidity ^0.5.9;
|
|||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
|
||||||
|
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
||||||
import "./interfaces/IExchangeRichErrors.sol";
|
import "./interfaces/IExchangeRichErrors.sol";
|
||||||
import "./interfaces/ITransactions.sol";
|
import "./interfaces/ITransactions.sol";
|
||||||
@ -28,9 +29,12 @@ import "./LibExchangeRichErrors.sol";
|
|||||||
|
|
||||||
|
|
||||||
contract MixinTransactions is
|
contract MixinTransactions is
|
||||||
|
LibEIP712ExchangeDomain,
|
||||||
ISignatureValidator,
|
ISignatureValidator,
|
||||||
ITransactions
|
ITransactions
|
||||||
{
|
{
|
||||||
|
using LibZeroExTransaction for LibZeroExTransaction.ZeroExTransaction;
|
||||||
|
|
||||||
// Mapping of transaction hash => executed
|
// Mapping of transaction hash => executed
|
||||||
// This prevents transactions from being executed more than once.
|
// This prevents transactions from being executed more than once.
|
||||||
mapping (bytes32 => bool) public transactionsExecuted;
|
mapping (bytes32 => bool) public transactionsExecuted;
|
||||||
@ -82,7 +86,7 @@ contract MixinTransactions is
|
|||||||
internal
|
internal
|
||||||
returns (bytes memory)
|
returns (bytes memory)
|
||||||
{
|
{
|
||||||
bytes32 transactionHash = LibZeroExTransaction.getTransactionHash(transaction);
|
bytes32 transactionHash = transaction.getTransactionHash(EIP712_EXCHANGE_DOMAIN_HASH);
|
||||||
|
|
||||||
// Check transaction is not expired
|
// Check transaction is not expired
|
||||||
// solhint-disable-next-line not-rely-on-time
|
// solhint-disable-next-line not-rely-on-time
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
pragma solidity ^0.5.9;
|
pragma solidity ^0.5.9;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||||
|
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
|
||||||
import "./interfaces/IExchangeCore.sol";
|
import "./interfaces/IExchangeCore.sol";
|
||||||
import "./interfaces/IExchangeRichErrors.sol";
|
import "./interfaces/IExchangeRichErrors.sol";
|
||||||
@ -33,6 +35,8 @@ contract MixinWrapperFunctions is
|
|||||||
IWrapperFunctions,
|
IWrapperFunctions,
|
||||||
MixinExchangeCore
|
MixinExchangeCore
|
||||||
{
|
{
|
||||||
|
using LibSafeMath for uint256;
|
||||||
|
|
||||||
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
|
/// @dev Fills the input order. Reverts if exact takerAssetFillAmount not filled.
|
||||||
/// @param order Order struct containing order specifications.
|
/// @param order Order struct containing order specifications.
|
||||||
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
/// @param takerAssetFillAmount Desired amount of takerAsset to sell.
|
||||||
@ -186,7 +190,7 @@ contract MixinWrapperFunctions is
|
|||||||
orders[i].takerAssetData = takerAssetData;
|
orders[i].takerAssetData = takerAssetData;
|
||||||
|
|
||||||
// Calculate the remaining amount of takerAsset to sell
|
// Calculate the remaining amount of takerAsset to sell
|
||||||
uint256 remainingTakerAssetFillAmount = _safeSub(takerAssetFillAmount, fillResults.takerAssetFilledAmount);
|
uint256 remainingTakerAssetFillAmount = takerAssetFillAmount.safeSub(fillResults.takerAssetFilledAmount);
|
||||||
|
|
||||||
// Attempt to sell the remaining amount of takerAsset
|
// Attempt to sell the remaining amount of takerAsset
|
||||||
LibFillResults.FillResults memory singleFillResults = fillOrderNoThrow(
|
LibFillResults.FillResults memory singleFillResults = fillOrderNoThrow(
|
||||||
@ -196,7 +200,7 @@ contract MixinWrapperFunctions is
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Update amounts filled and fees paid by maker and taker
|
// Update amounts filled and fees paid by maker and taker
|
||||||
fillResults = LibFillResults._addFillResults(fillResults, singleFillResults);
|
fillResults = LibFillResults.addFillResults(fillResults, singleFillResults);
|
||||||
|
|
||||||
// Stop execution if the entire amount of takerAsset has been sold
|
// Stop execution if the entire amount of takerAsset has been sold
|
||||||
if (fillResults.takerAssetFilledAmount >= takerAssetFillAmount) {
|
if (fillResults.takerAssetFilledAmount >= takerAssetFillAmount) {
|
||||||
@ -230,11 +234,11 @@ contract MixinWrapperFunctions is
|
|||||||
orders[i].makerAssetData = makerAssetData;
|
orders[i].makerAssetData = makerAssetData;
|
||||||
|
|
||||||
// Calculate the remaining amount of makerAsset to buy
|
// Calculate the remaining amount of makerAsset to buy
|
||||||
uint256 remainingMakerAssetFillAmount = _safeSub(makerAssetFillAmount, fillResults.makerAssetFilledAmount);
|
uint256 remainingMakerAssetFillAmount = makerAssetFillAmount.safeSub(fillResults.makerAssetFilledAmount);
|
||||||
|
|
||||||
// Convert the remaining amount of makerAsset to buy into remaining amount
|
// Convert the remaining amount of makerAsset to buy into remaining amount
|
||||||
// of takerAsset to sell, assuming entire amount can be sold in the current order
|
// of takerAsset to sell, assuming entire amount can be sold in the current order
|
||||||
uint256 remainingTakerAssetFillAmount = _getPartialAmountFloor(
|
uint256 remainingTakerAssetFillAmount = LibMath.getPartialAmountFloor(
|
||||||
orders[i].takerAssetAmount,
|
orders[i].takerAssetAmount,
|
||||||
orders[i].makerAssetAmount,
|
orders[i].makerAssetAmount,
|
||||||
remainingMakerAssetFillAmount
|
remainingMakerAssetFillAmount
|
||||||
@ -248,7 +252,7 @@ contract MixinWrapperFunctions is
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Update amounts filled and fees paid by maker and taker
|
// Update amounts filled and fees paid by maker and taker
|
||||||
fillResults = LibFillResults._addFillResults(fillResults, singleFillResults);
|
fillResults = LibFillResults.addFillResults(fillResults, singleFillResults);
|
||||||
|
|
||||||
// Stop execution if the entire amount of makerAsset has been bought
|
// Stop execution if the entire amount of makerAsset has been bought
|
||||||
if (fillResults.makerAssetFilledAmount >= makerAssetFillAmount) {
|
if (fillResults.makerAssetFilledAmount >= makerAssetFillAmount) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user