diff --git a/contracts/dev-utils/contracts/src/LibDydxBalance.sol b/contracts/dev-utils/contracts/src/LibDydxBalance.sol index bf061ac5fa..2cff51812e 100644 --- a/contracts/dev-utils/contracts/src/LibDydxBalance.sol +++ b/contracts/dev-utils/contracts/src/LibDydxBalance.sol @@ -42,8 +42,7 @@ library LibDydxBalance { address makerAddress; address makerTokenAddress; address takerTokenAddress; - uint256 makerAssetAmount; - uint256 takerAssetAmount; + int256 orderTakerToMakerRate; uint256[] accounts; IDydxBridge.BridgeAction[] actions; } @@ -66,9 +65,10 @@ library LibDydxBalance { if (!_areActionsWellFormed(info)) { return 0; } - // If the rate we withdraw maker tokens is < 1, the asset proxy will - // throw because we will always transfer less maker tokens than asked. - if (_getMakerTokenWithdrawRate(info) < D18.one()) { + // If the rate we withdraw maker tokens is less than the order conversion + // rate , the asset proxy will throw because we will always transfer + // less maker tokens than asked. + if (_getMakerTokenWithdrawRate(info) < info.orderTakerToMakerRate) { return 0; } // The maker balance is the smaller of: @@ -154,11 +154,7 @@ library LibDydxBalance { returns (uint256 depositableMakerAmount) { depositableMakerAmount = uint256(-1); - // The conversion rate from maker -> taker. - int256 makerToTakerRate = D18.div( - info.takerAssetAmount, - info.makerAssetAmount - ); + int256 orderMakerToTakerRate = D18.div(D18.one(), info.orderTakerToMakerRate); // Take the minimum maker amount from all deposits. for (uint256 i = 0; i < info.actions.length; ++i) { IDydxBridge.BridgeAction memory action = info.actions[i]; @@ -172,7 +168,7 @@ library LibDydxBalance { // token. address depositToken = info.dydx.getMarketTokenAddress(action.marketId); if (info.takerTokenAddress != address(0) && depositToken == info.takerTokenAddress) { - depositRate = D18.sub(depositRate, makerToTakerRate); + depositRate = D18.sub(depositRate, orderMakerToTakerRate); } // If the deposit rate is > 0, we are limited by the transferrable // token balance of the maker. @@ -241,7 +237,7 @@ library LibDydxBalance { _getActionRate(withdraw) ); // If the deposit to withdraw ratio is >= the minimum collateralization - // rate, then we will never become insolvent at these prices. + // ratio, then we will never become insolvent at these prices. if (D18.div(dd, db) >= minCr) { continue; } @@ -279,8 +275,7 @@ library LibDydxBalance { (, info.takerTokenAddress) = LibAssetData.decodeERC20AssetData(order.takerAssetData); } - info.makerAssetAmount = order.makerAssetAmount; - info.takerAssetAmount = order.takerAssetAmount; + info.orderTakerToMakerRate = D18.div(order.makerAssetAmount, order.takerAssetAmount); (IDydxBridge.BridgeData memory bridgeData) = abi.decode(rawBridgeData, (IDydxBridge.BridgeData)); info.accounts = bridgeData.accountNumbers; @@ -311,7 +306,7 @@ library LibDydxBalance { returns (int256 ratio) { IDydx.RiskParams memory riskParams = dydx.getRiskParams(); - return D18.toSigned(riskParams.marginRatio.value); + return D18.add(D18.one(), D18.toSigned(riskParams.marginRatio.value)); } /// @dev Get the quote (USD) value of a rate within a market. diff --git a/contracts/dev-utils/test/lib_dydx_balance_test.ts b/contracts/dev-utils/test/lib_dydx_balance_test.ts index 04438f8bc7..9ca1775d27 100644 --- a/contracts/dev-utils/test/lib_dydx_balance_test.ts +++ b/contracts/dev-utils/test/lib_dydx_balance_test.ts @@ -53,7 +53,7 @@ blockchainTests('LibDydxBalance', env => { const INSOLVENT_ACCOUNT_IDX = 2; const ZERO_BALANCE_ACCOUNT_IDX = 3; const DYDX_CONFIG: TestDydxConfig = { - marginRatio: fromTokenUnitAmount(MARGIN_RATIO, PRICE_DECIMALS), + marginRatio: fromTokenUnitAmount(MARGIN_RATIO - 1, PRICE_DECIMALS), operators: [{ owner: ACCOUNT_OWNER, operator: BRIDGE_ADDRESS }], accounts: [ { @@ -148,8 +148,7 @@ blockchainTests('LibDydxBalance', env => { makerAddress: string; makerTokenAddress: string; takerTokenAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; + orderTakerToMakerRate: BigNumber; accounts: BigNumber[]; actions: DydxBridgeAction[]; } @@ -161,8 +160,9 @@ blockchainTests('LibDydxBalance', env => { makerAddress: ACCOUNT_OWNER, makerTokenAddress: DYDX_CONFIG.markets[1].token, takerTokenAddress: DYDX_CONFIG.markets[0].token, - makerAssetAmount: fromTokenUnitAmount(10, MAKER_DECIMALS), - takerAssetAmount: fromTokenUnitAmount(5, TAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount( + fromTokenUnitAmount(5, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)), + ), accounts: [DYDX_CONFIG.accounts[SOLVENT_ACCOUNT_IDX].accountId], actions: [], ...fields, @@ -537,8 +537,9 @@ blockchainTests('LibDydxBalance', env => { blockchainTests.resets('_getDepositableMakerAmount()', () => { it('returns infinite if no deposit action', async () => { const checkInfo = createBalanceCheckInfo({ - takerAssetAmount: fromTokenUnitAmount(10, TAKER_DECIMALS), - makerAssetAmount: fromTokenUnitAmount(100, MAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount( + fromTokenUnitAmount(100, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)), + ), actions: [], }); const makerAssetFillAmount = await testContract.getDepositableMakerAmount(checkInfo).callAsync(); @@ -547,8 +548,9 @@ blockchainTests('LibDydxBalance', env => { it('returns infinite if deposit rate is zero', async () => { const checkInfo = createBalanceCheckInfo({ - takerAssetAmount: fromTokenUnitAmount(10, TAKER_DECIMALS), - makerAssetAmount: fromTokenUnitAmount(100, MAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount( + fromTokenUnitAmount(100, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)), + ), actions: [ { actionType: DydxBridgeActionType.Deposit, @@ -565,8 +567,9 @@ blockchainTests('LibDydxBalance', env => { it('returns infinite if taker tokens cover the deposit rate', async () => { const checkInfo = createBalanceCheckInfo({ - takerAssetAmount: fromTokenUnitAmount(10, TAKER_DECIMALS), - makerAssetAmount: fromTokenUnitAmount(100, MAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount( + fromTokenUnitAmount(100, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)), + ), actions: [ { actionType: DydxBridgeActionType.Deposit, @@ -586,8 +589,9 @@ blockchainTests('LibDydxBalance', env => { const exchangeRate = 0.1; const depositRate = Math.random() + exchangeRate; const checkInfo = createBalanceCheckInfo({ - takerAssetAmount: fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS), - makerAssetAmount: fromTokenUnitAmount(1, MAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount( + fromTokenUnitAmount(1, MAKER_DECIMALS).div(fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS)), + ), actions: [ { actionType: DydxBridgeActionType.Deposit, @@ -619,8 +623,7 @@ blockchainTests('LibDydxBalance', env => { const checkInfo = createBalanceCheckInfo({ // The `takerTokenAddress` will be zero if the asset is not an ERC20. takerTokenAddress: constants.NULL_ADDRESS, - takerAssetAmount: new BigNumber(1), - makerAssetAmount: fromTokenUnitAmount(100, MAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount(fromTokenUnitAmount(100, MAKER_DECIMALS)), actions: [ { actionType: DydxBridgeActionType.Deposit, @@ -652,8 +655,9 @@ blockchainTests('LibDydxBalance', env => { takerTokenAddress: randomAddress(), // These amounts should be effectively ignored in the final computation // because the token being deposited is not the taker token. - takerAssetAmount: fromTokenUnitAmount(10, TAKER_DECIMALS), - makerAssetAmount: fromTokenUnitAmount(100, MAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount( + fromTokenUnitAmount(100, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)), + ), actions: [ { actionType: DydxBridgeActionType.Deposit, @@ -672,8 +676,9 @@ blockchainTests('LibDydxBalance', env => { // The taker tokens getting exchanged in will only partially cover the deposit. const exchangeRate = 0.1; const checkInfo = createBalanceCheckInfo({ - takerAssetAmount: fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS), - makerAssetAmount: fromTokenUnitAmount(1, MAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount( + fromTokenUnitAmount(1, MAKER_DECIMALS).div(fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS)), + ), actions: [ // Technically, deposits of the same token are not allowed, but the // check isn't done in this function so we'll do this to simulate @@ -728,8 +733,7 @@ blockchainTests('LibDydxBalance', env => { const exchangeRate = 0.1; const depositRate = Math.random() + exchangeRate; const checkInfo = createBalanceCheckInfo({ - takerAssetAmount: fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS), - makerAssetAmount: fromTokenUnitAmount(1, MAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount(fromTokenUnitAmount(1 / exchangeRate, MAKER_DECIMALS)), actions: [ { actionType: DydxBridgeActionType.Deposit, @@ -756,8 +760,7 @@ blockchainTests('LibDydxBalance', env => { const exchangeRate = 0.1; const depositRate = Math.random() + exchangeRate; const checkInfo = createBalanceCheckInfo({ - takerAssetAmount: fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS), - makerAssetAmount: fromTokenUnitAmount(1, MAKER_DECIMALS), + orderTakerToMakerRate: fromTokenUnitAmount(fromTokenUnitAmount(1 / exchangeRate, MAKER_DECIMALS)), actions: [ { actionType: DydxBridgeActionType.Deposit, @@ -1085,7 +1088,7 @@ blockchainTests('LibDydxBalance', env => { senderAddress: constants.NULL_ADDRESS, makerFee: getRandomInteger(1, constants.MAX_UINT256), takerFee: getRandomInteger(1, constants.MAX_UINT256), - makerAssetAmount: fromTokenUnitAmount(100, TAKER_DECIMALS), + makerAssetAmount: fromTokenUnitAmount(100, MAKER_DECIMALS), takerAssetAmount: fromTokenUnitAmount(10, TAKER_DECIMALS), makerAssetData: createBridgeAssetData(makerTokenAddress, BRIDGE_ADDRESS), takerAssetData: createERC20AssetData(takerTokenAddress),