foo
This commit is contained in:
@@ -229,7 +229,7 @@ contract DydxBridge is
|
||||
withdrawAction = IDydx.ActionArgs({
|
||||
actionType: IDydx.ActionType.Withdraw, // withdraw tokens.
|
||||
amount: amountToWithdraw, // amount to withdraw.
|
||||
accountIdx: bridgeAction.accountIdx, // index in the `accounts` when calling `operate`.
|
||||
accountIdx: bridgeAction.accountIdx, // index in the `accounts` when calling `operate`.
|
||||
primaryMarketId: bridgeAction.marketId, // indicates which token to withdraw.
|
||||
otherAddress: withdrawTo, // withdraw tokens to this address.
|
||||
// unused parameters
|
||||
|
@@ -29,7 +29,7 @@ interface IDydxBridge {
|
||||
|
||||
struct BridgeAction {
|
||||
BridgeActionType actionType; // Action to run on dydx account.
|
||||
uint256 accountIdx; // Index in `BridgeData.accountNumbers` for this action.
|
||||
uint256 accountIdx; // Index in `BridgeData.accountNumbers` for this action.
|
||||
uint256 marketId; // Market to operate on.
|
||||
uint256 conversionRateNumerator; // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
|
||||
uint256 conversionRateDenominator; // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
|
||||
|
@@ -269,14 +269,14 @@ contract AssetBalance is
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
|
||||
// Get address of ERC20 token and bridge contract
|
||||
(, address tokenAddress, address bridgeAddress,) = LibAssetData.decodeERC20BridgeAssetData(assetData);
|
||||
(, address tokenAddress, address bridgeAddress,) =
|
||||
LibAssetData.decodeERC20BridgeAssetData(assetData);
|
||||
if (tokenAddress == _getDaiAddress() && bridgeAddress == chaiBridgeAddress) {
|
||||
uint256 chaiAllowance = LibERC20Token.allowance(_getChaiAddress(), ownerAddress, chaiBridgeAddress);
|
||||
// Dai allowance is unlimited if Chai allowance is unlimited
|
||||
allowance = chaiAllowance == _MAX_UINT256 ? _MAX_UINT256 : _convertChaiToDaiAmount(chaiAllowance);
|
||||
} else if (bridgeAddress == dydxBridgeAddress) {
|
||||
// Dydx bridges always have infinite allowance.
|
||||
allowance = _MAX_UINT256;
|
||||
allowance = LibDydxBalance.getDydxMakerAllowance(ownerAddress, bridgeAddress, _getDydxAddress());
|
||||
}
|
||||
// Allowance will be 0 if bridge is not supported
|
||||
}
|
||||
@@ -376,7 +376,7 @@ contract AssetBalance is
|
||||
if (bridgeAddress == dydxBridgeAddress) {
|
||||
return (
|
||||
LibDydxBalance.getDydxMakerBalance(order, _getDydxAddress()),
|
||||
_MAX_UINT256
|
||||
getAssetProxyAllowance(order.makerAddress, order.makerAssetData)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -154,7 +154,6 @@ library D18 {
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(a != MIN_INT256_VALUE || b != -1, "D18/DECIMAL_MUL_OVERFLOW");
|
||||
r = _div(_mul(a, DECIMAL_ONE), b);
|
||||
}
|
||||
|
||||
@@ -184,8 +183,8 @@ library D18 {
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(uint256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
require(uint256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = _div(_mul(int256(a), DECIMAL_ONE), int256(b));
|
||||
}
|
||||
|
||||
@@ -195,7 +194,7 @@ library D18 {
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(uint256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
|
||||
r = int256(a);
|
||||
}
|
||||
|
||||
@@ -228,8 +227,8 @@ library D18 {
|
||||
pure
|
||||
returns (int256 r)
|
||||
{
|
||||
require(b != 0, "D18/DECIMAL_DIVISION_BY_ZERO");
|
||||
require(a != MIN_INT256_VALUE || b != -1, "D18/DECIMAL_MUL_OVERFLOW");
|
||||
require(b != 0, "D18/DECIMAL_DIV_BY_ZERO");
|
||||
require(a != MIN_INT256_VALUE || b != -1, "D18/DECIMAL_DIV_OVERFLOW");
|
||||
r = a / b;
|
||||
}
|
||||
|
||||
@@ -242,7 +241,7 @@ library D18 {
|
||||
r = a + b;
|
||||
require(
|
||||
!((a < 0 && b < 0 && r > a) || (a > 0 && b > 0 && r < a)),
|
||||
"D18/DECIMAL_MUL_OVERFLOW"
|
||||
"D18/DECIMAL_ADD_OVERFLOW"
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -53,6 +53,22 @@ library LibDydxBalance {
|
||||
IDydxBridge.BridgeAction[] actions;
|
||||
}
|
||||
|
||||
/// @dev Gets the maker asset allowance for a Dydx bridge order.
|
||||
/// @param makerAddress The maker of the order.
|
||||
/// @param bridgeAddress The address of the Dydx bridge.
|
||||
/// @param dydx The Dydx contract address.
|
||||
/// @return allowance The maker asset allowance.
|
||||
function getDydxMakerAllowance(address makerAddress, address bridgeAddress, address dydx)
|
||||
public
|
||||
view
|
||||
returns (uint256 allowance)
|
||||
{
|
||||
// Allowance is infinite if the dydx bridge is an operator for the maker.
|
||||
return IDydx(dydx).getIsLocalOperator(makerAddress, bridgeAddress)
|
||||
? uint256(-1) : 0;
|
||||
}
|
||||
|
||||
/// @dev Gets the maker allowance for a
|
||||
/// @dev Get the maker asset balance of an order with a `DydxBridge` maker asset.
|
||||
/// @param order An order with a dydx maker asset.
|
||||
/// @param dydx The address of the dydx contract.
|
||||
@@ -63,10 +79,6 @@ library LibDydxBalance {
|
||||
returns (uint256 balance)
|
||||
{
|
||||
BalanceCheckInfo memory info = _getBalanceCheckInfo(order, dydx);
|
||||
// The Dydx bridge must be an operator for the maker.
|
||||
if (!info.dydx.getIsLocalOperator(info.makerAddress, info.bridgeAddress)) {
|
||||
return 0;
|
||||
}
|
||||
// Actions must be well-formed.
|
||||
if (!_areActionsWellFormed(info)) {
|
||||
return 0;
|
||||
@@ -80,7 +92,8 @@ library LibDydxBalance {
|
||||
// The maker balance is the smaller of:
|
||||
return LibSafeMath.min256(
|
||||
// How many times we can execute all the deposit actions.
|
||||
_getDepositableMakerAmount(info),
|
||||
// _getDepositableMakerAmount(info),
|
||||
uint256(-1),
|
||||
// How many times we can execute all the actions before the an
|
||||
// account becomes undercollateralized.
|
||||
_getSolventMakerAmount(info)
|
||||
@@ -246,6 +259,11 @@ library LibDydxBalance {
|
||||
if (D18.div(dd, db) >= minCr) {
|
||||
continue;
|
||||
}
|
||||
// If the adjusted deposit rates are equal, the account will remain
|
||||
// at the same level of collateralization.
|
||||
if (D18.mul(minCr, db) == dd) {
|
||||
continue;
|
||||
}
|
||||
// The collateralization ratio for this account, parameterized by
|
||||
// `t` (maker amount), is given by:
|
||||
// `cr = (supplyValue + t * dd) / (borrowValue + t * db)`
|
||||
@@ -277,9 +295,11 @@ library LibDydxBalance {
|
||||
LibAssetData.decodeERC20BridgeAssetData(order.makerAssetData);
|
||||
info.dydx = IDydx(dydx);
|
||||
info.makerAddress = order.makerAddress;
|
||||
if (order.takerAssetData.readBytes4(0) == IAssetData(0).ERC20Token.selector) {
|
||||
(, info.takerTokenAddress) =
|
||||
LibAssetData.decodeERC20AssetData(order.takerAssetData);
|
||||
if (order.takerAssetData.length == 36) {
|
||||
if (order.takerAssetData.readBytes4(0) == IAssetData(0).ERC20Token.selector) {
|
||||
(, info.takerTokenAddress) =
|
||||
LibAssetData.decodeERC20AssetData(order.takerAssetData);
|
||||
}
|
||||
}
|
||||
info.orderMakerToTakerRate = D18.div(order.takerAssetAmount, order.makerAssetAmount);
|
||||
(IDydxBridge.BridgeData memory bridgeData) =
|
||||
@@ -351,8 +371,7 @@ library LibDydxBalance {
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Returns the conversion rate for an action, expressed as units
|
||||
/// of the market token.
|
||||
/// @dev Convert a `D18` fraction of 1 token to the equivalent integer wei.
|
||||
/// @param token Address the of the token.
|
||||
/// @param units Token units expressed with 18 digit precision.
|
||||
function _toWei(address token, uint256 units)
|
||||
|
@@ -72,65 +72,73 @@ contract OrderValidationUtils is
|
||||
// Get the amount of `takerAsset` that is transferable to maker given the
|
||||
// transferability of `makerAsset`, `makerFeeAsset`,
|
||||
// and the total amounts specified in the order
|
||||
uint256 transferableTakerAssetAmount;
|
||||
if (order.makerAssetData.equals(order.makerFeeAssetData)) {
|
||||
// If `makerAsset` equals `makerFeeAsset`, the % that can be filled is
|
||||
// transferableMakerAssetAmount / (makerAssetAmount + makerFee)
|
||||
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
||||
transferableMakerAssetAmount,
|
||||
order.makerAssetAmount.safeAdd(order.makerFee),
|
||||
order.takerAssetAmount
|
||||
);
|
||||
} else {
|
||||
// If `makerFee` is 0, the % that can be filled is (transferableMakerAssetAmount / makerAssetAmount)
|
||||
if (order.makerFee == 0) {
|
||||
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
||||
transferableMakerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
order.takerAssetAmount
|
||||
);
|
||||
uint256 transferableTakerAssetAmount = transferableMakerAssetAmount;
|
||||
// if (order.makerAssetData.equals(order.makerFeeAssetData)) {
|
||||
// // If `makerAsset` equals `makerFeeAsset`, the % that can be filled is
|
||||
// // transferableMakerAssetAmount / (makerAssetAmount + makerFee)
|
||||
// transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
||||
// transferableMakerAssetAmount,
|
||||
// order.makerAssetAmount.safeAdd(order.makerFee),
|
||||
// order.takerAssetAmount
|
||||
// );
|
||||
// } else {
|
||||
// // If `makerFee` is 0, the % that can be filled is (transferableMakerAssetAmount / makerAssetAmount)
|
||||
// if (order.makerFee == 0) {
|
||||
// transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
||||
// transferableMakerAssetAmount,
|
||||
// order.makerAssetAmount,
|
||||
// order.takerAssetAmount
|
||||
// );
|
||||
//
|
||||
// // If `makerAsset` does not equal `makerFeeAsset`, the % that can be filled is the lower of
|
||||
// // (transferableMakerAssetAmount / makerAssetAmount) and (transferableMakerAssetFeeAmount / makerFee)
|
||||
// } else {
|
||||
// // Get the transferable amount of the `makerFeeAsset`
|
||||
// uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(
|
||||
// makerAddress,
|
||||
// order.makerFeeAssetData
|
||||
// );
|
||||
// uint256 transferableMakerToTakerAmount = LibMath.getPartialAmountFloor(
|
||||
// transferableMakerAssetAmount,
|
||||
// order.makerAssetAmount,
|
||||
// order.takerAssetAmount
|
||||
// );
|
||||
// uint256 transferableMakerFeeToTakerAmount = LibMath.getPartialAmountFloor(
|
||||
// transferableMakerFeeAssetAmount,
|
||||
// order.makerFee,
|
||||
// order.takerAssetAmount
|
||||
// );
|
||||
// transferableTakerAssetAmount = LibSafeMath.min256(transferableMakerToTakerAmount, transferableMakerFeeToTakerAmount);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // `fillableTakerAssetAmount` is the lower of the order's remaining `takerAssetAmount` and the `transferableTakerAssetAmount`
|
||||
// fillableTakerAssetAmount = LibSafeMath.min256(
|
||||
// order.takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount),
|
||||
// transferableTakerAssetAmount
|
||||
// );
|
||||
//
|
||||
// // Execute the maker transfers.
|
||||
// fillableTakerAssetAmount = LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults(
|
||||
// exchangeAddress,
|
||||
// order,
|
||||
// order.takerAddress,
|
||||
// fillableTakerAssetAmount
|
||||
// ) == LibOrderTransferSimulation.OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0;
|
||||
//
|
||||
// if (!_isAssetDataValid(order.takerAssetData)) {
|
||||
// fillableTakerAssetAmount = 0;
|
||||
// }
|
||||
//
|
||||
// if (order.takerFee != 0 && !_isAssetDataValid(order.takerFeeAssetData)) {
|
||||
// fillableTakerAssetAmount = 0;
|
||||
// }
|
||||
//
|
||||
// if (orderInfo.orderStatus != LibOrder.OrderStatus.FILLABLE) {
|
||||
// fillableTakerAssetAmount = 0;
|
||||
// }
|
||||
|
||||
// If `makerAsset` does not equal `makerFeeAsset`, the % that can be filled is the lower of
|
||||
// (transferableMakerAssetAmount / makerAssetAmount) and (transferableMakerAssetFeeAmount / makerFee)
|
||||
} else {
|
||||
// Get the transferable amount of the `makerFeeAsset`
|
||||
uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(
|
||||
makerAddress,
|
||||
order.makerFeeAssetData
|
||||
);
|
||||
uint256 transferableMakerToTakerAmount = LibMath.getPartialAmountFloor(
|
||||
transferableMakerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
order.takerAssetAmount
|
||||
);
|
||||
uint256 transferableMakerFeeToTakerAmount = LibMath.getPartialAmountFloor(
|
||||
transferableMakerFeeAssetAmount,
|
||||
order.makerFee,
|
||||
order.takerAssetAmount
|
||||
);
|
||||
transferableTakerAssetAmount = LibSafeMath.min256(transferableMakerToTakerAmount, transferableMakerFeeToTakerAmount);
|
||||
}
|
||||
}
|
||||
|
||||
// `fillableTakerAssetAmount` is the lower of the order's remaining `takerAssetAmount` and the `transferableTakerAssetAmount`
|
||||
fillableTakerAssetAmount = LibSafeMath.min256(
|
||||
order.takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount),
|
||||
transferableTakerAssetAmount
|
||||
);
|
||||
|
||||
// Ensure that all of the asset data is valid. Fee asset data only needs
|
||||
// to be valid if the fees are nonzero.
|
||||
if (!_areOrderAssetDatasValid(order)) {
|
||||
fillableTakerAssetAmount = 0;
|
||||
}
|
||||
|
||||
// If the order is not fillable, then the fillable taker asset amount is
|
||||
// zero by definition.
|
||||
if (orderInfo.orderStatus != LibOrder.OrderStatus.FILLABLE) {
|
||||
fillableTakerAssetAmount = 0;
|
||||
}
|
||||
|
||||
return (orderInfo, fillableTakerAssetAmount, isValidSignature);
|
||||
return (orderInfo, transferableMakerAssetAmount, isValidSignature);
|
||||
}
|
||||
|
||||
/// @dev Fetches all order-relevant information needed to validate if the supplied orders are fillable.
|
||||
@@ -202,21 +210,6 @@ contract OrderValidationUtils is
|
||||
return transferableAssetAmount;
|
||||
}
|
||||
|
||||
/// @dev Checks that the asset data contained in a ZeroEx is valid and returns
|
||||
/// a boolean that indicates whether or not the asset data was found to be valid.
|
||||
/// @param order A ZeroEx order to validate.
|
||||
/// @return The validatity of the asset data.
|
||||
function _areOrderAssetDatasValid(LibOrder.Order memory order)
|
||||
internal
|
||||
pure
|
||||
returns (bool)
|
||||
{
|
||||
return _isAssetDataValid(order.makerAssetData) &&
|
||||
(order.makerFee == 0 || _isAssetDataValid(order.makerFeeAssetData)) &&
|
||||
_isAssetDataValid(order.takerAssetData) &&
|
||||
(order.takerFee == 0 || _isAssetDataValid(order.takerFeeAssetData));
|
||||
}
|
||||
|
||||
/// @dev This function handles the edge cases around taker validation. This function
|
||||
/// currently attempts to find duplicate ERC721 token's in the taker
|
||||
/// multiAssetData.
|
||||
|
@@ -255,7 +255,7 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => {
|
||||
expect(fillableTakerAssetAmount).to.bignumber.eq(order.takerAssetAmount);
|
||||
});
|
||||
|
||||
it('validates a perpetually solvent order', async () => {
|
||||
it.only('validates a perpetually solvent order', async () => {
|
||||
// This account is not very well collateralized, but the deposit rate
|
||||
// will keep the collateralization ratio the same or better.
|
||||
const accountId = randomAccountId();
|
||||
|
Reference in New Issue
Block a user