Update transferEthFeeAndRefund, add check to ERC721 transfer

This commit is contained in:
Amir Bandeali
2018-07-10 15:41:33 -07:00
parent 814518dd80
commit 6fb157488c
6 changed files with 54 additions and 26 deletions

View File

@@ -21,7 +21,7 @@ pragma solidity 0.4.24;
/// This contract is intended to serve as a reference, but is not actually used for efficiency reasons.
contract MixinErrorMessages {
contract LibForwarderErrors {
string constant FEE_PERCENTAGE_TOO_LARGE = "FEE_PROPORTION_TOO_LARGE"; // Provided fee percentage greater than 5%.
string constant MAX_FEE_EXCEEDED = "MAX_FEE_EXCEEDED"; // Not enough ETH remaining to pay feeRecipient.
string constant OVERSOLD_WETH = "OVERSOLD_WETH"; // More WETH sold than provided with current message call.
@@ -30,4 +30,5 @@ contract MixinErrorMessages {
string constant UNSUPPORTED_TOKEN_PROXY = "UNSUPPORTED_TOKEN_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.
}

View File

@@ -95,7 +95,7 @@ contract MixinAssets is
if (proxyId == ERC20_DATA_ID) {
transferERC20Token(assetData, amount);
} else if (proxyId == ERC721_DATA_ID) {
transferERC721Token(assetData);
transferERC721Token(assetData, amount);
} else {
revert("UNSUPPORTED_TOKEN_PROXY");
}
@@ -149,9 +149,17 @@ contract MixinAssets is
/// @dev Decodes ERC721 assetData and transfers given amount to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
function transferERC721Token(bytes memory assetData)
/// @param amount Amount of asset to transfer to sender.
function transferERC721Token(
bytes memory assetData,
uint256 amount
)
internal
{
require(
amount == 1,
"INVALID_AMOUNT"
);
// Decode asset data.
address token = assetData.readAddress(16);
uint256 tokenId = assetData.readUint256(36);

View File

@@ -80,7 +80,7 @@ contract MixinForwarderCore is
// Attempt to sell 95% of WETH.
// ZRX fees are payed with this contract's balance.
marketSellEth(
orderFillResults = marketSellEth(
orders,
wethAvailable,
signatures
@@ -258,6 +258,7 @@ contract MixinForwarderCore is
bytes memory zrxAssetData = ZRX_ASSET_DATA;
bytes memory wethAssetData = WETH_ASSET_DATA;
uint256 zrxPurchased = 0;
for (uint256 i = 0; i < orders.length; i++) {
@@ -266,10 +267,7 @@ contract MixinForwarderCore is
orders[i].takerAssetData = wethAssetData;
// Calculate the remaining amount of ZRX to buy.
uint256 remainingZrxBuyAmount = safeAdd(
safeSub(zrxBuyAmount, totalFillResults.makerAssetFilledAmount),
totalFillResults.takerFeePaid
);
uint256 remainingZrxBuyAmount = safeSub(zrxBuyAmount, zrxPurchased);
// Convert the remaining amount of ZRX to buy into remaining amount
// of WETH to sell, assuming entire amount can be sold in the current order.
@@ -288,16 +286,17 @@ contract MixinForwarderCore is
// Update amounts filled and fees paid by maker and taker.
addFillResults(totalFillResults, singleFillResult);
zrxPurchased = safeSub(totalFillResults.makerAssetFilledAmount, totalFillResults.takerFeePaid);
// Stop execution if the entire amount of ZRX has been bought.
if (totalFillResults.makerAssetFilledAmount == zrxBuyAmount) {
if (zrxPurchased == zrxBuyAmount) {
break;
}
}
// Ensure that all ZRX spent while filling primary orders has been repurchased.
require(
totalFillResults.makerAssetFilledAmount == zrxBuyAmount,
zrxPurchased == zrxBuyAmount,
"COMPLETE_FILL_FAILED"
);
}

View File

@@ -78,32 +78,46 @@ contract MixinWeth is
)
internal
{
uint256 wethRemaining = safeSub(
msg.value,
safeAdd(wethSoldExcludingFeeOrders, wethSoldForZrx)
);
ETHER_TOKEN.withdraw(wethRemaining);
// Ensure feePercentage is less than 5%.
require(
feePercentage <= MAX_FEE_PERCENTAGE,
"FEE_PERCENTAGE_TOO_LARGE"
);
// Calculate amount of WETH that hasn't been sold.
uint256 wethRemaining = safeSub(
msg.value,
safeAdd(wethSoldExcludingFeeOrders, wethSoldForZrx)
);
// Calculate ETH fee to pay to feeRecipient.
uint256 ethFee = getPartialAmount(
feePercentage,
PERCENTAGE_DENOMINATOR,
wethSoldExcludingFeeOrders
);
// Ensure fee is less than amount of WETH remaining.
require(
ethFee < wethRemaining,
ethFee <= wethRemaining,
"MAX_FEE_EXCEEDED"
);
if (ethFee > 0) {
feeRecipient.transfer(ethFee);
}
// Do nothing if no WETH remaining
if (wethRemaining > 0) {
// Convert remaining WETH to ETH
ETHER_TOKEN.withdraw(wethRemaining);
uint256 ethRefund = safeSub(wethRemaining, ethFee);
if (ethRefund > 0) {
msg.sender.transfer(ethRefund);
// Pay ETH to feeRecipient
if (ethFee > 0) {
feeRecipient.transfer(ethFee);
}
// Refund remaining ETH to msg.sender.
uint256 ethRefund = safeSub(wethRemaining, ethFee);
if (ethRefund > 0) {
msg.sender.transfer(ethRefund);
}
}
}
}

View File

@@ -45,6 +45,10 @@ contract MAssets is
/// @dev Decodes ERC721 assetData and transfers given amount to sender.
/// @param assetData Byte array encoded for the respective asset proxy.
function transferERC721Token(bytes memory assetData)
/// @param amount Amount of asset to transfer to sender.
function transferERC721Token(
bytes memory assetData,
uint256 amount
)
internal;
}

View File

@@ -33,7 +33,8 @@ contract LibMath is
function getPartialAmount(
uint256 numerator,
uint256 denominator,
uint256 target)
uint256 target
)
internal
pure
returns (uint256 partialAmount)
@@ -53,7 +54,8 @@ contract LibMath is
function isRoundingError(
uint256 numerator,
uint256 denominator,
uint256 target)
uint256 target
)
internal
pure
returns (bool isError)