@0x/asset-proxy
: Add more functions to IDydx
.
`@0x/dev-utils`: Fix all the weird dydx base unit madness.
This commit is contained in:
parent
162b6f1a74
commit
651e94bd94
@ -30,6 +30,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Add asset data decoding functions",
|
"note": "Add asset data decoding functions",
|
||||||
"pr": 2462
|
"pr": 2462
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add `setOperators()` to `IDydx`",
|
||||||
|
"pr": "TODO"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"timestamp": 1581204851
|
"timestamp": 1581204851
|
||||||
|
@ -196,7 +196,7 @@ contract DydxBridge is
|
|||||||
otherAddress: depositFrom, // deposit from the account owner.
|
otherAddress: depositFrom, // deposit from the account owner.
|
||||||
// unused parameters
|
// unused parameters
|
||||||
secondaryMarketId: 0,
|
secondaryMarketId: 0,
|
||||||
otherAccountId: 0,
|
otherAccountIdx: 0,
|
||||||
data: hex''
|
data: hex''
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ contract DydxBridge is
|
|||||||
otherAddress: withdrawTo, // withdraw tokens to this address.
|
otherAddress: withdrawTo, // withdraw tokens to this address.
|
||||||
// unused parameters
|
// unused parameters
|
||||||
secondaryMarketId: 0,
|
secondaryMarketId: 0,
|
||||||
otherAccountId: 0,
|
otherAccountIdx: 0,
|
||||||
data: hex''
|
data: hex''
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ interface IDydx {
|
|||||||
uint256 primaryMarketId;
|
uint256 primaryMarketId;
|
||||||
uint256 secondaryMarketId;
|
uint256 secondaryMarketId;
|
||||||
address otherAddress;
|
address otherAddress;
|
||||||
uint256 otherAccountId;
|
uint256 otherAccountIdx;
|
||||||
bytes data;
|
bytes data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +83,11 @@ interface IDydx {
|
|||||||
uint256 value;
|
uint256 value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct OperatorArg {
|
||||||
|
address operator;
|
||||||
|
bool trusted;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev The global risk parameters that govern the health and security of the system
|
/// @dev The global risk parameters that govern the health and security of the system
|
||||||
struct RiskParams {
|
struct RiskParams {
|
||||||
// Required ratio of over-collateralization
|
// Required ratio of over-collateralization
|
||||||
@ -166,4 +171,13 @@ interface IDydx {
|
|||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (Value memory supplyValue, Value memory borrowValue);
|
returns (Value memory supplyValue, Value memory borrowValue);
|
||||||
|
|
||||||
|
// @dev Approves/disapproves any number of operators. An operator is an external address that has the
|
||||||
|
// same permissions to manipulate an account as the owner of the account. Operators are simply
|
||||||
|
// addresses and therefore may either be externally-owned Ethereum accounts OR smart contracts.
|
||||||
|
// Operators are also able to act as AutoTrader contracts on behalf of the account owner if the
|
||||||
|
// operator is a smart contract and implements the IAutoTrader interface.
|
||||||
|
// @param args A list of OperatorArgs which have an address and a boolean. The boolean value
|
||||||
|
// denotes whether to approve (true) or revoke approval (false) for that address.
|
||||||
|
function setOperators(OperatorArg[] calldata args) external;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ contract TestDydxBridge is
|
|||||||
actions[i].primaryMarketId,
|
actions[i].primaryMarketId,
|
||||||
actions[i].secondaryMarketId,
|
actions[i].secondaryMarketId,
|
||||||
actions[i].otherAddress,
|
actions[i].otherAddress,
|
||||||
actions[i].otherAccountId,
|
actions[i].otherAccountIdx,
|
||||||
actions[i].data
|
actions[i].data
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -216,6 +216,9 @@ contract TestDydxBridge is
|
|||||||
returns (Value memory supplyValue, Value memory borrowValue)
|
returns (Value memory supplyValue, Value memory borrowValue)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/// @dev Unused.
|
||||||
|
function setOperators(OperatorArg[] calldata args) external {}
|
||||||
|
|
||||||
/// @dev overrides `_getDydxAddress()` from `DeploymentConstants` to return this address.
|
/// @dev overrides `_getDydxAddress()` from `DeploymentConstants` to return this address.
|
||||||
function _getDydxAddress()
|
function _getDydxAddress()
|
||||||
internal
|
internal
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
export { artifacts } from './artifacts';
|
export { artifacts } from './artifacts';
|
||||||
export {
|
export {
|
||||||
|
ChaiBridgeContract,
|
||||||
ERC1155ProxyContract,
|
ERC1155ProxyContract,
|
||||||
ERC20BridgeProxyContract,
|
ERC20BridgeProxyContract,
|
||||||
ERC20ProxyContract,
|
ERC20ProxyContract,
|
||||||
ERC721ProxyContract,
|
ERC721ProxyContract,
|
||||||
Eth2DaiBridgeContract,
|
Eth2DaiBridgeContract,
|
||||||
DydxBridgeContract,
|
DydxBridgeContract,
|
||||||
TestDydxBridgeContract,
|
|
||||||
IAssetDataContract,
|
IAssetDataContract,
|
||||||
IAssetProxyContract,
|
IAssetProxyContract,
|
||||||
|
IChaiContract,
|
||||||
|
IDydxContract,
|
||||||
|
KyberBridgeContract,
|
||||||
MultiAssetProxyContract,
|
MultiAssetProxyContract,
|
||||||
StaticCallProxyContract,
|
StaticCallProxyContract,
|
||||||
|
TestDydxBridgeContract,
|
||||||
TestStaticCallTargetContract,
|
TestStaticCallTargetContract,
|
||||||
UniswapBridgeContract,
|
UniswapBridgeContract,
|
||||||
KyberBridgeContract,
|
|
||||||
ChaiBridgeContract,
|
|
||||||
IChaiContract,
|
|
||||||
} from './wrappers';
|
} from './wrappers';
|
||||||
|
|
||||||
export { ERC20Wrapper } from './erc20_wrapper';
|
export { ERC20Wrapper } from './erc20_wrapper';
|
||||||
|
@ -33,6 +33,12 @@ import "./D18.sol";
|
|||||||
library LibDydxBalance {
|
library LibDydxBalance {
|
||||||
|
|
||||||
using LibBytes for bytes;
|
using LibBytes for bytes;
|
||||||
|
using LibSafeMath for uint256;
|
||||||
|
|
||||||
|
/// @dev Padding % added to the minimum collateralization ratio to
|
||||||
|
/// prevent withdrawing exactly the amount that would make an account
|
||||||
|
/// insolvent. 1 bps.
|
||||||
|
int256 private constant MARGIN_RATIO_PADDING = 0.0001e18;
|
||||||
|
|
||||||
/// @dev Structure that holds all pertinent info needed to perform a balance
|
/// @dev Structure that holds all pertinent info needed to perform a balance
|
||||||
/// check.
|
/// check.
|
||||||
@ -42,7 +48,7 @@ library LibDydxBalance {
|
|||||||
address makerAddress;
|
address makerAddress;
|
||||||
address makerTokenAddress;
|
address makerTokenAddress;
|
||||||
address takerTokenAddress;
|
address takerTokenAddress;
|
||||||
int256 orderTakerToMakerRate;
|
int256 orderMakerToTakerRate;
|
||||||
uint256[] accounts;
|
uint256[] accounts;
|
||||||
IDydxBridge.BridgeAction[] actions;
|
IDydxBridge.BridgeAction[] actions;
|
||||||
}
|
}
|
||||||
@ -65,10 +71,10 @@ library LibDydxBalance {
|
|||||||
if (!_areActionsWellFormed(info)) {
|
if (!_areActionsWellFormed(info)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// If the rate we withdraw maker tokens is less than the order conversion
|
// If the rate we withdraw maker tokens is less than one, the asset
|
||||||
// rate , the asset proxy will throw because we will always transfer
|
// proxy will throw because we will always transfer less maker tokens
|
||||||
// less maker tokens than asked.
|
// than asked.
|
||||||
if (_getMakerTokenWithdrawRate(info) < info.orderTakerToMakerRate) {
|
if (_getMakerTokenWithdrawRate(info) < D18.one()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// The maker balance is the smaller of:
|
// The maker balance is the smaller of:
|
||||||
@ -154,7 +160,6 @@ library LibDydxBalance {
|
|||||||
returns (uint256 depositableMakerAmount)
|
returns (uint256 depositableMakerAmount)
|
||||||
{
|
{
|
||||||
depositableMakerAmount = uint256(-1);
|
depositableMakerAmount = uint256(-1);
|
||||||
int256 orderMakerToTakerRate = D18.div(D18.one(), info.orderTakerToMakerRate);
|
|
||||||
// Take the minimum maker amount from all deposits.
|
// Take the minimum maker amount from all deposits.
|
||||||
for (uint256 i = 0; i < info.actions.length; ++i) {
|
for (uint256 i = 0; i < info.actions.length; ++i) {
|
||||||
IDydxBridge.BridgeAction memory action = info.actions[i];
|
IDydxBridge.BridgeAction memory action = info.actions[i];
|
||||||
@ -162,13 +167,15 @@ library LibDydxBalance {
|
|||||||
if (action.actionType != IDydxBridge.BridgeActionType.Deposit) {
|
if (action.actionType != IDydxBridge.BridgeActionType.Deposit) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// `depositRate` is the rate at which we convert a maker token into
|
||||||
|
// a taker token for deposit.
|
||||||
int256 depositRate = _getActionRate(action);
|
int256 depositRate = _getActionRate(action);
|
||||||
// Taker tokens will be transferred to the maker for every fill, so
|
// Taker tokens will be transferred to the maker for every fill, so
|
||||||
// we reduce the effective deposit rate if we're depositing the taker
|
// we reduce the effective deposit rate if we're depositing the taker
|
||||||
// token.
|
// token.
|
||||||
address depositToken = info.dydx.getMarketTokenAddress(action.marketId);
|
address depositToken = info.dydx.getMarketTokenAddress(action.marketId);
|
||||||
if (info.takerTokenAddress != address(0) && depositToken == info.takerTokenAddress) {
|
if (info.takerTokenAddress != address(0) && depositToken == info.takerTokenAddress) {
|
||||||
depositRate = D18.sub(depositRate, orderMakerToTakerRate);
|
depositRate = D18.sub(depositRate, info.orderMakerToTakerRate);
|
||||||
}
|
}
|
||||||
// If the deposit rate is > 0, we are limited by the transferrable
|
// If the deposit rate is > 0, we are limited by the transferrable
|
||||||
// token balance of the maker.
|
// token balance of the maker.
|
||||||
@ -198,11 +205,11 @@ library LibDydxBalance {
|
|||||||
assert(info.actions.length >= 1);
|
assert(info.actions.length >= 1);
|
||||||
IDydxBridge.BridgeAction memory withdraw = info.actions[info.actions.length - 1];
|
IDydxBridge.BridgeAction memory withdraw = info.actions[info.actions.length - 1];
|
||||||
assert(withdraw.actionType == IDydxBridge.BridgeActionType.Withdraw);
|
assert(withdraw.actionType == IDydxBridge.BridgeActionType.Withdraw);
|
||||||
int256 minCr = _getMinimumCollateralizationRatio(info.dydx);
|
int256 minCr = D18.add(_getMinimumCollateralizationRatio(info.dydx), MARGIN_RATIO_PADDING);
|
||||||
// Loop through the accounts.
|
// Loop through the accounts.
|
||||||
for (uint256 accountIdx = 0; accountIdx < info.accounts.length; ++accountIdx) {
|
for (uint256 accountIdx = 0; accountIdx < info.accounts.length; ++accountIdx) {
|
||||||
(uint256 supplyValue, uint256 borrowValue) =
|
(uint256 supplyValue, uint256 borrowValue) =
|
||||||
_getAccountValues(info, info.accounts[accountIdx]);
|
_getAccountMarketValues(info, info.accounts[accountIdx]);
|
||||||
// All accounts must currently be solvent.
|
// All accounts must currently be solvent.
|
||||||
if (borrowValue != 0 && D18.div(supplyValue, borrowValue) < minCr) {
|
if (borrowValue != 0 && D18.div(supplyValue, borrowValue) < minCr) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -221,20 +228,18 @@ library LibDydxBalance {
|
|||||||
if (deposit.accountIdx == accountIdx) {
|
if (deposit.accountIdx == accountIdx) {
|
||||||
dd = D18.add(
|
dd = D18.add(
|
||||||
dd,
|
dd,
|
||||||
_toQuoteValue(
|
_getActionRateValue(
|
||||||
info.dydx,
|
info,
|
||||||
deposit.marketId,
|
deposit
|
||||||
_getActionRate(deposit)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Compute the borrow/withdraw rate, which is the rate at which
|
// Compute the borrow/withdraw rate, which is the rate at which
|
||||||
// (USD) value is deducted from the account.
|
// (USD) value is deducted from the account.
|
||||||
int256 db = _toQuoteValue(
|
int256 db = _getActionRateValue(
|
||||||
info.dydx,
|
info,
|
||||||
withdraw.marketId,
|
withdraw
|
||||||
_getActionRate(withdraw)
|
|
||||||
);
|
);
|
||||||
// If the deposit to withdraw ratio is >= the minimum collateralization
|
// If the deposit to withdraw ratio is >= the minimum collateralization
|
||||||
// ratio, then we will never become insolvent at these prices.
|
// ratio, then we will never become insolvent at these prices.
|
||||||
@ -252,7 +257,8 @@ library LibDydxBalance {
|
|||||||
);
|
);
|
||||||
solventMakerAmount = LibSafeMath.min256(
|
solventMakerAmount = LibSafeMath.min256(
|
||||||
solventMakerAmount,
|
solventMakerAmount,
|
||||||
uint256(D18.clip(t))
|
// `t` is in maker token units, so convert it to maker wei.
|
||||||
|
_toWei(info.makerTokenAddress, uint256(D18.clip(t)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,14 +281,14 @@ library LibDydxBalance {
|
|||||||
(, info.takerTokenAddress) =
|
(, info.takerTokenAddress) =
|
||||||
LibAssetData.decodeERC20AssetData(order.takerAssetData);
|
LibAssetData.decodeERC20AssetData(order.takerAssetData);
|
||||||
}
|
}
|
||||||
info.orderTakerToMakerRate = D18.div(order.makerAssetAmount, order.takerAssetAmount);
|
info.orderMakerToTakerRate = D18.div(order.takerAssetAmount, order.makerAssetAmount);
|
||||||
(IDydxBridge.BridgeData memory bridgeData) =
|
(IDydxBridge.BridgeData memory bridgeData) =
|
||||||
abi.decode(rawBridgeData, (IDydxBridge.BridgeData));
|
abi.decode(rawBridgeData, (IDydxBridge.BridgeData));
|
||||||
info.accounts = bridgeData.accountNumbers;
|
info.accounts = bridgeData.accountNumbers;
|
||||||
info.actions = bridgeData.actions;
|
info.actions = bridgeData.actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Returns the conversion rate for an action, treating infinites as 1.
|
/// @dev Returns the conversion rate for an action.
|
||||||
/// @param action A `BridgeAction`.
|
/// @param action A `BridgeAction`.
|
||||||
function _getActionRate(IDydxBridge.BridgeAction memory action)
|
function _getActionRate(IDydxBridge.BridgeAction memory action)
|
||||||
private
|
private
|
||||||
@ -297,6 +303,59 @@ library LibDydxBalance {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Returns the USD value of an action based on its conversion rate
|
||||||
|
/// and market prices.
|
||||||
|
/// @param info State from `_getBalanceCheckInfo()`.
|
||||||
|
/// @param action A `BridgeAction`.
|
||||||
|
function _getActionRateValue(
|
||||||
|
BalanceCheckInfo memory info,
|
||||||
|
IDydxBridge.BridgeAction memory action
|
||||||
|
)
|
||||||
|
private
|
||||||
|
view
|
||||||
|
returns (int256 value)
|
||||||
|
{
|
||||||
|
address toToken = info.dydx.getMarketTokenAddress(action.marketId);
|
||||||
|
uint256 fromTokenDecimals = LibERC20Token.decimals(info.makerTokenAddress);
|
||||||
|
uint256 toTokenDecimals = LibERC20Token.decimals(toToken);
|
||||||
|
// First express the rate as 18-decimal units.
|
||||||
|
value = toTokenDecimals > fromTokenDecimals
|
||||||
|
? int256(
|
||||||
|
uint256(_getActionRate(action))
|
||||||
|
.safeDiv(10 ** (toTokenDecimals - fromTokenDecimals))
|
||||||
|
)
|
||||||
|
: int256(
|
||||||
|
uint256(_getActionRate(action))
|
||||||
|
.safeMul(10 ** (fromTokenDecimals - toTokenDecimals))
|
||||||
|
);
|
||||||
|
// Prices have 18 + (18 - TOKEN_DECIMALS) decimal places because
|
||||||
|
// consistency is stupid.
|
||||||
|
uint256 price = info.dydx.getMarketPrice(action.marketId).value;
|
||||||
|
// Make prices have 18 decimals.
|
||||||
|
if (toTokenDecimals > 18) {
|
||||||
|
price = price.safeMul(10 ** (toTokenDecimals - 18));
|
||||||
|
} else {
|
||||||
|
price = price.safeDiv(10 ** (18 - toTokenDecimals));
|
||||||
|
}
|
||||||
|
// The action value is the action rate times the price.
|
||||||
|
value = D18.mul(price, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Returns the conversion rate for an action, expressed as units
|
||||||
|
/// of the market token.
|
||||||
|
/// @param token Address the of the token.
|
||||||
|
/// @param units Token units expressed with 18 digit precision.
|
||||||
|
function _toWei(address token, uint256 units)
|
||||||
|
private
|
||||||
|
view
|
||||||
|
returns (uint256 rate)
|
||||||
|
{
|
||||||
|
uint256 decimals = LibERC20Token.decimals(token);
|
||||||
|
rate = decimals > 18
|
||||||
|
? units.safeMul(10 ** (decimals - 18))
|
||||||
|
: units.safeDiv(10 ** (18 - decimals));
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Get the global minimum collateralization ratio required for
|
/// @dev Get the global minimum collateralization ratio required for
|
||||||
/// an account to be considered solvent.
|
/// an account to be considered solvent.
|
||||||
/// @param dydx The Dydx interface.
|
/// @param dydx The Dydx interface.
|
||||||
@ -309,24 +368,10 @@ library LibDydxBalance {
|
|||||||
return D18.add(D18.one(), 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.
|
|
||||||
/// @param dydx The Dydx interface.
|
|
||||||
/// @param marketId Dydx market ID.
|
|
||||||
/// @param rate Rate to scale by price.
|
|
||||||
function _toQuoteValue(IDydx dydx, uint256 marketId, int256 rate)
|
|
||||||
private
|
|
||||||
view
|
|
||||||
returns (int256 quotedRate)
|
|
||||||
{
|
|
||||||
IDydx.Price memory price = dydx.getMarketPrice(marketId);
|
|
||||||
uint8 tokenDecimals = LibERC20Token.decimals(dydx.getMarketTokenAddress(marketId));
|
|
||||||
return D18.mul(D18.div(price.value, 10 ** uint256(tokenDecimals)), rate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Get the total supply and borrow values for an account across all markets.
|
/// @dev Get the total supply and borrow values for an account across all markets.
|
||||||
/// @param info State from `_getBalanceCheckInfo()`.
|
/// @param info State from `_getBalanceCheckInfo()`.
|
||||||
/// @param account The Dydx account identifier.
|
/// @param account The Dydx account identifier.
|
||||||
function _getAccountValues(BalanceCheckInfo memory info, uint256 account)
|
function _getAccountMarketValues(BalanceCheckInfo memory info, uint256 account)
|
||||||
private
|
private
|
||||||
view
|
view
|
||||||
returns (uint256 supplyValue, uint256 borrowValue)
|
returns (uint256 supplyValue, uint256 borrowValue)
|
||||||
@ -336,7 +381,9 @@ library LibDydxBalance {
|
|||||||
info.makerAddress,
|
info.makerAddress,
|
||||||
account
|
account
|
||||||
));
|
));
|
||||||
return (supplyValue_.value, borrowValue_.value);
|
// Account values have 36 decimal places because dydx likes to make sure
|
||||||
|
// you're paying attention.
|
||||||
|
return (supplyValue_.value / 1e18, borrowValue_.value / 1e18);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Get the amount of an ERC20 token held by `owner` that can be transferred
|
/// @dev Get the amount of an ERC20 token held by `owner` that can be transferred
|
||||||
|
@ -106,16 +106,6 @@ contract TestDydx {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMarketPrice(
|
|
||||||
uint256 marketId
|
|
||||||
)
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (IDydx.Price memory price)
|
|
||||||
{
|
|
||||||
return IDydx.Price(_markets[marketId].price);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAdjustedAccountValues(
|
function getAdjustedAccountValues(
|
||||||
IDydx.AccountInfo calldata account
|
IDydx.AccountInfo calldata account
|
||||||
)
|
)
|
||||||
@ -124,11 +114,13 @@ contract TestDydx {
|
|||||||
returns (IDydx.Value memory supplyValue, IDydx.Value memory borrowValue)
|
returns (IDydx.Value memory supplyValue, IDydx.Value memory borrowValue)
|
||||||
{
|
{
|
||||||
for (uint256 marketId = 0; marketId < _markets.length; ++marketId) {
|
for (uint256 marketId = 0; marketId < _markets.length; ++marketId) {
|
||||||
MarketInfo memory market = _markets[marketId];
|
|
||||||
int256 balance =
|
int256 balance =
|
||||||
_balance[_getBalanceHash(account.owner, account.number, marketId)];
|
_balance[_getBalanceHash(account.owner, account.number, marketId)];
|
||||||
uint256 decimals = LibERC20Token.decimals(market.token);
|
// Account values have 36 decimal places.
|
||||||
balance = balance * int256(market.price) / int256(10 ** decimals);
|
// `getMarketPrice()` returns a unit with
|
||||||
|
// 18 + (18 - TOKEN_DECIMALS) decimal places so multiplying the price
|
||||||
|
// with the wei balance will result in a 36 decimal value.
|
||||||
|
balance = balance * int256(getMarketPrice(marketId).value);
|
||||||
if (balance >= 0) {
|
if (balance >= 0) {
|
||||||
supplyValue.value += uint256(balance);
|
supplyValue.value += uint256(balance);
|
||||||
} else {
|
} else {
|
||||||
@ -137,6 +129,24 @@ contract TestDydx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMarketPrice(
|
||||||
|
uint256 marketId
|
||||||
|
)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (IDydx.Price memory price)
|
||||||
|
{
|
||||||
|
MarketInfo memory market = _markets[marketId];
|
||||||
|
uint256 decimals = LibERC20Token.decimals(market.token);
|
||||||
|
price.value = _markets[marketId].price;
|
||||||
|
// Market prices have 18 + (18 - TOKEN_DECIMALS)
|
||||||
|
if (decimals > 18) {
|
||||||
|
price.value /= 10 ** (decimals - 18);
|
||||||
|
} else {
|
||||||
|
price.value *= 10 ** (18 - decimals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function _getOperatorHash(address owner, address operator)
|
function _getOperatorHash(address owner, address operator)
|
||||||
private
|
private
|
||||||
pure
|
pure
|
||||||
|
@ -148,7 +148,7 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
makerAddress: string;
|
makerAddress: string;
|
||||||
makerTokenAddress: string;
|
makerTokenAddress: string;
|
||||||
takerTokenAddress: string;
|
takerTokenAddress: string;
|
||||||
orderTakerToMakerRate: BigNumber;
|
orderMakerToTakerRate: BigNumber;
|
||||||
accounts: BigNumber[];
|
accounts: BigNumber[];
|
||||||
actions: DydxBridgeAction[];
|
actions: DydxBridgeAction[];
|
||||||
}
|
}
|
||||||
@ -160,8 +160,8 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
makerAddress: ACCOUNT_OWNER,
|
makerAddress: ACCOUNT_OWNER,
|
||||||
makerTokenAddress: DYDX_CONFIG.markets[1].token,
|
makerTokenAddress: DYDX_CONFIG.markets[1].token,
|
||||||
takerTokenAddress: DYDX_CONFIG.markets[0].token,
|
takerTokenAddress: DYDX_CONFIG.markets[0].token,
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(
|
orderMakerToTakerRate: fromTokenUnitAmount(
|
||||||
fromTokenUnitAmount(5, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)),
|
fromTokenUnitAmount(10, TAKER_DECIMALS).div(fromTokenUnitAmount(5, MAKER_DECIMALS)),
|
||||||
),
|
),
|
||||||
accounts: [DYDX_CONFIG.accounts[SOLVENT_ACCOUNT_IDX].accountId],
|
accounts: [DYDX_CONFIG.accounts[SOLVENT_ACCOUNT_IDX].accountId],
|
||||||
actions: [],
|
actions: [],
|
||||||
@ -214,8 +214,9 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
|
|
||||||
// Computes a deposit rate that is the minimum to keep an account solvent
|
// Computes a deposit rate that is the minimum to keep an account solvent
|
||||||
// perpetually.
|
// perpetually.
|
||||||
function getBalancedDepositRate(withdrawRate: BigNumber, scaling: Numberish = 1.000001): BigNumber {
|
function getBalancedDepositRate(withdrawRate: BigNumber, scaling: Numberish = 1): BigNumber {
|
||||||
return withdrawRate.times((MAKER_PRICE / TAKER_PRICE) * MARGIN_RATIO).times(scaling);
|
// Add a small amount to the margin ratio to stay just above insolvency.
|
||||||
|
return withdrawRate.times((MAKER_PRICE / TAKER_PRICE) * (MARGIN_RATIO + 1.1e-4)).times(scaling);
|
||||||
}
|
}
|
||||||
|
|
||||||
function takerToMakerAmount(takerAmount: BigNumber): BigNumber {
|
function takerToMakerAmount(takerAmount: BigNumber): BigNumber {
|
||||||
@ -537,8 +538,8 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
blockchainTests.resets('_getDepositableMakerAmount()', () => {
|
blockchainTests.resets('_getDepositableMakerAmount()', () => {
|
||||||
it('returns infinite if no deposit action', async () => {
|
it('returns infinite if no deposit action', async () => {
|
||||||
const checkInfo = createBalanceCheckInfo({
|
const checkInfo = createBalanceCheckInfo({
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(
|
orderMakerToTakerRate: fromTokenUnitAmount(
|
||||||
fromTokenUnitAmount(100, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)),
|
fromTokenUnitAmount(10, TAKER_DECIMALS).div(fromTokenUnitAmount(100, MAKER_DECIMALS)),
|
||||||
),
|
),
|
||||||
actions: [],
|
actions: [],
|
||||||
});
|
});
|
||||||
@ -548,8 +549,8 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
|
|
||||||
it('returns infinite if deposit rate is zero', async () => {
|
it('returns infinite if deposit rate is zero', async () => {
|
||||||
const checkInfo = createBalanceCheckInfo({
|
const checkInfo = createBalanceCheckInfo({
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(
|
orderMakerToTakerRate: fromTokenUnitAmount(
|
||||||
fromTokenUnitAmount(100, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)),
|
fromTokenUnitAmount(10, TAKER_DECIMALS).div(fromTokenUnitAmount(100, MAKER_DECIMALS)),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
@ -567,8 +568,8 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
|
|
||||||
it('returns infinite if taker tokens cover the deposit rate', async () => {
|
it('returns infinite if taker tokens cover the deposit rate', async () => {
|
||||||
const checkInfo = createBalanceCheckInfo({
|
const checkInfo = createBalanceCheckInfo({
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(
|
orderMakerToTakerRate: fromTokenUnitAmount(
|
||||||
fromTokenUnitAmount(100, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)),
|
fromTokenUnitAmount(10, TAKER_DECIMALS).div(fromTokenUnitAmount(100, MAKER_DECIMALS)),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
@ -589,8 +590,8 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
const exchangeRate = 0.1;
|
const exchangeRate = 0.1;
|
||||||
const depositRate = Math.random() + exchangeRate;
|
const depositRate = Math.random() + exchangeRate;
|
||||||
const checkInfo = createBalanceCheckInfo({
|
const checkInfo = createBalanceCheckInfo({
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(
|
orderMakerToTakerRate: fromTokenUnitAmount(
|
||||||
fromTokenUnitAmount(1, MAKER_DECIMALS).div(fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS)),
|
fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS).div(fromTokenUnitAmount(1, MAKER_DECIMALS)),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
@ -623,7 +624,7 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
const checkInfo = createBalanceCheckInfo({
|
const checkInfo = createBalanceCheckInfo({
|
||||||
// The `takerTokenAddress` will be zero if the asset is not an ERC20.
|
// The `takerTokenAddress` will be zero if the asset is not an ERC20.
|
||||||
takerTokenAddress: constants.NULL_ADDRESS,
|
takerTokenAddress: constants.NULL_ADDRESS,
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(fromTokenUnitAmount(100, MAKER_DECIMALS)),
|
orderMakerToTakerRate: fromTokenUnitAmount(fromTokenUnitAmount(0.1, MAKER_DECIMALS)),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
actionType: DydxBridgeActionType.Deposit,
|
actionType: DydxBridgeActionType.Deposit,
|
||||||
@ -655,8 +656,8 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
takerTokenAddress: randomAddress(),
|
takerTokenAddress: randomAddress(),
|
||||||
// These amounts should be effectively ignored in the final computation
|
// These amounts should be effectively ignored in the final computation
|
||||||
// because the token being deposited is not the taker token.
|
// because the token being deposited is not the taker token.
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(
|
orderMakerToTakerRate: fromTokenUnitAmount(
|
||||||
fromTokenUnitAmount(100, MAKER_DECIMALS).div(fromTokenUnitAmount(10, TAKER_DECIMALS)),
|
fromTokenUnitAmount(10, TAKER_DECIMALS).div(fromTokenUnitAmount(100, MAKER_DECIMALS)),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
@ -676,8 +677,8 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
// The taker tokens getting exchanged in will only partially cover the deposit.
|
// The taker tokens getting exchanged in will only partially cover the deposit.
|
||||||
const exchangeRate = 0.1;
|
const exchangeRate = 0.1;
|
||||||
const checkInfo = createBalanceCheckInfo({
|
const checkInfo = createBalanceCheckInfo({
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(
|
orderMakerToTakerRate: fromTokenUnitAmount(
|
||||||
fromTokenUnitAmount(1, MAKER_DECIMALS).div(fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS)),
|
fromTokenUnitAmount(exchangeRate, TAKER_DECIMALS).div(fromTokenUnitAmount(1, MAKER_DECIMALS)),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
// Technically, deposits of the same token are not allowed, but the
|
// Technically, deposits of the same token are not allowed, but the
|
||||||
@ -733,7 +734,7 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
const exchangeRate = 0.1;
|
const exchangeRate = 0.1;
|
||||||
const depositRate = Math.random() + exchangeRate;
|
const depositRate = Math.random() + exchangeRate;
|
||||||
const checkInfo = createBalanceCheckInfo({
|
const checkInfo = createBalanceCheckInfo({
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(fromTokenUnitAmount(1 / exchangeRate, MAKER_DECIMALS)),
|
orderMakerToTakerRate: fromTokenUnitAmount(fromTokenUnitAmount(1 / exchangeRate, MAKER_DECIMALS)),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
actionType: DydxBridgeActionType.Deposit,
|
actionType: DydxBridgeActionType.Deposit,
|
||||||
@ -760,7 +761,7 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
const exchangeRate = 0.1;
|
const exchangeRate = 0.1;
|
||||||
const depositRate = Math.random() + exchangeRate;
|
const depositRate = Math.random() + exchangeRate;
|
||||||
const checkInfo = createBalanceCheckInfo({
|
const checkInfo = createBalanceCheckInfo({
|
||||||
orderTakerToMakerRate: fromTokenUnitAmount(fromTokenUnitAmount(1 / exchangeRate, MAKER_DECIMALS)),
|
orderMakerToTakerRate: fromTokenUnitAmount(fromTokenUnitAmount(1 / exchangeRate, MAKER_DECIMALS)),
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
actionType: DydxBridgeActionType.Deposit,
|
actionType: DydxBridgeActionType.Deposit,
|
||||||
@ -1155,8 +1156,8 @@ blockchainTests('LibDydxBalance', env => {
|
|||||||
actionType: DydxBridgeActionType.Withdraw,
|
actionType: DydxBridgeActionType.Withdraw,
|
||||||
accountIdx: new BigNumber(0),
|
accountIdx: new BigNumber(0),
|
||||||
marketId: new BigNumber(1),
|
marketId: new BigNumber(1),
|
||||||
conversionRateNumerator: new BigNumber(9e18),
|
conversionRateNumerator: new BigNumber(0.99e18),
|
||||||
conversionRateDenominator: new BigNumber(10e18),
|
conversionRateDenominator: new BigNumber(1e18),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user