@0x/contracts-integrations
: Add USDC->DAI forked dydx bridge order validation.
This commit is contained in:
parent
f9a7857a90
commit
a04722b612
@ -31,11 +31,12 @@ enum DydxAssetReference {
|
|||||||
Target = 1,
|
Target = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAKER_ADDRESS = '0x3a9F7C8cA36C42d7035E87C3304eE5cBd353a532';
|
const CHONKY_DAI_WALLET = '0x3a9F7C8cA36C42d7035E87C3304eE5cBd353a532';
|
||||||
|
const CHONKY_USDC_WALLET = '0x1EDA7056fF11C9817038E0020C3a6F1d6A8Ec32e';
|
||||||
|
|
||||||
blockchainTests.configure({
|
blockchainTests.configure({
|
||||||
fork: {
|
fork: {
|
||||||
unlockedAccounts: [MAKER_ADDRESS],
|
unlockedAccounts: [CHONKY_DAI_WALLET, CHONKY_USDC_WALLET],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -57,11 +58,10 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => {
|
|||||||
};
|
};
|
||||||
const DAI_DECIMALS = TOKEN_INFO[DAI_ADDRESS].decimals;
|
const DAI_DECIMALS = TOKEN_INFO[DAI_ADDRESS].decimals;
|
||||||
const USDC_DECIMALS = TOKEN_INFO[USDC_ADDRESS].decimals;
|
const USDC_DECIMALS = TOKEN_INFO[USDC_ADDRESS].decimals;
|
||||||
const DAI_MARKET_ID = TOKEN_INFO[DAI_ADDRESS].marketId;
|
|
||||||
const USDC_MARKET_ID = TOKEN_INFO[USDC_ADDRESS].marketId;
|
|
||||||
let bridge: DydxBridgeContract;
|
let bridge: DydxBridgeContract;
|
||||||
let dydx: IDydxContract;
|
let dydx: IDydxContract;
|
||||||
let dai: ERC20TokenContract;
|
let dai: ERC20TokenContract;
|
||||||
|
let usdc: ERC20TokenContract;
|
||||||
let devUtils: DevUtilsContract;
|
let devUtils: DevUtilsContract;
|
||||||
let accountOwner: string;
|
let accountOwner: string;
|
||||||
let minMarginRatio: number;
|
let minMarginRatio: number;
|
||||||
@ -70,6 +70,7 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => {
|
|||||||
[accountOwner] = await env.getAccountAddressesAsync();
|
[accountOwner] = await env.getAccountAddressesAsync();
|
||||||
dydx = new IDydxContract(DYDX_ADDRESS, env.provider, env.txDefaults);
|
dydx = new IDydxContract(DYDX_ADDRESS, env.provider, env.txDefaults);
|
||||||
dai = new ERC20TokenContract(DAI_ADDRESS, env.provider, env.txDefaults);
|
dai = new ERC20TokenContract(DAI_ADDRESS, env.provider, env.txDefaults);
|
||||||
|
usdc = new ERC20TokenContract(USDC_ADDRESS, env.provider, env.txDefaults);
|
||||||
bridge = await DydxBridgeContract.deployFrom0xArtifactAsync(
|
bridge = await DydxBridgeContract.deployFrom0xArtifactAsync(
|
||||||
assetProxyArtifacts.DydxBridge,
|
assetProxyArtifacts.DydxBridge,
|
||||||
env.provider,
|
env.provider,
|
||||||
@ -89,21 +90,36 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => {
|
|||||||
minMarginRatio = toTokenUnitAmount((await dydx.getRiskParams().callAsync()).marginRatio.value)
|
minMarginRatio = toTokenUnitAmount((await dydx.getRiskParams().callAsync()).marginRatio.value)
|
||||||
.plus(1)
|
.plus(1)
|
||||||
.toNumber();
|
.toNumber();
|
||||||
// Deposit Dai collateral.
|
// Set approvals and operators.
|
||||||
await dai.approve(DYDX_ADDRESS, constants.MAX_UINT256).awaitTransactionSuccessAsync({ from: MAKER_ADDRESS });
|
await dai
|
||||||
|
.approve(DYDX_ADDRESS, constants.MAX_UINT256)
|
||||||
|
.awaitTransactionSuccessAsync({ from: CHONKY_DAI_WALLET });
|
||||||
|
await usdc
|
||||||
|
.approve(DYDX_ADDRESS, constants.MAX_UINT256)
|
||||||
|
.awaitTransactionSuccessAsync({ from: CHONKY_USDC_WALLET });
|
||||||
await dydx
|
await dydx
|
||||||
.setOperators([{ operator: bridge.address, trusted: true }])
|
.setOperators([{ operator: bridge.address, trusted: true }])
|
||||||
.awaitTransactionSuccessAsync({ from: MAKER_ADDRESS });
|
.awaitTransactionSuccessAsync({ from: CHONKY_DAI_WALLET });
|
||||||
|
await dydx
|
||||||
|
.setOperators([{ operator: bridge.address, trusted: true }])
|
||||||
|
.awaitTransactionSuccessAsync({ from: CHONKY_USDC_WALLET });
|
||||||
});
|
});
|
||||||
|
|
||||||
async function depositAndWithdrawAsync(
|
async function depositAndWithdrawAsync(
|
||||||
|
makerAddress: string,
|
||||||
accountId: BigNumber,
|
accountId: BigNumber,
|
||||||
depositSize: Numberish = 0,
|
depositSize: Numberish = 0,
|
||||||
withdrawSize: Numberish = 0,
|
withdrawSize: Numberish = 0,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const fromToken = makerAddress === CHONKY_DAI_WALLET ? DAI_ADDRESS : USDC_ADDRESS;
|
||||||
|
const toToken = fromToken === DAI_ADDRESS ? USDC_ADDRESS : DAI_ADDRESS;
|
||||||
|
const fromDecimals = TOKEN_INFO[fromToken].decimals;
|
||||||
|
const fromMarketId = TOKEN_INFO[fromToken].marketId;
|
||||||
|
const toDecimals = TOKEN_INFO[toToken].decimals;
|
||||||
|
const toMarketId = TOKEN_INFO[toToken].marketId;
|
||||||
await dydx
|
await dydx
|
||||||
.operate(
|
.operate(
|
||||||
[{ owner: MAKER_ADDRESS, number: accountId }],
|
[{ owner: makerAddress, number: accountId }],
|
||||||
[
|
[
|
||||||
...(depositSize > 0
|
...(depositSize > 0
|
||||||
? [
|
? [
|
||||||
@ -114,11 +130,11 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => {
|
|||||||
sign: true,
|
sign: true,
|
||||||
denomination: DydxAssetDenomination.Wei,
|
denomination: DydxAssetDenomination.Wei,
|
||||||
ref: DydxAssetReference.Delta,
|
ref: DydxAssetReference.Delta,
|
||||||
value: fromTokenUnitAmount(depositSize, DAI_DECIMALS),
|
value: fromTokenUnitAmount(depositSize, fromDecimals),
|
||||||
},
|
},
|
||||||
primaryMarketId: new BigNumber(DAI_MARKET_ID),
|
primaryMarketId: new BigNumber(fromMarketId),
|
||||||
secondaryMarketId: new BigNumber(constants.NULL_ADDRESS),
|
secondaryMarketId: new BigNumber(constants.NULL_ADDRESS),
|
||||||
otherAddress: MAKER_ADDRESS,
|
otherAddress: makerAddress,
|
||||||
otherAccountIdx: ZERO,
|
otherAccountIdx: ZERO,
|
||||||
data: constants.NULL_BYTES,
|
data: constants.NULL_BYTES,
|
||||||
},
|
},
|
||||||
@ -133,11 +149,11 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => {
|
|||||||
sign: false,
|
sign: false,
|
||||||
denomination: DydxAssetDenomination.Wei,
|
denomination: DydxAssetDenomination.Wei,
|
||||||
ref: DydxAssetReference.Delta,
|
ref: DydxAssetReference.Delta,
|
||||||
value: fromTokenUnitAmount(withdrawSize, USDC_DECIMALS),
|
value: fromTokenUnitAmount(withdrawSize, toDecimals),
|
||||||
},
|
},
|
||||||
primaryMarketId: new BigNumber(USDC_MARKET_ID),
|
primaryMarketId: new BigNumber(toMarketId),
|
||||||
secondaryMarketId: new BigNumber(constants.NULL_ADDRESS),
|
secondaryMarketId: new BigNumber(constants.NULL_ADDRESS),
|
||||||
otherAddress: MAKER_ADDRESS,
|
otherAddress: makerAddress,
|
||||||
otherAccountIdx: ZERO,
|
otherAccountIdx: ZERO,
|
||||||
data: constants.NULL_BYTES,
|
data: constants.NULL_BYTES,
|
||||||
},
|
},
|
||||||
@ -145,7 +161,7 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => {
|
|||||||
: []),
|
: []),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.awaitTransactionSuccessAsync({ from: MAKER_ADDRESS });
|
.awaitTransactionSuccessAsync({ from: makerAddress });
|
||||||
}
|
}
|
||||||
|
|
||||||
const SECONDS_IN_ONE_YEAR = 365 * 24 * 60 * 60;
|
const SECONDS_IN_ONE_YEAR = 365 * 24 * 60 * 60;
|
||||||
@ -155,7 +171,7 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => {
|
|||||||
chainId: 1,
|
chainId: 1,
|
||||||
exchangeAddress: contractAddresses.exchange,
|
exchangeAddress: contractAddresses.exchange,
|
||||||
expirationTimeSeconds: new BigNumber(Math.floor(Date.now() / 1000 + SECONDS_IN_ONE_YEAR)),
|
expirationTimeSeconds: new BigNumber(Math.floor(Date.now() / 1000 + SECONDS_IN_ONE_YEAR)),
|
||||||
makerAddress: MAKER_ADDRESS,
|
makerAddress: CHONKY_DAI_WALLET,
|
||||||
takerAddress: constants.NULL_ADDRESS,
|
takerAddress: constants.NULL_ADDRESS,
|
||||||
senderAddress: constants.NULL_ADDRESS,
|
senderAddress: constants.NULL_ADDRESS,
|
||||||
feeRecipientAddress: constants.NULL_ADDRESS,
|
feeRecipientAddress: constants.NULL_ADDRESS,
|
||||||
@ -240,84 +256,199 @@ blockchainTests.fork('DevUtils dydx order validation tests', env => {
|
|||||||
return new BigNumber(hexUtils.random());
|
return new BigNumber(hexUtils.random());
|
||||||
}
|
}
|
||||||
|
|
||||||
it('validates a fully solvent order', async () => {
|
describe('DAI -> USDC', () => {
|
||||||
// This account is collateralized enough to fill the order with just
|
const makerAddress = CHONKY_DAI_WALLET;
|
||||||
// withdraws.
|
function _createOrder(fields: Partial<Order> = {}): Order {
|
||||||
const accountId = randomAccountId();
|
return createOrder(fields);
|
||||||
await depositAndWithdrawAsync(accountId, 200, 0);
|
}
|
||||||
const order = createOrder({
|
|
||||||
makerAssetData: encodeDydxBridgeAssetData({
|
it('validates a fully solvent order', async () => {
|
||||||
accountId,
|
// This account is collateralized enough to fill the order with just
|
||||||
depositRate: 0,
|
// withdraws.
|
||||||
}),
|
const accountId = randomAccountId();
|
||||||
|
await depositAndWithdrawAsync(makerAddress, accountId, 200, 0);
|
||||||
|
const order = _createOrder({
|
||||||
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
|
accountId,
|
||||||
|
depositRate: 0,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.eq(order.takerAssetAmount);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('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();
|
||||||
|
await depositAndWithdrawAsync(makerAddress, accountId, 1, 0);
|
||||||
|
const order = _createOrder({
|
||||||
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
|
accountId,
|
||||||
|
depositRate: minMarginRatio,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.eq(order.takerAssetAmount);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates a partially solvent order with an inadequate deposit', async () => {
|
||||||
|
// This account is not very well collateralized and the deposit rate is
|
||||||
|
// also too low to sustain the collateralization ratio for the full order.
|
||||||
|
const accountId = randomAccountId();
|
||||||
|
await depositAndWithdrawAsync(makerAddress, accountId, 1, 0);
|
||||||
|
const order = _createOrder({
|
||||||
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
|
accountId,
|
||||||
|
depositRate: minMarginRatio * 0.95,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.gt(0);
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.lt(order.takerAssetAmount);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates a partially solvent order with no deposit', async () => {
|
||||||
|
// This account is not very well collateralized and there is no deposit
|
||||||
|
// to keep the collateralization ratio up.
|
||||||
|
const accountId = randomAccountId();
|
||||||
|
await depositAndWithdrawAsync(makerAddress, accountId, 1, 0);
|
||||||
|
const order = _createOrder({
|
||||||
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
|
accountId,
|
||||||
|
depositRate: 0,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.gt(0);
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.lt(order.takerAssetAmount);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO(dorothy-zbornak): We can't actually create an account that's below
|
||||||
|
// the margin ratio without replacing the price oracles.
|
||||||
|
it('invalidates a virtually insolvent order', async () => {
|
||||||
|
// This account has a collateralization ratio JUST above the
|
||||||
|
// minimum margin ratio, so it can only withdraw nearly zero maker tokens.
|
||||||
|
const accountId = randomAccountId();
|
||||||
|
await depositAndWithdrawAsync(makerAddress, accountId, 1, 1 / (minMarginRatio + 3e-4));
|
||||||
|
const order = _createOrder({
|
||||||
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
|
accountId,
|
||||||
|
depositRate: 0,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
// Price fluctuations will cause this to be a little above zero, so we
|
||||||
|
// don't compare to zero.
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.lt(fromTokenUnitAmount(1e-3, DAI_DECIMALS));
|
||||||
});
|
});
|
||||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
|
||||||
expect(fillableTakerAssetAmount).to.bignumber.eq(order.takerAssetAmount);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it.only('validates a perpetually solvent order', async () => {
|
describe('USDC -> DAI', () => {
|
||||||
// This account is not very well collateralized, but the deposit rate
|
const makerAddress = CHONKY_USDC_WALLET;
|
||||||
// will keep the collateralization ratio the same or better.
|
function _createOrder(fields: Partial<Order> = {}): Order {
|
||||||
const accountId = randomAccountId();
|
return createOrder({
|
||||||
await depositAndWithdrawAsync(accountId, 1, 0);
|
makerAddress,
|
||||||
const order = createOrder({
|
takerAssetData: encodeERC20AssetData(USDC_ADDRESS),
|
||||||
makerAssetData: encodeDydxBridgeAssetData({
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
accountId,
|
fromToken: USDC_ADDRESS,
|
||||||
depositRate: minMarginRatio,
|
toToken: DAI_ADDRESS,
|
||||||
}),
|
}),
|
||||||
});
|
makerAssetAmount: fromTokenUnitAmount(100, DAI_DECIMALS),
|
||||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
takerAssetAmount: fromTokenUnitAmount(100, USDC_DECIMALS),
|
||||||
expect(fillableTakerAssetAmount).to.bignumber.eq(order.takerAssetAmount);
|
...fields,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
it('validates a partially solvent order with an inadequate deposit', async () => {
|
it('validates a fully solvent order', async () => {
|
||||||
// This account is not very well collateralized and the deposit rate is
|
// This account is collateralized enough to fill the order with just
|
||||||
// also too low to sustain the collateralization ratio for the full order.
|
// withdraws.
|
||||||
const accountId = randomAccountId();
|
const accountId = randomAccountId();
|
||||||
await depositAndWithdrawAsync(accountId, 1, 0);
|
await depositAndWithdrawAsync(makerAddress, accountId, 200, 0);
|
||||||
const order = createOrder({
|
const order = _createOrder({
|
||||||
makerAssetData: encodeDydxBridgeAssetData({
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
accountId,
|
accountId,
|
||||||
depositRate: minMarginRatio * 0.95,
|
depositRate: 0,
|
||||||
}),
|
fromToken: USDC_ADDRESS,
|
||||||
|
toToken: DAI_ADDRESS,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.eq(order.takerAssetAmount);
|
||||||
});
|
});
|
||||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
|
||||||
expect(fillableTakerAssetAmount).to.bignumber.gt(0);
|
|
||||||
expect(fillableTakerAssetAmount).to.bignumber.lt(order.takerAssetAmount);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('validates a partially solvent order with no deposit', async () => {
|
it('validates a perpetually solvent order', async () => {
|
||||||
// This account is not very well collateralized and there is no deposit
|
// This account is not very well collateralized, but the deposit rate
|
||||||
// to keep the collateralization ratio up.
|
// will keep the collateralization ratio the same or better.
|
||||||
const accountId = randomAccountId();
|
const accountId = randomAccountId();
|
||||||
await depositAndWithdrawAsync(accountId, 1, 0);
|
await depositAndWithdrawAsync(makerAddress, accountId, 1, 0);
|
||||||
const order = createOrder({
|
const order = _createOrder({
|
||||||
makerAssetData: encodeDydxBridgeAssetData({
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
accountId,
|
accountId,
|
||||||
depositRate: 0,
|
depositRate: minMarginRatio,
|
||||||
}),
|
fromToken: USDC_ADDRESS,
|
||||||
|
toToken: DAI_ADDRESS,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.eq(order.takerAssetAmount);
|
||||||
});
|
});
|
||||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
|
||||||
expect(fillableTakerAssetAmount).to.bignumber.gt(0);
|
|
||||||
expect(fillableTakerAssetAmount).to.bignumber.lt(order.takerAssetAmount);
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO(dorothy-zbornak): We can't actually create an account that's below
|
it('validates a partially solvent order with an inadequate deposit', async () => {
|
||||||
// the margin ratio without replacing the price oracles.
|
// This account is not very well collateralized and the deposit rate is
|
||||||
it('invalidates a virtually insolvent order', async () => {
|
// also too low to sustain the collateralization ratio for the full order.
|
||||||
// This account has a collateralization ratio JUST above the
|
const accountId = randomAccountId();
|
||||||
// minimum margin ratio, so it can only withdraw nearly zero maker tokens.
|
await depositAndWithdrawAsync(makerAddress, accountId, 1, 0);
|
||||||
const accountId = randomAccountId();
|
const order = _createOrder({
|
||||||
await depositAndWithdrawAsync(accountId, 1, 1 / (minMarginRatio + 3e-4));
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
const order = createOrder({
|
accountId,
|
||||||
makerAssetData: encodeDydxBridgeAssetData({
|
depositRate: minMarginRatio * 0.95,
|
||||||
accountId,
|
fromToken: USDC_ADDRESS,
|
||||||
depositRate: 0,
|
toToken: DAI_ADDRESS,
|
||||||
}),
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.gt(0);
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.lt(order.takerAssetAmount);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('validates a partially solvent order with no deposit', async () => {
|
||||||
|
// This account is not very well collateralized and there is no deposit
|
||||||
|
// to keep the collateralization ratio up.
|
||||||
|
const accountId = randomAccountId();
|
||||||
|
await depositAndWithdrawAsync(makerAddress, accountId, 1, 0);
|
||||||
|
const order = _createOrder({
|
||||||
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
|
accountId,
|
||||||
|
depositRate: 0,
|
||||||
|
fromToken: USDC_ADDRESS,
|
||||||
|
toToken: DAI_ADDRESS,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.gt(0);
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.lt(order.takerAssetAmount);
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO(dorothy-zbornak): We can't actually create an account that's below
|
||||||
|
// the margin ratio without replacing the price oracles.
|
||||||
|
it('invalidates a virtually insolvent order', async () => {
|
||||||
|
// This account has a collateralization ratio JUST above the
|
||||||
|
// minimum margin ratio, so it can only withdraw nearly zero maker tokens.
|
||||||
|
const accountId = randomAccountId();
|
||||||
|
await depositAndWithdrawAsync(makerAddress, accountId, 1, 1 / (minMarginRatio + 3e-4));
|
||||||
|
const order = _createOrder({
|
||||||
|
makerAssetData: encodeDydxBridgeAssetData({
|
||||||
|
accountId,
|
||||||
|
depositRate: 0,
|
||||||
|
fromToken: USDC_ADDRESS,
|
||||||
|
toToken: DAI_ADDRESS,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
||||||
|
// Price fluctuations will cause this to be a little above zero, so we
|
||||||
|
// don't compare to zero.
|
||||||
|
expect(fillableTakerAssetAmount).to.bignumber.lt(fromTokenUnitAmount(1e-3, USDC_DECIMALS));
|
||||||
});
|
});
|
||||||
const [, fillableTakerAssetAmount] = await devUtils.getOrderRelevantState(order, SIGNATURE).callAsync();
|
|
||||||
// Price fluctuations will cause this to be a little above zero, so we
|
|
||||||
// don't compare to zero.
|
|
||||||
expect(fillableTakerAssetAmount).to.bignumber.lt(fromTokenUnitAmount(1e-7, DAI_DECIMALS));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user